Skip to content

TokenStream::parse does not resolve with Span::call_site() #50050

Closed
@golddranks

Description

@golddranks

Updated description

The following procedural macro:

#![feature(proc_macro)]

extern crate proc_macro;

use proc_macro::*;

#[proc_macro]
pub fn foo(input: TokenStream) -> TokenStream {
    let mut body = Vec::<TokenTree>::new();

    // input = `let a = 2;`
    body.extend(input.into_iter());

    // manually add `let b = a;`
    body.push(Term::new("let", Span::call_site()).into());
    body.push(Term::new("b", Span::call_site()).into());
    body.push(Op::new('=', Spacing::Alone).into());
    body.push(Term::new("a", Span::call_site()).into());
    body.push(Op::new(';', Spacing::Alone).into());

    // parse and add `let c = b;`
    body.extend("let c = b;".parse::<TokenStream>().unwrap().into_iter());

    let mut ret = Vec::<TokenTree>::new();
    ret.push(Term::new("fn", Span::call_site()).into());
    ret.push(Term::new("main", Span::call_site()).into());
    ret.push(Group::new(Delimiter::Parenthesis, TokenStream::empty()).into());
    ret.push(Group::new(Delimiter::Brace, body.into_iter().collect()).into());
    ret.into_iter().collect()
}

fails when invoked as:

#![feature(proc_macro)]

extern crate foo;

foo::foo! {
    let a = 3;
}

with the error message:

error[E0425]: cannot find value `b` in this scope
 --> src/main.rs:6:1
  |
6 | / foo::foo! {
7 | |     let a = 3;
8 | | }
  | |_^ not found in this scope

error: aborting due to previous error

For more information about this error, try `rustc --explain E0425`.

Original description

Linking the futures-await crate and a crate that useserror-chain-derive together breaks the build. Here's a simple example: https://github.com/golddranks/test_futures_await_error_chain_derive Either of the two dependencies (futures-await and dotenv, which uses error-chain-derive) builds on its own (using the latest nightly), but together they refuse to build.

This seems to have something to do with the defsite hygiene: error-chain-derive is using derive macros 1.1, and the syntax for using it is as follows: (from https://github.com/purpliminal/rust-dotenv/blob/master/src/errors.rs )

#[derive(Debug, ErrorChain)]
#[cfg_attr(not(feature = "backtrace"), error_chain(backtrace = "false"))]
pub enum ErrorKind {
    // generic error string, required by derive_error_chain
    Msg(String),
    #[error_chain(custom)]
    #[error_chain(description = r#"|_| "Parsing Error""#)]
    #[error_chain(display = r#"|l| write!(f, "Error parsing line: '{}'", l)"#)]
    LineParse(String),
    #[error_chain(foreign)]
    Io(::std::io::Error),
    #[error_chain(foreign)]
    EnvVar(::std::env::VarError),
}

|l| write!(f, "Error parsing line: '{}'", l) breaks, because it can't find f: cannot find value f in this scope

It seems like just the presence of futures-await somehow affects how the Derive macros 1.1 hygiene works; however, the derive macros are stable, so this is an undesirable thing.

Metadata

Metadata

Assignees

Labels

A-decl-macros-1-2Area: Declarative macros 1.2A-decl-macros-2-0Area: Declarative macros 2.0 (#39412)C-bugCategory: This is a bug.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions