Files
rust/tests/run-make
Stuart Cook c3b51b3182 Rollup merge of #146874 - Enselic:multiple-adt-versions, r=jieyouxu
compiler: Hint at multiple crate versions if trait impl is for wrong ADT

If a user does e.g.

    impl From<Bar> for foo::Foo

and get a compilation error about that `From<Bar>` is not implemented for `Foo`, check if multiple versions of the crate with `Foo` is present in the dependency graph. If so, give a hint about it.

Note that a test is added as a separate commit so it is easy to see what effect the fix has on the emitted error message.

This can be seen as a continuation of rust-lang/rust#124944.

I think this closes RUST-71693 but I haven't checked since it lacks a minimal reproducer. If this gets merged I'll ask that reporter if this fix works for them.

## Real world example

I encountered this case in the wild and didn't realize I had multiple versions of a crate in my dependency graph. So I was a bit confused at first. For reference, here is what that looked like.

<details>
<summary>Click to expand</summary>

### Before fix

```
error[E0277]: the trait bound `lambda_http::lambda_runtime::Diagnostic: From<Error>` is not satisfied
   --> src/main.rs:73:5
    |
73  |     lambda_http::run(service_fn(handle_event)).await
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<Error>` is not implemented for `lambda_http::lambda_runtime::Diagnostic`
    |
    = help: the following other types implement trait `From<T>`:
              `lambda_http::lambda_runtime::Diagnostic` implements `From<&str>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<Box<dyn StdError + Send + Sync>>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<Box<dyn StdError>>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<Infallible>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<lambda_runtime::deserializer::DeserializeError>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<std::io::Error>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<std::string::String>`
    = note: required for `Error` to implement `Into<lambda_http::lambda_runtime::Diagnostic>`
note: required by a bound in `lambda_http::run`
   --> /home/martin/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lambda_http-0.17.0/src/lib.rs:199:26
    |
194 | pub async fn run<'a, R, S, E>(handler: S) -> Result<(), Error>
    |              --- required by a bound in this function
...
199 |     E: std::fmt::Debug + Into<Diagnostic>,
    |                          ^^^^^^^^^^^^^^^^ required by this bound in `run`

error[E0277]: the trait bound `lambda_http::lambda_runtime::Diagnostic: From<Error>` is not satisfied
   --> src/main.rs:73:48
    |
73  |     lambda_http::run(service_fn(handle_event)).await
    |                                                ^^^^^ the trait `From<Error>` is not implemented for `lambda_http::lambda_runtime::Diagnostic`
    |
    = help: the following other types implement trait `From<T>`:
              `lambda_http::lambda_runtime::Diagnostic` implements `From<&str>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<Box<dyn StdError + Send + Sync>>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<Box<dyn StdError>>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<Infallible>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<lambda_runtime::deserializer::DeserializeError>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<std::io::Error>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<std::string::String>`
    = note: required for `Error` to implement `Into<lambda_http::lambda_runtime::Diagnostic>`
note: required by a bound in `lambda_http::run`
   --> /home/martin/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lambda_http-0.17.0/src/lib.rs:199:26
    |
194 | pub async fn run<'a, R, S, E>(handler: S) -> Result<(), Error>
    |              --- required by a bound in this function
...
199 |     E: std::fmt::Debug + Into<Diagnostic>,
    |                          ^^^^^^^^^^^^^^^^ required by this bound in `run`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `auto-merge-dependabot-pull-requests-webhook` (bin "auto-merge-dependabot-pull-requests-webhook") due to 2 previous errors
```

### After fix

```
   Compiling auto-merge-dependabot-pull-requests-webhook v0.1.0 (/home/martin/src/auto-merge-dependabot-prs/rust-webhook)
error[E0277]: the trait bound `lambda_http::lambda_runtime::Diagnostic: From<Error>` is not satisfied
   --> src/main.rs:73:5
    |
 73 |     lambda_http::run(service_fn(handle_event)).await
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `From<Error>` is not implemented for `lambda_http::lambda_runtime::Diagnostic`
    |
help: item with same name found
   --> /home/martin/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lambda_runtime-0.13.0/src/diagnostic.rs:43:1
    |
 43 | pub struct Diagnostic {
    | ^^^^^^^^^^^^^^^^^^^^^
    = note: perhaps two different versions of crate `lambda_runtime` are being used?
    = help: the following other types implement trait `From<T>`:
              `lambda_http::lambda_runtime::Diagnostic` implements `From<&str>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<Box<dyn StdError + Send + Sync>>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<Box<dyn StdError>>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<Infallible>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<lambda_runtime::deserializer::DeserializeError>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<std::io::Error>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<std::string::String>`
    = note: required for `Error` to implement `Into<lambda_http::lambda_runtime::Diagnostic>`
note: required by a bound in `lambda_http::run`
   --> /home/martin/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lambda_http-0.17.0/src/lib.rs:199:26
    |
194 | pub async fn run<'a, R, S, E>(handler: S) -> Result<(), Error>
    |              --- required by a bound in this function
...
199 |     E: std::fmt::Debug + Into<Diagnostic>,
    |                          ^^^^^^^^^^^^^^^^ required by this bound in `run`

error[E0277]: the trait bound `lambda_http::lambda_runtime::Diagnostic: From<Error>` is not satisfied
   --> src/main.rs:73:48
    |
 73 |     lambda_http::run(service_fn(handle_event)).await
    |                                                ^^^^^ the trait `From<Error>` is not implemented for `lambda_http::lambda_runtime::Diagnostic`
    |
help: item with same name found
   --> /home/martin/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lambda_runtime-0.13.0/src/diagnostic.rs:43:1
    |
 43 | pub struct Diagnostic {
    | ^^^^^^^^^^^^^^^^^^^^^
    = note: perhaps two different versions of crate `lambda_runtime` are being used?
    = help: the following other types implement trait `From<T>`:
              `lambda_http::lambda_runtime::Diagnostic` implements `From<&str>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<Box<dyn StdError + Send + Sync>>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<Box<dyn StdError>>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<Infallible>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<lambda_runtime::deserializer::DeserializeError>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<std::io::Error>`
              `lambda_http::lambda_runtime::Diagnostic` implements `From<std::string::String>`
    = note: required for `Error` to implement `Into<lambda_http::lambda_runtime::Diagnostic>`
note: required by a bound in `lambda_http::run`
   --> /home/martin/.cargo/registry/src/index.crates.io-1949cf8c6b5b557f/lambda_http-0.17.0/src/lib.rs:199:26
    |
194 | pub async fn run<'a, R, S, E>(handler: S) -> Result<(), Error>
    |              --- required by a bound in this function
...
199 |     E: std::fmt::Debug + Into<Diagnostic>,
    |                          ^^^^^^^^^^^^^^^^ required by this bound in `run`

For more information about this error, try `rustc --explain E0277`.
error: could not compile `auto-merge-dependabot-pull-requests-webhook` (bin "auto-merge-dependabot-pull-requests-webhook") due to 2 previous errors
```

</details>

try-job: dist-various-1
try-job: aarch64-msvc-1
2025-10-06 21:20:08 +11:00
..
2024-06-07 11:12:04 +02:00
2025-08-06 16:55:50 +01:00
2024-08-15 15:44:29 +02:00
2024-07-17 13:34:18 +00:00
2024-07-29 08:26:52 +10:00
2024-06-25 14:27:43 -04:00
2024-07-18 09:28:30 -04:00
2024-07-17 13:34:18 +00:00
2025-07-08 16:40:10 +08:00
2025-08-13 09:42:46 +08:00
2025-08-13 09:42:46 +08:00
2025-08-13 09:42:46 +08:00
2024-07-17 13:34:18 +00:00
2024-07-17 13:34:18 +00:00
2024-07-17 13:34:18 +00:00
2025-02-08 22:12:13 +00:00
2024-07-29 08:26:52 +10:00
2025-03-02 05:56:56 +08:00

The run-make test suite

The run-make test suite contains tests which are the most flexible out of all the rust-lang/rust test suites. run-make tests can basically contain arbitrary code, and are supported by the run_make_support library.

Infrastructure

A run-make test is a test recipe source file rmake.rs accompanied by its parent directory (e.g. tests/run-make/foo/rmake.rs is the foo run-make test).

The implementation for collecting and building the rmake.rs recipes are in src/tools/compiletest/src/runtest.rs, in run_rmake_test.

The setup for the rmake.rs can be summarized as a 3-stage process:

  1. First, we build the run_make_support library in bootstrap as a tool lib.

  2. Then, we compile the rmake.rs "recipe" linking the support library and its dependencies in, and provide a bunch of env vars. We setup a directory structure within build/<target>/test/run-make/

    <test-name>/
        rmake.exe              # recipe binary
        rmake_out/             # sources from test sources copied over
    

    and copy non-rmake.rs input support files over to rmake_out/. The support library is made available as an extern prelude.

  3. Finally, we run the recipe binary and set rmake_out/ as the working directory.