Skip to content

Testing a proc macro may build with the wrong crates with -Zfeatures=all #8563

New issue

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

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

Already on GitHub? # to your account

Closed
alexcrichton opened this issue Jul 29, 2020 · 1 comment · Fixed by #8742
Closed

Testing a proc macro may build with the wrong crates with -Zfeatures=all #8563

alexcrichton opened this issue Jul 29, 2020 · 1 comment · Fixed by #8742
Labels
A-features2 Area: issues specifically related to the v2 feature resolver

Comments

@alexcrichton
Copy link
Member

This is unfortunately a bit of a complicated issue. This came up when we tested out using -Zfeatures=all on the wasmtime repository where we got an error that looked like:

error[E0277]: the trait bound `wiggle_generate::Config: syn::parse::Parse` is not satisfied
  --> crates/wiggle/macro/src/lib.rs:9:33
   |
9  |     parse_macro_input!(args2 as wiggle_generate::Config);
   |                                 ^^^^^^^^^^^^^^^^^^^^^^^ the trait `syn::parse::Parse` is not implemented for `wiggle_generate::Config`
   |
  ::: /home/alex/.cargo/registry/src/github.heygears.com-1ecc6299db9ec823/syn-1.0.34/src/parse_macro_input.rs:93:17
   |
93 | pub fn parse<T: ParseMacroInput>(token_stream: TokenStream) -> Result<T> {
   |                 --------------- required by this bound in `syn::parse_macro_input::parse`
   |
help: trait impl with same name found
  --> /home/alex/code/wasmtime/crates/wiggle/generate/src/lib.rs:3:1
   |
3  | / impl syn::parse::Parse for Config {
4  | |     fn parse(_: &syn::parse::ParseBuffer<'_>) -> syn::Result<Self> {
5  | |         panic!()
6  | |     }
7  | | }
   | |_^
   = note: perhaps two different versions of crate `syn` are being used?
   = note: required because of the requirements on the impl of `syn::parse_macro_input::ParseMacroInput` for `wiggle_generate::Config`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0277`.
error: could not compile `wiggle-macro`.

this is perplexing because it looks like Cargo's compiling something with the wrong version of syn, since there's two versions of syn in play and that shouldn't happen.

I was able to reduce this to a test:

#[cargo_test]
fn test_proc_macro() {
    let p = project()
        .file(
            "Cargo.toml",
            r#"
                [package]
                name = "runtime"
                version = "0.1.0"
                [dependencies]
                the-macro = { path = "the-macro", features = ['a'] }
                [build-dependencies]
                shared = { path = "shared", features = ['b'] }
            "#,
        )
        .file("src/lib.rs", "")
        .file(
            "the-macro/Cargo.toml",
            r#"
                [package]
                name = "the-macro"
                version = "0.1.0"
                [lib]
                proc-macro = true
                test = false
                [dependencies]
                the-macro-support = { path = "../the-macro-support" }
                shared = { path = "../shared" }
                [dev-dependencies]
                runtime = { path = ".." }
                [features]
                a = []
            "#,
        )
        .file(
            "the-macro/src/lib.rs",
            "
                fn _test() {
                    the_macro_support::foo(shared::Foo);
                }
            ",
        )
        .file(
            "the-macro-support/Cargo.toml",
            r#"
                [package]
                name = "the-macro-support"
                version = "0.1.0"
                [dependencies]
                shared = { path = "../shared" }
            "#,
        )
        .file(
            "the-macro-support/src/lib.rs",
            "
                pub fn foo(_: shared::Foo) {}
            ",
        )
        .file(
            "shared/Cargo.toml",
            r#"
                [package]
                name = "shared"
                version = "0.1.0"
                [features]
                b = []
            "#,
        )
        .file("shared/src/lib.rs", "pub struct Foo;")
        .build();
    p.cargo("test -Zfeatures=all --manifest-path the-macro/Cargo.toml")
        .masquerade_as_nightly_cargo()
        .run();
}

which yields:

---- features2::test_proc_macro stdout ----
running `/home/alex/code/cargo/target/debug/cargo test -Zfeatures=all --manifest-path the-macro/Cargo.toml`
thread 'features2::test_proc_macro' panicked at '
Expected: execs
    but: exited with exit code: 101
--- stdout

--- stderr
   Compiling shared v0.1.0 (/home/alex/code/cargo/target/cit/t0/foo/shared)
   Compiling the-macro-support v0.1.0 (/home/alex/code/cargo/target/cit/t0/foo/the-macro-support)
   Compiling the-macro v0.1.0 (/home/alex/code/cargo/target/cit/t0/foo/the-macro)
error[E0308]: mismatched types
 --> src/lib.rs:3:44
  |
3 |                     the_macro_support::foo(shared::Foo);
  |                                            ^^^^^^^^^^^ expected struct `shared::Foo`, found a different struct `shared::Foo`
  |
  = note: perhaps two different versions of crate `shared` are being used?

error: aborting due to previous error

For more information about this error, try `rustc --explain E0308`.
error: could not compile `the-macro`.

To learn more, run the command again with --verbose.
warning: build failed, waiting for other jobs to finish...
error: build failed
', crates/cargo-test-support/src/lib.rs:832:13
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace


failures:
    features2::test_proc_macro

cc @ehuss, you're likely interested in this!

@alexcrichton alexcrichton added the A-features2 Area: issues specifically related to the v2 feature resolver label Jul 29, 2020
@ehuss
Copy link
Contributor

ehuss commented Jul 31, 2020

This is a tricky one, somewhat the confluence of three different issues. The following is mostly notes to myself.

The primary issue is probably #8549. the-macro-support needs to be built twice (once for host, once without), but due to unit unification (without --target), it is only built once because the only difference is what it links to (shared with no features, and shared with feature B).

Another issue is this line. This forces proc-macros to be built for-host, even if it is a test. So the fix to above doesn't completely solve the issue.

Another issue is possibly #8312. proc-macros have some unusual requirements (like this). Not sure how this fits in the picture. There is some wonkiness around cargo test for proc-macros.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-features2 Area: issues specifically related to the v2 feature resolver
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants