Skip to content

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

Closed
@alexcrichton

Description

@alexcrichton

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.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!

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-features2Area: issues specifically related to the v2 feature resolver

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions