Skip to content

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

@MoSal

Description

@MoSal

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions