Skip to content

Commit 3ac20da

Browse files
committed
Distinguish crates with the same name in type errors
Previously, errors for crates with the same name would only distinguish them by the span of the source: ``` note: `HashMap<_, _, _, _>` is defined in crate `hashbrown` --> /Users/runner/.cargo/registry/src/index.crates.io-6f17d22bba15001f/hashbrown-0.12.3/src/map.rs:188:1 note: `HashMap<u32, u32>` is defined in crate `hashbrown` --> /Users/jyn/.local/lib/cargo/registry/src/index.crates.io-6f17d22bba15001f/hashbrown-0.12.3/src/map.rs:188:1 ``` When the same version of the crate is loaded twice, this isn't particularly helpful. Additionally show where the .rlib was loaded from (in this case one was loaded from the sysroot and the other from a cargo target dir).
1 parent 4b85902 commit 3ac20da

File tree

6 files changed

+78
-1
lines changed

6 files changed

+78
-1
lines changed

compiler/rustc_infer/src/infer/error_reporting/mod.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -1824,6 +1824,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
18241824
let expected_defid = expected_adt.did();
18251825

18261826
diagnostic.note(format!("{found_name} and {expected_name} have similar names, but are actually distinct types"));
1827+
let have_same_crate_name = self.tcx.crate_name(found_defid.krate) == self.tcx.crate_name(expected_defid.krate);
18271828
for (defid, name) in
18281829
[(found_defid, found_name), (expected_defid, expected_name)]
18291830
{
@@ -1843,7 +1844,15 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
18431844
format!("{name} is defined in the current crate")
18441845
} else {
18451846
let crate_name = self.tcx.crate_name(defid.krate);
1846-
format!("{name} is defined in crate `{crate_name}`")
1847+
diagnostic.span_note(def_span, format!("{name} is defined in crate `{crate_name}`"));
1848+
1849+
// If these are named the same, give a hint about why the compiler thinks they're different.
1850+
if have_same_crate_name {
1851+
let crate_paths = self.tcx.crate_extern_paths(defid.krate);
1852+
diagnostic.note(format!("`{crate_name}` was loaded from {}", crate_paths[0].display()));
1853+
}
1854+
1855+
continue;
18471856
};
18481857
diagnostic.span_note(def_span, msg);
18491858
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Test that we emit useful diagnostics when the same crate is loaded from the sysroot and --extern.
2+
# This can't be a run-make test because it needs the aux-file to itself have a dependency passed with --extern
3+
# (and just bare `--extern hashbrown` errors too early, while compiling `uses_hashbrown.rs`).
4+
5+
include ../tools.mk
6+
# s/hashbrown-[0-9.]\+/VERSION/;
7+
define SED_REGEX
8+
s#[^ ]*registry/src/index.crates.io[^ ]*/src#CARGO_REGISTRY/hashbrown-VERSION/src#;
9+
s#[^ ]*/build/[^ ]*/lib/rustlib/[^ ]*#BUILD_DIR/HOST/stageN/lib/rustlib/TARGET/lib/libhashbrown.rlib#;
10+
s#[^ ]*/build/[^ ]*/test/run-make/#BUILD_DIR/HOST/test/run-make/#
11+
s#[^ ]*tests/run-make/#TEST_DIR/#
12+
endef
13+
export SED_REGEX
14+
15+
all:
16+
$(RUSTC) hashbrown.rs --crate-type lib
17+
$(RUSTC) uses-hashbrown.rs --extern hashbrown=$(TMPDIR)/libhashbrown.rlib --crate-type lib
18+
$(RUSTC) mismatch.rs --extern uses_hashbrown=$(TMPDIR)/libuses_hashbrown.rlib 2>$(TMPDIR)/stderr.txt || true
19+
sed -e "$$SED_REGEX" < $(TMPDIR)/stderr.txt > $(TMPDIR)/normalized.txt
20+
$(RUSTC_TEST_OP) $(TMPDIR)/normalized.txt expected.txt
21+
$(CGREP) "loaded from" < $(TMPDIR)/stderr.txt
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
error[E0308]: mismatched types
2+
--> mismatch.rs:5:25
3+
|
4+
5 | uses_hashbrown::foo(hashbrown::HashMap::default())
5+
| ------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `HashMap<_, _>`, found `HashMap<_, _, _, _>`
6+
| |
7+
| arguments to this function are incorrect
8+
|
9+
= note: `hashbrown::HashMap<_, _, _, _>` and `hashbrown::HashMap<_, _>` have similar names, but are actually distinct types
10+
note: `hashbrown::HashMap<_, _, _, _>` is defined in crate `hashbrown`
11+
--> CARGO_REGISTRY/hashbrown-VERSION/src/map.rs:190:1
12+
|
13+
190 | pub struct HashMap<K, V, S = DefaultHashBuilder, A: Allocator = Global> {
14+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
15+
= note: `hashbrown` was loaded from BUILD_DIR/HOST/stageN/lib/rustlib/TARGET/lib/libhashbrown.rlib
16+
note: `hashbrown::HashMap<_, _>` is defined in crate `hashbrown`
17+
--> TEST_DIR/type-mismatch-sysroot-crate/hashbrown.rs:3:1
18+
|
19+
3 | pub struct HashMap<T, U>(PhantomData<(T, U)>);
20+
| ^^^^^^^^^^^^^^^^^^^^^^^^
21+
= note: `hashbrown` was loaded from BUILD_DIR/HOST/test/run-make/type-mismatch-sysroot-crate/type-mismatch-sysroot-crate/libhashbrown.rlib
22+
= note: perhaps two different versions of crate `hashbrown` are being used?
23+
note: function defined here
24+
--> TEST_DIR/type-mismatch-sysroot-crate/uses-hashbrown.rs:2:8
25+
|
26+
2 | pub fn foo<T, U>(_: hashbrown::HashMap<T, U>) {}
27+
| ^^^
28+
29+
error: aborting due to previous error
30+
31+
For more information about this error, try `rustc --explain E0308`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
use std::marker::PhantomData;
2+
3+
pub struct HashMap<T, U>(PhantomData<(T, U)>);
4+
impl<T, U> Default for HashMap<T, U> {
5+
fn default() -> Self {
6+
Self(PhantomData)
7+
}
8+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#![feature(rustc_private)]
2+
extern crate hashbrown;
3+
4+
fn main() {
5+
uses_hashbrown::foo(hashbrown::HashMap::default())
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// compile-flags:--extern hashbrown
2+
pub fn foo<T, U>(_: hashbrown::HashMap<T, U>) {}

0 commit comments

Comments
 (0)