@@ -78,6 +78,7 @@ use rustc_front::hir;
78
78
use rustc_front:: print:: pprust;
79
79
80
80
use middle:: def;
81
+ use middle:: def_id:: DefId ;
81
82
use middle:: infer;
82
83
use middle:: region;
83
84
use middle:: subst;
@@ -226,6 +227,8 @@ pub trait ErrorReporting<'tcx> {
226
227
227
228
fn report_type_error ( & self , trace : TypeTrace < ' tcx > , terr : & ty:: TypeError < ' tcx > ) ;
228
229
230
+ fn check_and_note_conflicting_crates ( & self , terr : & ty:: TypeError < ' tcx > , sp : Span ) ;
231
+
229
232
fn report_and_explain_type_error ( & self ,
230
233
trace : TypeTrace < ' tcx > ,
231
234
terr : & ty:: TypeError < ' tcx > ) ;
@@ -484,13 +487,60 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
484
487
expected_found_str,
485
488
terr) ;
486
489
490
+ self . check_and_note_conflicting_crates ( terr, trace. origin . span ( ) ) ;
491
+
487
492
match trace. origin {
488
493
infer:: MatchExpressionArm ( _, arm_span) =>
489
494
self . tcx . sess . span_note ( arm_span, "match arm with an incompatible type" ) ,
490
495
_ => ( )
491
496
}
492
497
}
493
498
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
+
494
544
fn report_and_explain_type_error ( & self ,
495
545
trace : TypeTrace < ' tcx > ,
496
546
terr : & ty:: TypeError < ' tcx > ) {
0 commit comments