diff options
| author | Esteban Küber <esteban@kuber.com.ar> | 2024-11-28 17:55:52 +0000 |
|---|---|---|
| committer | Josh Stone <jistone@redhat.com> | 2025-01-02 13:43:18 -0800 |
| commit | 21c75ad1ccc234b8cc2ffd23ed411b3a0da70833 (patch) | |
| tree | 93a26f18159e565d4398879f6339ac2677084fe9 | |
| parent | 0857a8e32cd55fca2e6c648e586f9ce46c22eb42 (diff) | |
| download | rust-21c75ad1ccc234b8cc2ffd23ed411b3a0da70833.tar.gz rust-21c75ad1ccc234b8cc2ffd23ed411b3a0da70833.zip | |
Do not call `extern_crate` on current trait on crate mismatch errors
When we encounter an error caused by traits/types of different versions of the same crate, filter out the current crate when collecting spans to add to the context so we don't call `extern_crate` on the `DefId` of the current crate, which is meaningless and ICEs.
Produced output with this filter:
```
error[E0277]: the trait bound `foo::Struct: Trait` is not satisfied
--> y.rs:13:19
|
13 | check_trait::<foo::Struct>();
| ^^^^^^^^^^^ the trait `Trait` is not implemented for `foo::Struct`
|
note: there are multiple different versions of crate `foo` in the dependency graph
--> y.rs:7:1
|
4 | extern crate foo;
| ----------------- one version of crate `foo` is used here, as a direct dependency of the current crate
5 |
6 | pub struct Struct;
| ----------------- this type implements the required trait
7 | pub trait Trait {}
| ^^^^^^^^^^^^^^^ this is the required trait
|
::: x.rs:4:1
|
4 | pub struct Struct;
| ----------------- this type doesn't implement the required trait
5 | pub trait Trait {}
| --------------- this is the found trait
= note: two types coming from two different versions of the same crate are different types even if they look the same
= help: you can use `cargo tree` to explore your dependency tree
note: required by a bound in `check_trait`
--> y.rs:10:19
|
10 | fn check_trait<T: Trait>() {}
| ^^^^^ required by this bound in `check_trait`
```
Fix #133563.
(cherry picked from commit 8574f374e2cc27b53c8b81dc4031c59ca3035284)
4 files changed, 56 insertions, 0 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 4e7d7b79ff4..20cef5e06a4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1732,6 +1732,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { span.push_span_label(self.tcx.def_span(trait_def_id), "this is the required trait"); for (sp, label) in [trait_def_id, other_trait_def_id] .iter() + // The current crate-version might depend on another version of the same crate + // (Think "semver-trick"). Do not call `extern_crate` in that case for the local + // crate as that doesn't make sense and ICEs (#133563). + .filter(|def_id| !def_id.is_local()) .filter_map(|def_id| self.tcx.extern_crate(def_id.krate)) .map(|data| { let dependency = if data.dependency_of == LOCAL_CRATE { diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/foo-current.rs b/tests/run-make/crate-loading-crate-depends-on-itself/foo-current.rs new file mode 100644 index 00000000000..71b27cd85bf --- /dev/null +++ b/tests/run-make/crate-loading-crate-depends-on-itself/foo-current.rs @@ -0,0 +1,14 @@ +#![crate_type = "lib"] +#![crate_name = "foo"] + +extern crate foo; + +pub struct Struct; +pub trait Trait {} +impl Trait for Struct {} + +fn check_trait<T: Trait>() {} + +fn ice() { + check_trait::<foo::Struct>(); +} diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/foo-prev.rs b/tests/run-make/crate-loading-crate-depends-on-itself/foo-prev.rs new file mode 100644 index 00000000000..19d3f3c972b --- /dev/null +++ b/tests/run-make/crate-loading-crate-depends-on-itself/foo-prev.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] +#![crate_name = "foo"] + +pub struct Struct; +pub trait Trait {} +impl Trait for Struct {} diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs b/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs new file mode 100644 index 00000000000..f52f3d791a7 --- /dev/null +++ b/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs @@ -0,0 +1,32 @@ +//@ only-linux +//@ ignore-wasm32 +//@ ignore-wasm64 +// ignore-tidy-linelength + +// Verify that if the current crate depends on a different version of the same crate, *and* types +// and traits of the different versions are mixed, we produce diagnostic output and not an ICE. +// #133563 + +use run_make_support::{rust_lib_name, rustc}; + +fn main() { + rustc().input("foo-prev.rs").run(); + + rustc() + .extra_filename("current") + .metadata("current") + .input("foo-current.rs") + .extern_("foo", rust_lib_name("foo")) + .run_fail() + .assert_stderr_contains(r#" +note: there are multiple different versions of crate `foo` in the dependency graph + --> foo-current.rs:7:1 + | +4 | extern crate foo; + | ----------------- one version of crate `foo` is used here, as a direct dependency of the current crate +5 | +6 | pub struct Struct; + | ----------------- this type implements the required trait +7 | pub trait Trait {} + | ^^^^^^^^^^^^^^^ this is the required trait"#); +} |
