Skip to content

Running cargo test with proc macro that uses main fails #62127

Description

@DoumanAsh

Attempting to run test with proc macro that uses main as identifier fails with following error:

error[E0659]: `main` is ambiguous (built-in attribute vs any other name)
  |
  = note: `main` could refer to a built-in attribute
note: `main` could also refer to the crate-local procedural macro defined here
 --> tokio-macros\src\lib.rs:26:1
  |
26| / pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
27| |     let input = syn::parse_macro_input!(item as syn::ItemFn);
28| |
29| |     let ret = &input.decl.output;
... |
41| |     result.into()
42| | }
  | |_^
  = help: use `crate::main` to refer to this crate-local procedural macro unambiguously

Rustc version:rustc 1.37.0-nightly (8aa42ed7c 2019-06-24)

But it seems it wasn't present in rustc 1.35.0 (3c235d560 2019-05-20)

UPD: It is present since (400b409ef 2019-06-09) too

UPD 2: Might be always present as cargo test seems to inject own main

So something changed in the way such identifier is treated.

Code example:

/// ```
/// #[tokio_macros::main]
/// fn main() {
///     println!("Hello world");
/// }
/// ```
#[proc_macro_attribute]
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
    let input = syn::parse_macro_input!(item as syn::ItemFn);

    let ret = &input.decl.output;
    let name = &input.ident;
    let body = &input.block;
    let attrs = &input.attrs;

    let result = quote! {
        #(#attrs)*
        fn #name() #ret {
            #body
        }
    };

    result.into()
}

Activity

  1. added
    A-resolveArea: Name/path resolution done by `rustc_resolve` specifically
    C-bugCategory: This is a bug.
    T-compilerRelevant to the compiler team, which will review and decide on the PR/issue.
    on Jun 25, 2019
  2. Centril commented on Jun 27, 2019

    @Centril
    Contributor
  3. petrochenkov commented on Jun 27, 2019

    @petrochenkov
    Contributor

    Built-in attribute #[x] will conflict with any other attribute named x in scope due to issues that are hard to fix.
    This rule was in effect since macro modularization and stabilization of attribute macros.

    So, the regression here is that something injects a use of built-in attribute #[main] where it wasn't used previously.
    This may be an acceptable regression though, since it's equivalent to introducing a new built-in attribute and we are probably not going to stop introducing new built-in attributes.

  4. DoumanAsh commented on Jun 27, 2019

    @DoumanAsh
    Author

    I wasn't aware, but is there main attribute which used by compiler already?

    But I see the problem with name resolution despite using absolute path, if it is difficult/impossible to resolve it is not really critical

  5. petrochenkov commented on Jun 27, 2019

    @petrochenkov
    Contributor

    @DoumanAsh

    I wasn't aware, but is there main attribute which used by compiler already?

    Yes, it turns an arbitrary function into main.

    #![feature(main)]
    
    #[main]
    fn not_named_main() {
        println!("Hello");
    }
    
    --- Output
    
    Hello

    https://play.rust-lang.org/?version=nightly&mode=debug&edition=2018&gist=e53c20462ac85fb770709af2551bde4f

  6. DoumanAsh commented on Jun 27, 2019

    @DoumanAsh
    Author

    @petrochenkov So does the issue boils down to resolution of attribute then?
    Or should any usage of builtin attribute fail regardless of used path to access it

  7. petrochenkov commented on Jun 27, 2019

    @petrochenkov
    Contributor

    @DoumanAsh
    Only single-segment paths are ambiguous, an attribute macro named main can still be used if it's referred to by a module-relative path or renamed.

    // Ok.
     #[tokio_macros::main]
    fn foo() {}
    
    // Ok.
    use tokio_macros::main as pain;
    #[pain]
    fn foo() {}
    
    // Not Ok, ambiguity.
    use tokio_macros::main;
    #[main]
    fn foo() {}
  8. DoumanAsh commented on Jun 27, 2019

    @DoumanAsh
    Author

    Ah but in my doctest it was #[tokio_macros::main] and it fails?
    So I assume by Ok you mean how it is supposed to be?

  9. petrochenkov commented on Jun 27, 2019

    @petrochenkov
    Contributor

    I suspect that #[tokio_macros::main] is irrelevant and the ambiguous #[main] is generated by the test harness, so this minimized example should also fail:

    /// ```
    /// fn main() {}
    /// ```
    #[proc_macro_attribute]
    pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
        item
    }
  10. DoumanAsh commented on Jun 28, 2019

    @DoumanAsh
    Author

    Yes, you are right, it seems the problem is with using main as name of attribute to define rather than with doc test itself

  11. pnkfelix commented on Jul 4, 2019

    @pnkfelix
    Contributor
  12. petrochenkov commented on Jul 8, 2019

    @petrochenkov
    Contributor

    Not a regression, the issue reproduces on Rust 1.30 already (the release that stabilized procedural macro attributes).

    Minimized example:

    // rustc --test
    
    #![crate_type = "proc-macro"]
    
    extern crate proc_macro;
    use proc_macro::*;
    
    #[proc_macro_attribute]
    pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
        item
    }

    As described above, the behavior is expected - the test harness uses the built-in #[main] attribute which becomes ambiguous if any other attribute named main is in scope.

  13. added 2 commits that reference this issue on Feb 9, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

A-resolveArea: Name/path resolution done by `rustc_resolve` specificallyP-highHigh priorityT-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