Skip to content

Span issues with FromStr in unstable proc_macro #48944

Description

@mystor

While writing improved tests for proc_macro2, I noticed some surprising behaviour of the FromStr impl for proc_macro::TokenStream.

When parsing a string with FromStr, a token parsed from the very beginning of the string can have a different source_file() than a token parsed elsewhere. For example:

let tokens = "aaa\nbbb".parse::<proc_macro::TokenStream>().unwrap().into_iter().collect::<Vec<_>>();
println!("span: {:?}", tokens[0].span);
println!("source_file: {:?}", tokens[0].span.source_file());
println!("");
println!("span: {:?}", tokens[1].span);
println!("source_file: {:?}", tokens[1].span.source_file());

Will produce the output:

span: Span(Span { lo: BytePos(6734829), hi: BytePos(6734832), ctxt: #0 })
source_file: SourceFile { path: ProcMacroSourceCode, is_real: false }

span: Span(Span { lo: BytePos(50), hi: BytePos(58), ctxt: #25 })
source_file: SourceFile { path: Real("pm_test.rs"), is_real: true }

I would've expected both tokens to have the same context, and similar BytePos-es. Specifically I would have expected both of these tokens to have a span located in a fake ProcMacroSourceCode file, but set to resolve in the context of the enclosing scope (as if span.resolved_at(Span::call_site()) was called).

Activity

  1. mystor commented on Mar 12, 2018

    @mystor
    ContributorAuthor

    I should note that adding a ' ' (space) character to the beginning of the string causes all tokens to have spans matching the second one.

  2. mystor commented on Mar 12, 2018

    @mystor
    ContributorAuthor

    I think the cause of the first-span-being-different issue is

    pub fn new(sess: &'a ParseSess, filemap: Lrc<syntax_pos::FileMap>) -> Self {
    let mut sr = StringReader::new_raw(sess, filemap);
    if sr.advance_token().is_err() {
    sr.emit_fatal_errors();
    FatalError.raise();
    }
    sr
    }
    , which causes the first token to be advanced-to and peeked at before the override_span is set here:
    srdr.override_span = override_span;

    The cause of the issue where all parsed tokens have the line and column of the input file instead of lines and columns into a fake proc-macro object seems to be caused by the way that override_span is used - namely how it overrides the entire span instead of just the expansion context.

  3. added
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    C-bugCategory: This is a bug.
    on May 14, 2018
  4. oskgo commented on Jan 25, 2024

    @oskgo
    Contributor

    @rustbot label +E-needs-test

    Does not reproduce anymore. A bisect reveals that it was fixed by #50924.

    The fix didn't add any tests.

  5. added
    E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.
    on Jan 25, 2024
  6. KaiTomotake commented on Feb 1, 2026

    @KaiTomotake
    Contributor

    @rustbot claim

  7. zakrad commented on Sep 15, 2026

    @zakrad
    Contributor

    @KaiTomotake you still on it? happy to push if you are not on it

  8. added a commit that references this issue on Sep 23, 2026
    ea4ccf9
  9. added a commit that references this issue on Sep 23, 2026
    204d0ab
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-decl-macros-2-0Area: Declarative macros 2.0 (#39412)C-bugCategory: This is a bug.E-needs-testCall for participation: An issue has been fixed and does not reproduce, but no test has been added.T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions