about summary refs log tree commit diff
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2015-09-08 19:48:56 +0530
committerManish Goregaokar <manishsmail@gmail.com>2015-09-08 19:48:56 +0530
commit8b16eb832596d305f7da3f88c64aa35762fcba1e (patch)
treed649fbf37c86225a76757ff295eb1534616cf64c
parent7bf626a68045be1d1a4fac9a635113bb7775b6bb (diff)
downloadrust-8b16eb832596d305f7da3f88c64aa35762fcba1e.tar.gz
rust-8b16eb832596d305f7da3f88c64aa35762fcba1e.zip
Add note for when a type error comes from similarly named objects from two different crate of the same name (#22750)
-rw-r--r--src/librustc/middle/infer/error_reporting.rs37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs
index 8197ccf4be7..67357ab239f 100644
--- a/src/librustc/middle/infer/error_reporting.rs
+++ b/src/librustc/middle/infer/error_reporting.rs
@@ -226,6 +226,8 @@ pub trait ErrorReporting<'tcx> {
 
     fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &ty::TypeError<'tcx>);
 
+    fn check_and_note_conflicting_crates(&self, terr: &ty::TypeError<'tcx>, sp: Span);
+
     fn report_and_explain_type_error(&self,
                                      trace: TypeTrace<'tcx>,
                                      terr: &ty::TypeError<'tcx>);
@@ -484,6 +486,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                  expected_found_str,
                  terr);
 
+        self.check_and_note_conflicting_crates(terr, trace.origin.span());
+
         match trace.origin {
             infer::MatchExpressionArm(_, arm_span) =>
                 self.tcx.sess.span_note(arm_span, "match arm with an incompatible type"),
@@ -491,6 +495,39 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
         }
     }
 
+    /// Adds a note if the types come from similarly named crates
+    fn check_and_note_conflicting_crates(&self, terr: &ty::TypeError<'tcx>, sp: Span) {
+        match *terr {
+            ty::TypeError::Sorts(ref exp_found) => {
+                // if they are both "path types", there's a chance of ambiguity
+                // due to different versions of the same crate
+                match (&exp_found.expected.sty, &exp_found.found.sty) {
+                    (&ty::TyEnum(ref exp_adt, _), &ty::TyEnum(ref found_adt, _)) |
+                    (&ty::TyStruct(ref exp_adt, _), &ty::TyStruct(ref found_adt, _)) |
+                    (&ty::TyEnum(ref exp_adt, _), &ty::TyStruct(ref found_adt, _)) |
+                    (&ty::TyStruct(ref exp_adt, _), &ty::TyEnum(ref found_adt, _)) => {
+                        // Only external crates, if either is from a local
+                        // module we could have false positives
+                        if exp_adt.did.is_local() || found_adt.did.is_local() {
+                            return
+                        }
+                        let exp_path = self.tcx.with_path(exp_adt.did, 
+                                                          |p| p.collect::<Vec<_>>());
+                        let found_path = self.tcx.with_path(exp_adt.did, 
+                                                            |p| p.collect::<Vec<_>>());
+                        if exp_path == found_path {
+                            self.tcx.sess.span_note(sp, &format!("Perhaps two different versions \
+                                                                  of crate `{}` are being used?",
+                                                                  exp_path[0]));
+                        }
+                    },
+                    _ => ()
+                }
+            }
+            _ => () // FIXME(Manishearth) handle traits and stuff
+        }
+    }
+
     fn report_and_explain_type_error(&self,
                                      trace: TypeTrace<'tcx>,
                                      terr: &ty::TypeError<'tcx>) {