@@ -78,6 +78,7 @@ use rustc_front::hir;
7878use rustc_front:: print:: pprust;
7979
8080use middle:: def;
81+ use middle:: def_id:: DefId ;
8182use middle:: infer;
8283use middle:: region;
8384use middle:: subst;
@@ -226,6 +227,8 @@ pub trait ErrorReporting<'tcx> {
226227
227228 fn report_type_error ( & self , trace : TypeTrace < ' tcx > , terr : & ty:: TypeError < ' tcx > ) ;
228229
230+ fn check_and_note_conflicting_crates ( & self , terr : & ty:: TypeError < ' tcx > , sp : Span ) ;
231+
229232 fn report_and_explain_type_error ( & self ,
230233 trace : TypeTrace < ' tcx > ,
231234 terr : & ty:: TypeError < ' tcx > ) ;
@@ -484,13 +487,60 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
484487 expected_found_str,
485488 terr) ;
486489
490+ self . check_and_note_conflicting_crates ( terr, trace. origin . span ( ) ) ;
491+
487492 match trace. origin {
488493 infer:: MatchExpressionArm ( _, arm_span) =>
489494 self . tcx . sess . span_note ( arm_span, "match arm with an incompatible type" ) ,
490495 _ => ( )
491496 }
492497 }
493498
499+ /// Adds a note if the types come from similarly named crates
500+ fn check_and_note_conflicting_crates ( & self , terr : & ty:: TypeError < ' tcx > , sp : Span ) {
501+ let report_path_match = |did1 : DefId , did2 : DefId | {
502+ // Only external crates, if either is from a local
503+ // module we could have false positives
504+ if !( did1. is_local ( ) || did2. is_local ( ) ) && did1. krate != did2. krate {
505+ let exp_path = self . tcx . with_path ( did1,
506+ |p| p. map ( |x| x. to_string ( ) )
507+ . collect :: < Vec < _ > > ( ) ) ;
508+ let found_path = self . tcx . with_path ( did2,
509+ |p| p. map ( |x| x. to_string ( ) )
510+ . collect :: < Vec < _ > > ( ) ) ;
511+ // We compare strings because PathMod and PathName can be different
512+ // for imported and non-imported crates
513+ if exp_path == found_path {
514+ let crate_name = self . tcx . sess . cstore
515+ . get_crate_data ( did1. krate ) . name ( ) ;
516+ self . tcx . sess . span_note ( sp, & format ! ( "Perhaps two different versions \
517+ of crate `{}` are being used?",
518+ crate_name) ) ;
519+ }
520+ }
521+ } ;
522+ match * terr {
523+ ty:: TypeError :: Sorts ( ref exp_found) => {
524+ // if they are both "path types", there's a chance of ambiguity
525+ // due to different versions of the same crate
526+ match ( & exp_found. expected . sty , & exp_found. found . sty ) {
527+ ( & ty:: TyEnum ( ref exp_adt, _) , & ty:: TyEnum ( ref found_adt, _) ) |
528+ ( & ty:: TyStruct ( ref exp_adt, _) , & ty:: TyStruct ( ref found_adt, _) ) |
529+ ( & ty:: TyEnum ( ref exp_adt, _) , & ty:: TyStruct ( ref found_adt, _) ) |
530+ ( & ty:: TyStruct ( ref exp_adt, _) , & ty:: TyEnum ( ref found_adt, _) ) => {
531+ report_path_match ( exp_adt. did , found_adt. did ) ;
532+ } ,
533+ _ => ( )
534+ }
535+ } ,
536+ ty:: TypeError :: Traits ( ref exp_found) => {
537+ self . tcx . sess . note ( "errrr0" ) ;
538+ report_path_match ( exp_found. expected , exp_found. found ) ;
539+ } ,
540+ _ => ( ) // FIXME(#22750) handle traits and stuff
541+ }
542+ }
543+
494544 fn report_and_explain_type_error ( & self ,
495545 trace : TypeTrace < ' tcx > ,
496546 terr : & ty:: TypeError < ' tcx > ) {
0 commit comments