@@ -51,6 +51,7 @@ use super::{InferCtxt, RegionVariableOrigin, SubregionOrigin, TypeTrace, ValuePa
51
51
52
52
use crate :: infer;
53
53
use crate :: infer:: error_reporting:: nice_region_error:: find_anon_type:: find_anon_type;
54
+ use crate :: infer:: ExpectedFound ;
54
55
use crate :: traits:: error_reporting:: report_object_safety_error;
55
56
use crate :: traits:: {
56
57
IfExpressionCause , MatchExpressionArmCause , ObligationCause , ObligationCauseCode ,
@@ -1653,8 +1654,51 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1653
1654
) ,
1654
1655
Mismatch :: Fixed ( s) => ( s. into ( ) , s. into ( ) , None ) ,
1655
1656
} ;
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;
1658
1702
let sort_string = |ty : Ty < ' tcx > | match ( extra, ty. kind ( ) ) {
1659
1703
( true , ty:: Opaque ( def_id, _) ) => {
1660
1704
let sm = self . tcx . sess . source_map ( ) ;
@@ -1707,10 +1751,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
1707
1751
) ;
1708
1752
}
1709
1753
}
1710
- ( TypeError :: ObjectUnsafeCoercion ( _ ) , _) => {
1754
+ TypeError :: ObjectUnsafeCoercion ( _) => {
1711
1755
diag. note_unsuccessful_coercion ( found, expected) ;
1712
1756
}
1713
- ( _ , _ ) => {
1757
+ _ => {
1714
1758
debug ! (
1715
1759
"note_type_err: exp_found={:?}, expected={:?} found={:?}" ,
1716
1760
exp_found, expected, found
0 commit comments