diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2016-01-07 13:51:16 -0500 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2016-01-08 20:20:02 -0500 |
| commit | 77756cb12ae718cd3b20c0da2b3b89c881910b1d (patch) | |
| tree | c8bc6bb721c26602594fdec954bfdf03bcac7fcc /src | |
| parent | 64b720229c1fc819db00a45d43a3a0815a3b5809 (diff) | |
| download | rust-77756cb12ae718cd3b20c0da2b3b89c881910b1d.tar.gz rust-77756cb12ae718cd3b20c0da2b3b89c881910b1d.zip | |
Change error scheme so that if projection fails we generate `A::B` instead of `TyError`
Diffstat (limited to 'src')
| -rw-r--r-- | src/librustc/middle/traits/project.rs | 25 | ||||
| -rw-r--r-- | src/librustc_typeck/check/mod.rs | 3 | ||||
| -rw-r--r-- | src/test/compile-fail/coherence-projection-conflict-ty-param.rs | 22 | ||||
| -rw-r--r-- | src/test/compile-fail/const-eval-overflow-4b.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-19692.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-21950.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-23966.rs | 4 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-24352.rs | 2 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-29857.rs | 8 | ||||
| -rw-r--r-- | src/test/compile-fail/issue-3973.rs | 1 |
10 files changed, 58 insertions, 13 deletions
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs index ad3524661d3..e9d7b330d07 100644 --- a/src/librustc/middle/traits/project.rs +++ b/src/librustc/middle/traits/project.rs @@ -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) } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 3cf75483fea..dbc22bcde9e 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -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 index 00000000000..6880f3e9a3c --- /dev/null +++ b/src/test/compile-fail/coherence-projection-conflict-ty-param.rs @@ -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() {} diff --git a/src/test/compile-fail/const-eval-overflow-4b.rs b/src/test/compile-fail/const-eval-overflow-4b.rs index a8f47ab92e5..253285d3919 100644 --- a/src/test/compile-fail/const-eval-overflow-4b.rs +++ b/src/test/compile-fail/const-eval-overflow-4b.rs @@ -22,7 +22,7 @@ use std::{u8, u16, u32, u64, usize}; 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() { diff --git a/src/test/compile-fail/issue-19692.rs b/src/test/compile-fail/issue-19692.rs index 88ae0f835d0..ca1715445e5 100644 --- a/src/test/compile-fail/issue-19692.rs +++ b/src/test/compile-fail/issue-19692.rs @@ -12,7 +12,7 @@ struct Homura; 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() { } diff --git a/src/test/compile-fail/issue-21950.rs b/src/test/compile-fail/issue-21950.rs index 900ad5ce812..ef6ce5c995b 100644 --- a/src/test/compile-fail/issue-21950.rs +++ b/src/test/compile-fail/issue-21950.rs @@ -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 } diff --git a/src/test/compile-fail/issue-23966.rs b/src/test/compile-fail/issue-23966.rs index d7f909e4ebc..7f9c7a292f2 100644 --- a/src/test/compile-fail/issue-23966.rs +++ b/src/test/compile-fail/issue-23966.rs @@ -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 } diff --git a/src/test/compile-fail/issue-24352.rs b/src/test/compile-fail/issue-24352.rs index 9936f67b3af..4b077314056 100644 --- a/src/test/compile-fail/issue-24352.rs +++ b/src/test/compile-fail/issue-24352.rs @@ -10,5 +10,5 @@ fn main() { 1.0f64 - 1.0; - 1.0f64 - 1 //~ ERROR: is not implemented + 1.0f64 - 1 //~ ERROR E0277 } diff --git a/src/test/compile-fail/issue-29857.rs b/src/test/compile-fail/issue-29857.rs index b46246cd216..661579f52b6 100644 --- a/src/test/compile-fail/issue-29857.rs +++ b/src/test/compile-fail/issue-29857.rs @@ -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 diff --git a/src/test/compile-fail/issue-3973.rs b/src/test/compile-fail/issue-3973.rs index 1fda423e9ee..92456760b05 100644 --- a/src/test/compile-fail/issue-3973.rs +++ b/src/test/compile-fail/issue-3973.rs @@ -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 } |
