Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Span is bytes(0..0) in many error cases #482

Closed
MoSal opened this issue Sep 7, 2018 · 3 comments
Closed

Span is bytes(0..0) in many error cases #482

MoSal opened this issue Sep 7, 2018 · 3 comments

Comments

@MoSal
Copy link

MoSal commented Sep 7, 2018

Assume we have this trivial proc-macro-attribute:

extern crate proc_macro;
extern crate syn;

use proc_macro::TokenStream;
use syn::ImplItemMethod;
use syn::parse::Error as PError;


#[proc_macro_attribute]
pub fn dummy_attr(_: TokenStream, input: TokenStream) -> TokenStream {
    match check_if_impl_item_method(input.clone()) {
        Ok(()) => input,
        Err(e) => e.to_compile_error().into(),
    }
}

fn check_if_impl_item_method(input: TokenStream) -> Result<(), PError> {
    let err_msg = "dummy_attr only applies to methods in an impl block";
    match syn::parse::<ImplItemMethod>(input) {
        Ok(_) => Ok(()),
        Err(e) => {
            println!("span = {:?}", e.span());
            Err(PError::new(e.span(), err_msg))
        },
    }
}

If we try it on a struct, we get a useful span:

extern crate dummy_attr;

pub mod simple {
    use dummy_attr::dummy_attr;

    #[dummy_attr]
    pub struct Simple {
        num: i32,
    }
}

Compile error:

span = #0 bytes(102..108)
error: dummy_attr only applies to methods in an impl block
 --> src/lib.rs:7:9
  |
7 |     pub struct Simple {
  |         ^^^^^^

error: aborting due to previous error

But if we try it in other contexts like a module, an impl block, or a statement, the span is bytes(0..0).

For example:

extern crate dummy_attr;

pub mod simple {
    use dummy_attr::dummy_attr;

    pub struct Simple {
        num: i32,
    }

    #[dummy_attr]
    impl Simple {
        pub fn new(n: i32) -> Self {
            Self { num: n }
        }
    }
}

The error does not have a useful span:

span = #0 bytes(0..0)
error: dummy_attr only applies to methods in an impl block

error: aborting due to previous error
@dtolnay
Copy link
Owner

dtolnay commented Sep 7, 2018

Thanks, this is being tracked in rust-lang/rust#43081. For now attribute macros only receive a usable span if the input is formatted precisely the way that rustc's ugly-printer would format it. In this case if you write a trailing comma in Self { num: n, } then you'll see the span. This is a limitation in the compiler's current implementation of procedural macros.

error: dummy_attr only applies to methods in an impl block
  --> src/main.rs:11:5
   |
11 |     impl Simple {
   |     ^^^^

@MoSal
Copy link
Author

MoSal commented Sep 7, 2018

Thanks for pointing me to that issue. I suspected compiler limitations are at play.

The statement case might be a different bug though!

#![feature(proc_macro_expr)]
#![feature(stmt_expr_attributes)]

extern crate dummy_attr;

pub mod simple {
    use dummy_attr::dummy_attr;

    pub struct Simple {
        num: i32,
    }

    impl Simple {
        pub fn add_1(&mut self) { #[dummy_attr] self.num += 1; }
    }
}

@dtolnay
Copy link
Owner

dtolnay commented Oct 25, 2018

All the "spans are null when they shouldn't be" issues are ultimately a consequence of rust-lang/rust#43081. Closing in favor of that issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants