Skip to content

Commit 3699c24

Browse files
author
mejrs
committed
Address feedback
1 parent 8477b9b commit 3699c24

File tree

10 files changed

+223
-49
lines changed

10 files changed

+223
-49
lines changed

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

Lines changed: 140 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1654,47 +1654,156 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16541654
),
16551655
Mismatch::Fixed(s) => (s.into(), s.into(), None),
16561656
};
1657-
let looks_similar = |e: ExpectedFound<Ty<'_>>| {
1658-
// We're only interested in adts
1659-
if let (Some(e), Some(f)) = (e.expected.ty_adt_def(), e.found.ty_adt_def()) {
1660-
// Only compare the last parts of the path.
1661-
// `whatever::Foo` is pretty similar to `blah::Foo`
1662-
let e_path = self.tcx.def_path(e.did()).data;
1663-
let f_path = self.tcx.def_path(f.did()).data;
1664-
if let (Some(e), Some(f)) = (e_path.last(), f_path.last()) {
1665-
return e.data == f.data;
1657+
1658+
enum Similar<'tcx> {
1659+
Adts(ty::AdtDef<'tcx>, ty::AdtDef<'tcx>),
1660+
PrimitiveFound(Ty<'tcx>, ty::AdtDef<'tcx>),
1661+
PrimitiveExpected(ty::AdtDef<'tcx>, Ty<'tcx>),
1662+
}
1663+
1664+
let primitive_sym = |kind: &_| match kind {
1665+
ty::Bool => Some(sym::bool),
1666+
ty::Char => Some(sym::char),
1667+
ty::Float(f) => match f {
1668+
ty::FloatTy::F32 => Some(sym::f32),
1669+
ty::FloatTy::F64 => Some(sym::f64),
1670+
},
1671+
ty::Int(f) => match f {
1672+
ty::IntTy::Isize => Some(sym::isize),
1673+
ty::IntTy::I8 => Some(sym::i8),
1674+
ty::IntTy::I16 => Some(sym::i16),
1675+
ty::IntTy::I32 => Some(sym::i32),
1676+
ty::IntTy::I64 => Some(sym::i64),
1677+
ty::IntTy::I128 => Some(sym::i128),
1678+
},
1679+
ty::Uint(f) => match f {
1680+
ty::UintTy::Usize => Some(sym::usize),
1681+
ty::UintTy::U8 => Some(sym::u8),
1682+
ty::UintTy::U16 => Some(sym::u16),
1683+
ty::UintTy::U32 => Some(sym::u32),
1684+
ty::UintTy::U64 => Some(sym::u64),
1685+
ty::UintTy::U128 => Some(sym::u128),
1686+
},
1687+
_ => None,
1688+
};
1689+
1690+
let similarity = |e: ExpectedFound<Ty<'tcx>>| {
1691+
let (fk, ek) = (e.found.kind(), e.expected.kind());
1692+
match (fk, ek) {
1693+
(
1694+
ty::Adt(adt, _),
1695+
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_),
1696+
) => {
1697+
let path = self.tcx.def_path(adt.did()).data;
1698+
let name = path.last().unwrap().data.get_opt_name();
1699+
let prim_sym = primitive_sym(ek);
1700+
1701+
if name == prim_sym {
1702+
return Some(Similar::PrimitiveExpected(*adt, e.expected));
1703+
}
1704+
None
1705+
}
1706+
(
1707+
ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Float(_),
1708+
ty::Adt(adt, _),
1709+
) => {
1710+
let path = self.tcx.def_path(adt.did()).data;
1711+
let name = path.last().unwrap().data.get_opt_name();
1712+
let prim_sym = primitive_sym(fk);
1713+
1714+
if name == prim_sym {
1715+
return Some(Similar::PrimitiveFound(e.expected, *adt));
1716+
}
1717+
None
1718+
}
1719+
(ty::Adt(f, _), ty::Adt(e, _)) => {
1720+
if !f.did().is_local() && f.did().krate == e.did().krate {
1721+
// Most likely types from different versions of the same crate
1722+
// are in play, in which case this message isn't so helpful.
1723+
// A "perhaps two different versions..." error is already emitted for that.
1724+
return None;
1725+
}
1726+
let e_path = self.tcx.def_path(e.did()).data;
1727+
let f_path = self.tcx.def_path(f.did()).data;
1728+
if let (Some(e_last), Some(f_last)) = (e_path.last(), f_path.last()) && e_last == f_last {
1729+
return Some(Similar::Adts(*f, *e));
1730+
}
1731+
None
16661732
}
1733+
_ => None,
16671734
}
1668-
false
16691735
};
16701736

