Skip to content

Commit ecdcb9d

Browse files
committed
Change error scheme so that if projection fails we generate A::B instead of TyError
Conflicts: src/test/compile-fail/issue-29857.rs
1 parent 2e48b59 commit ecdcb9d

File tree

9 files changed

+83
-10
lines changed

9 files changed

+83
-10
lines changed

src/librustc/middle/traits/project.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -426,11 +426,25 @@ fn opt_normalize_projection_type<'a,'b,'tcx>(
426426
}
427427
}
428428

429-
/// in various error cases, we just set TyError and return an obligation
430-
/// that, when fulfilled, will lead to an error.
429+
/// If we are projecting `<T as Trait>::Item`, but `T: Trait` does not
430+
/// hold. In various error cases, we cannot generate a valid
431+
/// normalized projection. Therefore, we create an inference variable
432+
/// return an associated obligation that, when fulfilled, will lead to
433+
/// an error.
431434
///
432-
/// FIXME: the TyError created here can enter the obligation we create,
433-
/// leading to error messages involving TyError.
435+
/// Note that we used to return `TyError` here, but that was quite
436+
/// dubious -- the premise was that an error would *eventually* be
437+
/// reported, when the obligation was processed. But in general once
438+
/// you see a `TyError` you are supposed to be able to assume that an
439+
/// error *has been* reported, so that you can take whatever heuristic
440+
/// paths you want to take. To make things worse, it was possible for
441+
/// cycles to arise, where you basically had a setup like `<MyType<$0>
442+
/// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0> as
443+
/// Trait>::Foo> to `[type error]` would lead to an obligation of
444+
/// `<MyType<[type error]> as Trait>::Foo`. We are supposed to report
445+
/// an error for this obligation, but we legitimately should not,
446+
/// because it contains `[type error]`. Yuck! (See issue #29857 for
447+
/// one case where this arose.)
434448
fn normalize_to_error<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
435449
projection_ty: ty::ProjectionTy<'tcx>,
436450
cause: ObligationCause<'tcx>,
@@ -441,8 +455,9 @@ fn normalize_to_error<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
441455
let trait_obligation = Obligation { cause: cause,
442456
recursion_depth: depth,
443457
predicate: trait_ref.to_predicate() };
458+
let new_value = selcx.infcx().next_ty_var();
444459
Normalized {
445-
value: selcx.tcx().types.err,
460+
value: new_value,
446461
obligations: vec!(trait_obligation)
447462
}
448463
}

src/librustc_typeck/check/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1059,6 +1059,9 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
10591059
t_cast: Ty<'tcx>,
10601060
t_expr: Ty<'tcx>,
10611061
id: ast::NodeId) {
1062+
if t_cast.references_error() || t_expr.references_error() {
1063+
return;
1064+
}
10621065
let tstr = fcx.infcx().ty_to_string(t_cast);
10631066
fcx.type_error_message(span, |actual| {
10641067
format!("cast to unsized type: `{}` as `{}`", actual, tstr)
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Coherence error results because we do not know whether `T: Foo<P>` or not
12+
// for the second impl.
13+
14+
use std::marker::PhantomData;
15+
16+
pub trait Foo<P> {}
17+
18+
impl <P, T: Foo<P>> Foo<P> for Option<T> {} //~ ERROR E0119
19+
20+
impl<T, U> Foo<T> for Option<U> { }
21+
22+
fn main() {}

src/test/compile-fail/const-eval-overflow-4b.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use std::{u8, u16, u32, u64, usize};
2222
const A_I8_T
2323
: [u32; (i8::MAX as i8 + 1u8) as usize]
2424
//~^ ERROR mismatched types
25-
//~| the trait `core::ops::Add<u8>` is not implemented for the type `i8`
25+
//~| ERROR the trait `core::ops::Add<u8>` is not implemented for the type `i8`
2626
= [0; (i8::MAX as usize) + 1];
2727

2828
fn main() {

src/test/compile-fail/issue-19692.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ struct Homura;
1212

1313
fn akemi(homura: Homura) {
1414
let Some(ref madoka) = Some(homura.kaname()); //~ ERROR no method named `kaname` found
15-
madoka.clone(); //~ ERROR the type of this value must be known in this context
15+
madoka.clone();
1616
}
1717

1818
fn main() { }

src/test/compile-fail/issue-21950.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,5 @@ fn main() {
1616
let x = &10 as
1717
&Add;
1818
//~^ ERROR the type parameter `RHS` must be explicitly specified in an object type because its default value `Self` references the type `Self`
19-
//~^^ ERROR the value of the associated type `Output` (from the trait `core::ops::Add`) must be specified
19+
//~| ERROR the value of the associated type `Output` (from the trait `core::ops::Add`) must be specified
2020
}

src/test/compile-fail/issue-23966.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,7 @@
99
// except according to those terms.
1010

1111
fn main() {
12-
"".chars().fold(|_, _| (), ()); //~ ERROR is not implemented for the type `()`
12+
"".chars().fold(|_, _| (), ());
13+
//~^ ERROR E0277
14+
//~| ERROR E0277
1315
}

src/test/compile-fail/issue-24352.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@
1010

1111
fn main() {
1212
1.0f64 - 1.0;
13-
1.0f64 - 1 //~ ERROR: is not implemented
13+
1.0f64 - 1 //~ ERROR E0277
1414
}

src/test/compile-fail/issue-29857.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
12+
#![feature(rustc_attrs)]
13+
14+
use std::marker::PhantomData;
15+
16+
pub trait Foo<P> {}
17+
18+
impl <P, T: Foo<P>> Foo<P> for Option<T> {}
19+
20+
pub struct Qux<T> (PhantomData<*mut T>);
21+
22+
impl<T> Foo<*mut T> for Option<Qux<T>> {}
23+
24+
pub trait Bar {
25+
type Output: 'static;
26+
}
27+
28+
impl<T: 'static, W: Bar<Output = T>> Foo<*mut T> for W {}
29+
30+
#[rustc_error]
31+
fn main() {} //~ ERROR compilation successful

0 commit comments

Comments
 (0)