@@ -51,6 +51,7 @@ use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePa
5151
5252use crate :: infer;
5353use crate :: infer:: error_reporting:: nice_region_error:: find_anon_type:: find_anon_type;
54+ use crate :: infer:: ExpectedFound ;
5455use crate :: traits:: error_reporting:: report_object_safety_error;
5556use crate :: traits:: {
5657 IfExpressionCause , MatchExpressionArmCause , ObligationCause , ObligationCauseCode ,
@@ -1653,8 +1654,51 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
16531654 ) ,
16541655 Mismatch :: Fixed ( s) => ( s. into ( ) , s. into ( ) , None ) ,
16551656 } ;
1656- match ( & terr, expected == found) {
1657- ( TypeError :: Sorts ( values) , extra) => {
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 ;
1666+ }
1667+ }
1668+ false
1669+ } ;
1670+
1671+ match terr {
1672+ // 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 ) ;
1679+
1680+ diag. note ( format ! ( "{found_name} and {expected_name} have similar names, but are actually distinct types" ) ) ;
1681+
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) ;
1685+
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}`." )
1696+ } ;
1697+ diag. span_note ( def_span, msg) ;
1698+ }
1699+ }
1700+ TypeError :: Sorts ( values) => {
1701+ let extra = expected == found;
16581702 let sort_string = |ty : Ty < ' tcx > | match ( extra, ty. kind ( ) ) {
16591703 ( true , ty:: Opaque ( def_id, _) ) => {
16601704 let sm = self . tcx . sess . source_map ( ) ;
@@ -1707,10 +1751,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
17071751 ) ;
17081752 }
17091753 }
1710- ( TypeError :: ObjectUnsafeCoercion ( _ ) , _) => {
1754+ TypeError :: ObjectUnsafeCoercion ( _) => {
17111755 diag. note_unsuccessful_coercion ( found, expected) ;
17121756 }
1713- ( _ , _ ) => {
1757+ _ => {
17141758 debug ! (
17151759 "note_type_err: exp_found={:?}, expected={:?} found={:?}" ,
17161760 exp_found, expected, found
0 commit comments