16711737
match terr {
16721738
// If two types mismatch but have similar names, mention that specifically.
1673-
TypeError::Sorts(values) if looks_similar(values) => {
1674-
let found_adt = values.found.ty_adt_def().unwrap();
1675-
let expected_adt = values.expected.ty_adt_def().unwrap();
1676-
1677-
let found_name = values.found.sort_string(self.tcx);
1678-
let expected_name = values.expected.sort_string(self.tcx);
1739+
TypeError::Sorts(values) if let Some(s) = similarity(values) => {
1740+
let diagnose_primitive =
1741+
|prim: Ty<'tcx>,
1742+
shadow: Ty<'tcx>,
1743+
defid: DefId,
1744+
diagnostic: &mut Diagnostic| {
1745+
let name = shadow.sort_string(self.tcx);
1746+
diagnostic.note(format!(
1747+
"{prim} and {name} have similar names, but are actually distinct types"
1748+
));
1749+
diagnostic
1750+
.note(format!("{prim} is a primitive defined by the language"));
1751+
let def_span = self.tcx.def_span(defid);
1752+
let msg = if defid.is_local() {
1753+
format!("{name} is defined in the current crate")
1754+
} else {
1755+
let crate_name = self.tcx.crate_name(defid.krate);
1756+
format!("{name} is defined in crate `{crate_name}")
1757+
};
1758+
diagnostic.span_note(def_span, msg);
1759+
};
16791760

1680-
diag.note(format!("{found_name} and {expected_name} have similar names, but are actually distinct types"));
1761+
let diagnose_adts =
1762+
|found_adt: ty::AdtDef<'tcx>,
1763+
expected_adt: ty::AdtDef<'tcx>,
1764+
diagnostic: &mut Diagnostic| {
1765+
let found_name = values.found.sort_string(self.tcx);
1766+
let expected_name = values.expected.sort_string(self.tcx);
16811767

1682-
for (adt, name) in [(found_adt, found_name), (expected_adt, expected_name)] {
1683-
let defid = adt.did();
1684-
let def_span = self.tcx.def_span(defid);
1768+
let found_defid = found_adt.did();
1769+
let expected_defid = expected_adt.did();
16851770

1686-
let msg = if defid.is_local() {
1687-
format!("{name} is defined in the current crate.")
1688-
} else if self.tcx.all_diagnostic_items(()).id_to_name.get(&defid).is_some()
1689-
{
1690-
// if it's a diagnostic item, it's definitely defined in std/core/alloc
1691-
// otherwise might be, might not be.
1692-
format!("{name} is defined in the standard library.")
1693-
} else {
1694-
let crate_name = self.tcx.crate_name(defid.krate);
1695-
format!("{name} is defined in crate `{crate_name}`.")
1771+
diagnostic.note(format!("{found_name} and {expected_name} have similar names, but are actually distinct types"));
1772+
for (defid, name) in
1773+
[(found_defid, found_name), (expected_defid, expected_name)]
1774+
{
1775+
let def_span = self.tcx.def_span(defid);
1776+
1777+
let msg = if found_defid.is_local() && expected_defid.is_local() {
1778+
let module = self
1779+
.tcx
1780+
.parent_module_from_def_id(defid.expect_local())
1781+
.to_def_id();
1782+
let module_name =
1783+
self.tcx.def_path(module).to_string_no_crate_verbose();
1784+
format!(
1785+
"{name} is defined in module {module_name} of the current crate"
1786+
)
1787+
} else if defid.is_local() {
1788+
format!("{name} is defined in the current crate")
1789+
} else {
1790+
let crate_name = self.tcx.crate_name(defid.krate);
1791+
format!("{name} is defined in crate `{crate_name}`")
1792+
};
1793+
diagnostic.span_note(def_span, msg);
1794+
}
16961795
};
1697-
diag.span_note(def_span, msg);
1796+
1797+
match s {
1798+
Similar::Adts(found_adt, expected_adt) => {
1799+
diagnose_adts(found_adt, expected_adt, diag)
1800+
}
1801+
Similar::PrimitiveFound(prim, e) => {
1802+
diagnose_primitive(prim, values.expected, e.did(), diag)
1803+
}
1804+
Similar::PrimitiveExpected(f, prim) => {
1805+
diagnose_primitive(prim, values.found, f.did(), diag)
1806+
}
16981807
}
16991808
}
17001809
TypeError::Sorts(values) => {

compiler/rustc_infer/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#![cfg_attr(bootstrap, feature(label_break_value))]
2121
#![feature(let_chains)]
2222
#![cfg_attr(bootstrap, feature(let_else))]
23+
#![feature(let_else)]
24+
#![feature(if_let_guard)]
2325
#![feature(min_specialization)]
2426
#![feature(never_type)]
2527
#![feature(try_blocks)]

src/test/ui/fully-qualified-type/fully-qualified-type-name2.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ LL | return x;
77
| ^ expected enum `y::Foo`, found enum `x::Foo`
88
|
99
= note: enum `x::Foo` and enum `y::Foo` have similar names, but are actually distinct types
10-
note: enum `x::Foo` is defined in the current crate.
10+
note: enum `x::Foo` is defined in module ::x of the current crate
1111
--> $DIR/fully-qualified-type-name2.rs:4:5
1212
|
1313
LL | pub enum Foo { }
1414
| ^^^^^^^^^^^^
15-
note: enum `y::Foo` is defined in the current crate.
15+
note: enum `y::Foo` is defined in module ::y of the current crate
1616
--> $DIR/fully-qualified-type-name2.rs:8:5
1717
|
1818
LL | pub enum Foo { }

src/test/ui/issues/issue-56943.stderr

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -5,18 +5,6 @@ LL | let _: issue_56943::S = issue_56943::S2;
55
| -------------- ^^^^^^^^^^^^^^^ expected struct `S`, found struct `S2`
66
| |
77
| expected due to this
8-
|
9-
= note: struct `S2` and struct `S` have similar names, but are actually distinct types
10-
note: struct `S2` is defined in crate `issue_56943`.
11-
--> $DIR/auxiliary/issue-56943.rs:2:9
12-
|
13-
LL | mod m { pub struct S; }
14-
| ^^^^^^^^^^^^
15-
note: struct `S` is defined in crate `issue_56943`.
16-
--> $DIR/auxiliary/issue-56943.rs:1:1
17-
|
18-
LL | pub struct S;
19-
| ^^^^^^^^^^^^
208

219
error: aborting due to previous error
2210

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
pub mod blah{
2+
pub mod baz{
3+
pub struct Foo;
4+
}
5+
}
6+
7+
pub mod meh{
8+
pub struct Foo;
9+
}
10+
11+
pub type Foo = blah::baz::Foo;
12+
13+
fn foo() -> Foo {
14+
meh::Foo
15+
//~^ ERROR mismatched types [E0308]
16+
}
17+
18+
fn main(){}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/show_module.rs:14:5
3+
|
4+
LL | fn foo() -> Foo {
5+
| --- expected `baz::Foo` because of return type
6+
LL | meh::Foo
7+
| ^^^^^^^^ expected struct `baz::Foo`, found struct `meh::Foo`
8+
|
9+
= note: struct `meh::Foo` and struct `baz::Foo` have similar names, but are actually distinct types
10+
note: struct `meh::Foo` is defined in module ::meh of the current crate
11+
--> $DIR/show_module.rs:8:5
12+
|
13+
LL | pub struct Foo;
14+
| ^^^^^^^^^^^^^^
15+
note: struct `baz::Foo` is defined in module ::blah::baz of the current crate
16+
--> $DIR/show_module.rs:3:9
17+
|
18+
LL | pub struct Foo;
19+
| ^^^^^^^^^^^^^^
20+
21+
error: aborting due to previous error
22+
23+
For more information about this error, try `rustc --explain E0308`.

src/test/ui/mismatched_types/similar_paths.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ LL | Some(42_u8)
77
| ^^^^^^^^^^^ expected enum `Option`, found enum `std::option::Option`
88
|
99
= note: enum `std::option::Option` and enum `Option` have similar names, but are actually distinct types
10-
note: enum `std::option::Option` is defined in the standard library.
10+
note: enum `std::option::Option` is defined in crate `core`
1111
--> $SRC_DIR/core/src/option.rs:LL:COL
1212
|
1313
LL | pub enum Option<T> {
1414
| ^^^^^^^^^^^^^^^^^^
15-
note: enum `Option` is defined in the current crate.
15+
note: enum `Option` is defined in the current crate
1616
--> $DIR/similar_paths.rs:1:1
1717
|
1818
LL | enum Option<T>{
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#![allow(non_camel_case_types)]
2+
3+
struct bool;
4+
5+
fn foo(_: bool) {}
6+
7+
fn main() {
8+
foo(true);
9+
//~^ ERROR mismatched types [E0308]
10+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
error[E0308]: mismatched types
2+
--> $DIR/similar_paths_primitive.rs:8:9
3+
|
4+
LL | foo(true);
5+
| --- ^^^^ expected struct `bool`, found `bool`
6+
| |
7+
| arguments to this function are incorrect
8+
|
9+
= note: bool and struct `bool` have similar names, but are actually distinct types
10+
= note: bool is a primitive defined by the language
11+
note: struct `bool` is defined in the current crate
12+
--> $DIR/similar_paths_primitive.rs:3:1
13+
|
14+
LL | struct bool;
15+
| ^^^^^^^^^^^
16+
note: function defined here
17+
--> $DIR/similar_paths_primitive.rs:5:4
18+
|
19+
LL | fn foo(_: bool) {}
20+
| ^^^ -------
21+
22+
error: aborting due to previous error
23+
24+
For more information about this error, try `rustc --explain E0308`.

src/test/ui/type/type-mismatch-same-crate-name.stderr

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,12 @@ LL | a::try_foo(foo2);
77
| arguments to this function are incorrect
88
|
99
= note: struct `main::a::Foo` and struct `main::a::Foo` have similar names, but are actually distinct types
10-
note: struct `main::a::Foo` is defined in crate `crate_a2`.
10+
note: struct `main::a::Foo` is defined in crate `crate_a2`
1111
--> $DIR/auxiliary/crate_a2.rs:1:1
1212
|
1313
LL | pub struct Foo;
1414
| ^^^^^^^^^^^^^^
15-
note: struct `main::a::Foo` is defined in crate `crate_a1`.
15+
note: struct `main::a::Foo` is defined in crate `crate_a1`
1616
--> $DIR/auxiliary/crate_a1.rs:1:1
1717
|
1818
LL | pub struct Foo;

0 commit comments

Comments
 (0)