mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
Note if mismatched types have a similar name
This commit is contained in:
parent
98ad6a5519
commit
8477b9b707
@ -51,6 +51,7 @@ use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePa
|
||||
|
||||
use crate::infer;
|
||||
use crate::infer::error_reporting::nice_region_error::find_anon_type::find_anon_type;
|
||||
use crate::infer::ExpectedFound;
|
||||
use crate::traits::error_reporting::report_object_safety_error;
|
||||
use crate::traits::{
|
||||
IfExpressionCause, MatchExpressionArmCause, ObligationCause, ObligationCauseCode,
|
||||
@ -1653,8 +1654,51 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
),
|
||||
Mismatch::Fixed(s) => (s.into(), s.into(), None),
|
||||
};
|
||||
match (&terr, expected == found) {
|
||||
(TypeError::Sorts(values), extra) => {
|
||||
let looks_similar = |e: ExpectedFound<Ty<'_>>| {
|
||||
// We're only interested in adts
|
||||
if let (Some(e), Some(f)) = (e.expected.ty_adt_def(), e.found.ty_adt_def()) {
|
||||
// Only compare the last parts of the path.
|
||||
// `whatever::Foo` is pretty similar to `blah::Foo`
|
||||
let e_path = self.tcx.def_path(e.did()).data;
|
||||
let f_path = self.tcx.def_path(f.did()).data;
|
||||
if let (Some(e), Some(f)) = (e_path.last(), f_path.last()) {
|
||||
return e.data == f.data;
|
||||
}
|
||||
}
|
||||
false
|
||||
};
|
||||
|
||||
match terr {
|
||||
// If two types mismatch but have similar names, mention that specifically.
|
||||
TypeError::Sorts(values) if looks_similar(values) => {
|
||||
let found_adt = values.found.ty_adt_def().unwrap();
|
||||
let expected_adt = values.expected.ty_adt_def().unwrap();
|
||||
|
||||
let found_name = values.found.sort_string(self.tcx);
|
||||
let expected_name = values.expected.sort_string(self.tcx);
|
||||
|
||||
diag.note(format!("{found_name} and {expected_name} have similar names, but are actually distinct types"));
|
||||
|
||||
for (adt, name) in [(found_adt, found_name), (expected_adt, expected_name)] {
|
||||
let defid = adt.did();
|
||||
let def_span = self.tcx.def_span(defid);
|
||||
|
||||
let msg = if defid.is_local() {
|
||||
format!("{name} is defined in the current crate.")
|
||||
} else if self.tcx.all_diagnostic_items(()).id_to_name.get(&defid).is_some()
|
||||
{
|
||||
// if it's a diagnostic item, it's definitely defined in std/core/alloc
|
||||
// otherwise might be, might not be.
|
||||
format!("{name} is defined in the standard library.")
|
||||
} else {
|
||||
let crate_name = self.tcx.crate_name(defid.krate);
|
||||
format!("{name} is defined in crate `{crate_name}`.")
|
||||
};
|
||||
diag.span_note(def_span, msg);
|
||||
}
|
||||
}
|
||||
TypeError::Sorts(values) => {
|
||||
let extra = expected == found;
|
||||
let sort_string = |ty: Ty<'tcx>| match (extra, ty.kind()) {
|
||||
(true, ty::Opaque(def_id, _)) => {
|
||||
let sm = self.tcx.sess.source_map();
|
||||
@ -1707,10 +1751,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
|
||||
);
|
||||
}
|
||||
}
|
||||
(TypeError::ObjectUnsafeCoercion(_), _) => {
|
||||
TypeError::ObjectUnsafeCoercion(_) => {
|
||||
diag.note_unsuccessful_coercion(found, expected);
|
||||
}
|
||||
(_, _) => {
|
||||
_ => {
|
||||
debug!(
|
||||
"note_type_err: exp_found={:?}, expected={:?} found={:?}",
|
||||
exp_found, expected, found
|
||||
|
@ -5,6 +5,18 @@ LL | fn bar(x: x::Foo) -> y::Foo {
|
||||
| ------ expected `y::Foo` because of return type
|
||||
LL | return x;
|
||||
| ^ expected enum `y::Foo`, found enum `x::Foo`
|
||||
|
|
||||
= note: enum `x::Foo` and enum `y::Foo` have similar names, but are actually distinct types
|
||||
note: enum `x::Foo` is defined in the current crate.
|
||||
--> $DIR/fully-qualified-type-name2.rs:4:5
|
||||
|
|
||||
LL | pub enum Foo { }
|
||||
| ^^^^^^^^^^^^
|
||||
note: enum `y::Foo` is defined in the current crate.
|
||||
--> $DIR/fully-qualified-type-name2.rs:8:5
|
||||
|
|
||||
LL | pub enum Foo { }
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
@ -5,6 +5,18 @@ LL | let _: issue_56943::S = issue_56943::S2;
|
||||
| -------------- ^^^^^^^^^^^^^^^ expected struct `S`, found struct `S2`
|
||||
| |
|
||||
| expected due to this
|
||||
|
|
||||
= note: struct `S2` and struct `S` have similar names, but are actually distinct types
|
||||
note: struct `S2` is defined in crate `issue_56943`.
|
||||
--> $DIR/auxiliary/issue-56943.rs:2:9
|
||||
|
|
||||
LL | mod m { pub struct S; }
|
||||
| ^^^^^^^^^^^^
|
||||
note: struct `S` is defined in crate `issue_56943`.
|
||||
--> $DIR/auxiliary/issue-56943.rs:1:1
|
||||
|
|
||||
LL | pub struct S;
|
||||
| ^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
11
src/test/ui/mismatched_types/similar_paths.rs
Normal file
11
src/test/ui/mismatched_types/similar_paths.rs
Normal file
@ -0,0 +1,11 @@
|
||||
enum Option<T>{
|
||||
Some(T),
|
||||
None,
|
||||
}
|
||||
|
||||
pub fn foo() -> Option<u8>{
|
||||
Some(42_u8)
|
||||
//~^ ERROR mismatched types [E0308]
|
||||
}
|
||||
|
||||
fn main(){}
|
23
src/test/ui/mismatched_types/similar_paths.stderr
Normal file
23
src/test/ui/mismatched_types/similar_paths.stderr
Normal file
@ -0,0 +1,23 @@
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/similar_paths.rs:7:5
|
||||
|
|
||||
LL | pub fn foo() -> Option<u8>{
|
||||
| ---------- expected `Option<u8>` because of return type
|
||||
LL | Some(42_u8)
|
||||
| ^^^^^^^^^^^ expected enum `Option`, found enum `std::option::Option`
|
||||
|
|
||||
= note: enum `std::option::Option` and enum `Option` have similar names, but are actually distinct types
|
||||
note: enum `std::option::Option` is defined in the standard library.
|
||||
--> $SRC_DIR/core/src/option.rs:LL:COL
|
||||
|
|
||||
LL | pub enum Option<T> {
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
note: enum `Option` is defined in the current crate.
|
||||
--> $DIR/similar_paths.rs:1:1
|
||||
|
|
||||
LL | enum Option<T>{
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
@ -6,6 +6,17 @@ LL | a::try_foo(foo2);
|
||||
| |
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
= note: struct `main::a::Foo` and struct `main::a::Foo` have similar names, but are actually distinct types
|
||||
note: struct `main::a::Foo` is defined in crate `crate_a2`.
|
||||
--> $DIR/auxiliary/crate_a2.rs:1:1
|
||||
|
|
||||
LL | pub struct Foo;
|
||||
| ^^^^^^^^^^^^^^
|
||||
note: struct `main::a::Foo` is defined in crate `crate_a1`.
|
||||
--> $DIR/auxiliary/crate_a1.rs:1:1
|
||||
|
|
||||
LL | pub struct Foo;
|
||||
| ^^^^^^^^^^^^^^
|
||||
= note: perhaps two different versions of crate `crate_a1` are being used?
|
||||
note: function defined here
|
||||
--> $DIR/auxiliary/crate_a1.rs:10:8
|
||||
|
Loading…
Reference in New Issue
Block a user