]> git.lizzy.rs Git - rust.git/commitdiff
switch projection errors to use the new type error messages
authorAriel Ben-Yehuda <ariel.byd@gmail.com>
Mon, 18 Jul 2016 22:02:47 +0000 (01:02 +0300)
committerAriel Ben-Yehuda <ariel.byd@gmail.com>
Fri, 22 Jul 2016 11:32:56 +0000 (14:32 +0300)
Unfortunately, projection errors do not come with a nice set of
mismatched types. This is because the type equality check occurs
within a higher-ranked context. Therefore, only the type error
is reported. This is ugly but was always the situation.

I will introduce better errors for the lower-ranked case in
another commit.

Fixes the last known occurence of #31173

src/librustc/infer/error_reporting.rs
src/librustc/macros.rs
src/librustc/traits/error_reporting.rs
src/librustc_typeck/check/compare_method.rs
src/test/compile-fail/associated-types-eq-3.rs
src/test/compile-fail/issue-31173.rs [new file with mode: 0644]

index be73818c8a4ebdea291bded641e3bb5e00e35d28..0726d8560bab949387d84d8d97893f371aa08d6a 100644 (file)
@@ -522,37 +522,46 @@ fn note_error_origin(&self,
     }
 
     pub fn report_and_explain_type_error_with_code(&self,
-                                                   trace: TypeTrace<'tcx>,
+                                                   origin: TypeOrigin,
+                                                   values: Option<ValuePairs<'tcx>>,
                                                    terr: &TypeError<'tcx>,
                                                    message: &str,
                                                    code: &str)
                                                    -> DiagnosticBuilder<'tcx>
     {
-        let (expected, found) = match self.values_str(&trace.values) {
-            Some((expected, found)) => (expected, found),
-            None => return self.tcx.sess.diagnostic().struct_dummy() /* derived error */
+        let expected_found = match values {
+            None => None,
+            Some(values) => match self.values_str(&values) {
+                Some((expected, found)) => Some((expected, found)),
+                None => return self.tcx.sess.diagnostic().struct_dummy() /* derived error */
+            }
         };
 
-        let span = trace.origin.span();
+        let span = origin.span();
+        let mut err = self.tcx.sess.struct_span_err_with_code(
+            span, message, code);
 
-        let is_simple_error = if let &TypeError::Sorts(ref values) = terr {
-            values.expected.is_primitive() && values.found.is_primitive()
-        } else {
-            false
-        };
+        let mut is_simple_error = false;
 
-        let mut err = self.tcx.sess.struct_span_err_with_code(
-            trace.origin.span(),
-            message,
-            code);
+        if let Some((expected, found)) = expected_found {
+            is_simple_error = if let &TypeError::Sorts(ref values) = terr {
+                values.expected.is_primitive() && values.found.is_primitive()
+            } else {
+                false
+            };
 
-        if !is_simple_error || check_old_school() {
-            err.note_expected_found(&"type", &expected, &found);
+            if !is_simple_error || check_old_school() {
+                err.note_expected_found(&"type", &expected, &found);
+            }
         }
 
-        err.span_label(span, &terr);
+        if !is_simple_error && check_old_school() {
+            err.span_note(span, &format!("{}", terr));
+        } else {
+            err.span_label(span, &terr);
+        }
 
-        self.note_error_origin(&mut err, &trace.origin);
+        self.note_error_origin(&mut err, &origin);
         self.check_and_note_conflicting_crates(&mut err, terr, span);
         self.tcx.note_and_explain_type_err(&mut err, terr, span);
 
@@ -566,7 +575,7 @@ pub fn report_and_explain_type_error(&self,
     {
         // FIXME: do we want to use a different error code for each origin?
         let failure_str = trace.origin.as_failure_str();
-        type_err!(self, trace, terr, E0308, "{}", failure_str)
+        type_err!(self, trace.origin, Some(trace.values), terr, E0308, "{}", failure_str)
     }
 
     /// Returns a string of the form "expected `{}`, found `{}`".
index 52420475db1002db565b5f9541caf5d338782cb8..190c9b665e0dda476bee1cf518595572ef6ed7f8 100644 (file)
@@ -62,11 +62,12 @@ macro_rules! span_bug {
 
 #[macro_export]
 macro_rules! type_err {
-    ($infcx:expr, $trace: expr, $terr: expr, $code:ident, $($message:tt)*) => ({
+    ($infcx:expr, $origin: expr, $values: expr, $terr: expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
         $infcx.report_and_explain_type_error_with_code(
-            $trace,
-            $terr,
+            $origin,
+            $values,
+            &$terr,
             &format!($($message)*),
             stringify!($code))
     })
index 3b9ecb88258540cd011bb543b07be1a8bd5145e7..afbe34f89bbf4758bfc480370399ef72a32ecd03 100644 (file)
@@ -26,7 +26,7 @@
 
 use fmt_macros::{Parser, Piece, Position};
 use hir::def_id::DefId;
-use infer::{InferCtxt};
+use infer::{InferCtxt, TypeOrigin};
 use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
 use ty::fast_reject;
 use ty::fold::TypeFolder;
@@ -117,10 +117,14 @@ fn report_projection_error(&self,
                             predicate,
                             error.err));
             } else {
-                let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271,
-                                               "type mismatch resolving `{}`: {}",
-                                               predicate,
-                                               error.err);
+                let mut err = type_err!(
+                    self,
+                    TypeOrigin::Misc(obligation.cause.span),
+                    None, // FIXME: be smarter
+                    error.err,
+                    E0271,
+                    "type mismatch resolving `{}`",
+                    predicate);
                 self.note_obligation_cause(&mut err, obligation);
                 err.emit();
             }
index 847dcc90ad395fdd3202a617ebbf955c08d863f6..2c4c6279076dc098528388278194feaa0b5b7a09 100644 (file)
@@ -12,6 +12,7 @@
 use rustc::infer::{self, InferOk, TypeOrigin};
 use rustc::ty;
 use rustc::traits::{self, ProjectionMode};
+use rustc::ty::error::ExpectedFound;
 use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace};
 
 use syntax::ast;
@@ -324,8 +325,11 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             debug!("sub_types failed: impl ty {:?}, trait ty {:?}",
                    impl_fty,
                    trait_fty);
-            let trace = infer::TypeTrace::types(origin, false, impl_fty, trait_fty);
-            type_err!(infcx, trace, &terr, E0053,
+            let values = Some(infer::ValuePairs::Types(ExpectedFound {
+                expected: trait_fty,
+                found: impl_fty
+            }));
+            type_err!(infcx, origin, values, terr, E0053,
                       "method `{}` has an incompatible type for trait",
                       trait_m.name).emit();
             return
index 8c66160e8a36f723c0a16c017d2956a83814f8fe..cb952f6534f0e57da26b0e45b6d91a14c64be083 100644 (file)
@@ -47,10 +47,8 @@ pub fn main() {
     let a = 42;
     foo1(a);
     //~^ ERROR type mismatch resolving
-    //~| expected usize
-    //~| found struct `Bar`
+    //~| expected usize, found struct `Bar`
     baz(&a);
     //~^ ERROR type mismatch resolving
-    //~| expected usize
-    //~| found struct `Bar`
+    //~| expected usize, found struct `Bar`
 }
diff --git a/src/test/compile-fail/issue-31173.rs b/src/test/compile-fail/issue-31173.rs
new file mode 100644 (file)
index 0000000..62d23a9
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::vec::IntoIter;
+
+pub fn get_tok(it: &mut IntoIter<u8>) {
+    let mut found_e = false;
+
+    let temp: Vec<u8> = it.take_while(|&x| {
+        found_e = true;
+        false
+    })
+        .cloned()
+        //~^ ERROR type mismatch resolving
+        //~| expected u8, found &-ptr
+        .collect(); //~ ERROR no method named `collect`
+}
+
+fn main() {}