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

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

Closed
DoumanAsh opened this issue Jun 25, 2019 · 11 comments
Closed

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

DoumanAsh opened this issue Jun 25, 2019 · 11 comments
Assignees
Labels
A-resolve Area: Path resolution P-high High priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@DoumanAsh
Copy link

DoumanAsh commented Jun 25, 2019

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()
}
@jonas-schievink jonas-schievink added A-resolve Area: Path resolution C-bug Category: This is a bug. I-nominated regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Jun 25, 2019
@Centril
Copy link
Contributor

Centril commented Jun 27, 2019

cc @petrochenkov

@Centril Centril added the P-high High priority label Jun 27, 2019
@petrochenkov
Copy link
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.

@DoumanAsh
Copy link
Author

DoumanAsh commented Jun 27, 2019

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

@petrochenkov
Copy link
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

@DoumanAsh
Copy link
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

@petrochenkov
Copy link
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() {}

@DoumanAsh
Copy link
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?

@petrochenkov
Copy link
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
}

@DoumanAsh
Copy link
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

@pnkfelix
Copy link
Member

pnkfelix commented Jul 4, 2019

@rustbot assign @petrochenkov

@petrochenkov
Copy link
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.

@petrochenkov petrochenkov removed C-bug Category: This is a bug. regression-from-stable-to-nightly Performance or correctness regression from stable to nightly. labels Jul 8, 2019
rivy added a commit to uutils/uucore that referenced this issue May 24, 2020
…ion during testing

- proc_macro "main" collides with attribute "#[main]" during testing (for rust < v1.38.0; fixed in v1.38.0+)
- ref: GH:rust-lang/rust#62127
rivy added a commit to rivy/rs.coreutils that referenced this issue Nov 7, 2020
…ion during testing

- proc_macro "main" collides with attribute "#[main]" during testing (for rust < v1.38.0; fixed in v1.38.0+)
- ref: GH:rust-lang/rust#62127
rivy added a commit to rivy/rs.coreutils that referenced this issue Nov 9, 2020
…ion during testing

- proc_macro "main" collides with attribute "#[main]" during testing (for rust < v1.38.0; fixed in v1.38.0+)
- ref: GH:rust-lang/rust#62127
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Feb 9, 2022
…henkov

Complete removal of #[main] attribute from compiler

resolves rust-lang#93786

---

The `#[main]` attribute was mostly removed from the language in rust-lang#84217, but not completely. It is still recognized as a builtin attribute by the compiler, but it has no effect. However, this no-op attribute is no longer gated by `#[feature(main)]` (which no longer exists), so it's possible to include it in code *on stable* without any errors, which seems unintentional. For example, the following code is accepted ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&code=%23%5Bmain%5D%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22hello%20world%22)%3B%0A%7D%0A)).

```rust
#[main]
fn main() {
    println!("hello world");
}
```

Aside from that oddity, the existence of this attribute causes code like the following to fail ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&code=use%20tokio%3A%3Amain%3B%0A%0A%23%5Bmain%5D%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22hello%20world%22)%3B%0A%7D%0A)). According rust-lang#84062 (comment), the removal of `#[main]` was expected to eliminate this conflict (previously reported as rust-lang#62127).

```rust
use tokio::main;

#[main]
fn main() {
    println!("hello world");
}
```

```
error[E0659]: `main` is ambiguous
 --> src/main.rs:3:3
  |
3 | #[main]
  |   ^^^^ ambiguous name
  |
  = note: ambiguous because of a name conflict with a builtin attribute
  = note: `main` could refer to a built-in attribute
```

[This error message can be confusing](https://stackoverflow.com/q/71024443/1114), as the mostly-removed `#[main]` attribute is not mentioned in any documentation.

Since the current availability of `#[main]` on stable seems unintentional, and to needlessly block use of the `main` identifier in the attribute namespace, this PR finishes removing the `#[main]` attribute as described in rust-lang#29634 (comment) by deleting it from `builtin_attrs.rs`, and adds two test cases to ensure that the attribute is no longer accepted and no longer conflicts with other attributes imported as `main`.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Feb 9, 2022
…henkov

Complete removal of #[main] attribute from compiler

resolves rust-lang#93786

---

The `#[main]` attribute was mostly removed from the language in rust-lang#84217, but not completely. It is still recognized as a builtin attribute by the compiler, but it has no effect. However, this no-op attribute is no longer gated by `#[feature(main)]` (which no longer exists), so it's possible to include it in code *on stable* without any errors, which seems unintentional. For example, the following code is accepted ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&code=%23%5Bmain%5D%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22hello%20world%22)%3B%0A%7D%0A)).

```rust
#[main]
fn main() {
    println!("hello world");
}
```

Aside from that oddity, the existence of this attribute causes code like the following to fail ([playground link](https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&code=use%20tokio%3A%3Amain%3B%0A%0A%23%5Bmain%5D%0Afn%20main()%20%7B%0A%20%20%20%20println!(%22hello%20world%22)%3B%0A%7D%0A)). According rust-lang#84062 (comment), the removal of `#[main]` was expected to eliminate this conflict (previously reported as rust-lang#62127).

```rust
use tokio::main;

#[main]
fn main() {
    println!("hello world");
}
```

```
error[E0659]: `main` is ambiguous
 --> src/main.rs:3:3
  |
3 | #[main]
  |   ^^^^ ambiguous name
  |
  = note: ambiguous because of a name conflict with a builtin attribute
  = note: `main` could refer to a built-in attribute
```

[This error message can be confusing](https://stackoverflow.com/q/71024443/1114), as the mostly-removed `#[main]` attribute is not mentioned in any documentation.

Since the current availability of `#[main]` on stable seems unintentional, and to needlessly block use of the `main` identifier in the attribute namespace, this PR finishes removing the `#[main]` attribute as described in rust-lang#29634 (comment) by deleting it from `builtin_attrs.rs`, and adds two test cases to ensure that the attribute is no longer accepted and no longer conflicts with other attributes imported as `main`.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-resolve Area: Path resolution P-high High priority T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

6 participants