]> git.lizzy.rs Git - rust.git/commitdiff
Change error scheme so that if projection fails we generate `A::B` instead of `TyError`
authorNiko Matsakis <niko@alum.mit.edu>
Thu, 7 Jan 2016 18:51:16 +0000 (13:51 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Sat, 9 Jan 2016 01:20:02 +0000 (20:20 -0500)
src/librustc/middle/traits/project.rs
src/librustc_typeck/check/mod.rs
src/test/compile-fail/coherence-projection-conflict-ty-param.rs [new file with mode: 0644]
src/test/compile-fail/const-eval-overflow-4b.rs
src/test/compile-fail/issue-19692.rs
src/test/compile-fail/issue-21950.rs
src/test/compile-fail/issue-23966.rs
src/test/compile-fail/issue-24352.rs
src/test/compile-fail/issue-29857.rs
src/test/compile-fail/issue-3973.rs

index ad3524661d326a4b8abb0023c97dae8292510073..e9d7b330d07acc17f15bbc29f093e63dd3812872 100644 (file)
@@ -426,11 +426,25 @@ fn opt_normalize_projection_type<'a,'b,'tcx>(
     }
 }
 
-/// in various error cases, we just set TyError and return an obligation
-/// that, when fulfilled, will lead to an error.
+/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
+/// hold. In various error cases, we cannot generate a valid
+/// normalized projection. Therefore, we create an inference variable
+/// return an associated obligation that, when fulfilled, will lead to
+/// an error.
 ///
-/// FIXME: the TyError created here can enter the obligation we create,
-/// leading to error messages involving TyError.
+/// Note that we used to return `TyError` here, but that was quite
+/// dubious -- the premise was that an error would *eventually* be
+/// reported, when the obligation was processed. But in general once
+/// you see a `TyError` you are supposed to be able to assume that an
+/// error *has been* reported, so that you can take whatever heuristic
+/// paths you want to take. To make things worse, it was possible for
+/// cycles to arise, where you basically had a setup like `<MyType<$0>
+/// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
+/// Trait>::Foo> to `[type error]` would lead to an obligation of
+/// `<MyType<[type error]> as Trait>::Foo`.  We are supposed to report
+/// an error for this obligation, but we legitimately should not,
+/// because it contains `[type error]`. Yuck! (See issue #29857 for
+/// one case where this arose.)
 fn normalize_to_error<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
                                projection_ty: ty::ProjectionTy<'tcx>,
                                cause: ObligationCause<'tcx>,
@@ -441,8 +455,9 @@ fn normalize_to_error<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
     let trait_obligation = Obligation { cause: cause,
                                         recursion_depth: depth,
                                         predicate: trait_ref.to_predicate() };
+    let new_value = selcx.infcx().next_ty_var();
     Normalized {
-        value: selcx.tcx().types.err,
+        value: new_value,
         obligations: vec!(trait_obligation)
     }
 }
index 3cf75483fea0f28bb17c466556fb79e2b9549dbb..dbc22bcde9ec749257469c0549575992c268b7a7 100644 (file)
@@ -1038,6 +1038,9 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                          t_cast: Ty<'tcx>,
                                          t_expr: Ty<'tcx>,
                                          id: ast::NodeId) {
+    if t_cast.references_error() || t_expr.references_error() {
+        return;
+    }
     let tstr = fcx.infcx().ty_to_string(t_cast);
     let mut err = fcx.type_error_struct(span, |actual| {
         format!("cast to unsized type: `{}` as `{}`", actual, tstr)
diff --git a/src/test/compile-fail/coherence-projection-conflict-ty-param.rs b/src/test/compile-fail/coherence-projection-conflict-ty-param.rs
new file mode 100644 (file)
index 0000000..6880f3e
--- /dev/null
@@ -0,0 +1,22 @@
+// 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.
+
+// Coherence error results because we do not know whether `T: Foo<P>` or not
+// for the second impl.
+
+use std::marker::PhantomData;
+
+pub trait Foo<P> {}
+
+impl <P, T: Foo<P>> Foo<P> for Option<T> {} //~ ERROR E0119
+
+impl<T, U> Foo<T> for Option<U> { }
+
+fn main() {}
index a8f47ab92e52950040606ebc5174b7e47d8373c0..253285d3919c21937c4c5ebb4ee90fdfc7eb6a44 100644 (file)
@@ -22,7 +22,7 @@
 const A_I8_T
     : [u32; (i8::MAX as i8 + 1u8) as usize]
     //~^ ERROR mismatched types
-    //~| the trait `core::ops::Add<u8>` is not implemented for the type `i8`
+    //~| ERROR the trait `core::ops::Add<u8>` is not implemented for the type `i8`
     = [0; (i8::MAX as usize) + 1];
 
 fn main() {
index 88ae0f835d0d724b69676800bd8199ca607618de..ca1715445e526e976f3c8f10b67c09bc7e483b4f 100644 (file)
@@ -12,7 +12,7 @@
 
 fn akemi(homura: Homura) {
     let Some(ref madoka) = Some(homura.kaname()); //~ ERROR no method named `kaname` found
-    madoka.clone(); //~ ERROR the type of this value must be known in this context
+    madoka.clone();
 }
 
 fn main() { }
index 900ad5ce812e3dfb96018862da620d4a9a985c8f..ef6ce5c995bf3f91803e2c7362498f00138d9750 100644 (file)
@@ -16,5 +16,5 @@ fn main() {
     let x = &10 as
             &Add;
             //~^ ERROR the type parameter `RHS` must be explicitly specified in an object type because its default value `Self` references the type `Self`
-            //~^^ ERROR the value of the associated type `Output` (from the trait `core::ops::Add`) must be specified
+            //~| ERROR the value of the associated type `Output` (from the trait `core::ops::Add`) must be specified
 }
index d7f909e4ebcf628bb7fa55009d7b9205be7303fe..7f9c7a292f2be0c7de7921b9ecbfcc483c35dabb 100644 (file)
@@ -9,5 +9,7 @@
 // except according to those terms.
 
 fn main() {
-    "".chars().fold(|_, _| (), ()); //~ ERROR is not implemented for the type `()`
+    "".chars().fold(|_, _| (), ());
+    //~^ ERROR E0277
+    //~| ERROR E0277
 }
index 9936f67b3af3c8e0908bfff2d03376c0d7725c77..4b0773140566c06fb1bf9923da9ac4b8715ef4ed 100644 (file)
@@ -10,5 +10,5 @@
 
 fn main() {
     1.0f64 - 1.0;
-    1.0f64 - 1 //~ ERROR: is not implemented
+    1.0f64 - 1 //~ ERROR E0277
 }
index b46246cd2164b68578f6fce94578ab2cb19abcf5..661579f52b6845e902544481cd873bfc03e76b0e 100644 (file)
@@ -8,11 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+
+#![feature(rustc_attrs)]
+
 use std::marker::PhantomData;
 
 pub trait Foo<P> {}
 
-impl <P, T: Foo<P>> Foo<P> for Option<T> {} //~ ERROR E0119
+impl <P, T: Foo<P>> Foo<P> for Option<T> {}
 
 pub struct Qux<T> (PhantomData<*mut T>);
 
@@ -24,4 +27,5 @@ pub trait Bar {
 
 impl<T: 'static, W: Bar<Output = T>> Foo<*mut T> for W {}
 
-fn main() {}
+#[rustc_error]
+fn main() {} //~ ERROR compilation successful
index 1fda423e9ee8d37ab30f2bafef90a2312ededdcd..92456760b0508971bef2f5cde9506564b39b7f89 100644 (file)
@@ -32,5 +32,4 @@ fn main() {
     let p = Point::new(0.0, 0.0);
     //~^ ERROR no associated item named `new` found for type `Point` in the current scope
     println!("{}", p.to_string());
-    //~^ ERROR the type of this value must be known in this context
 }