Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[beta] Backport fix for issue 29857 #30847

Merged
merged 6 commits into from
Jan 12, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 20 additions & 5 deletions src/librustc/middle/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>,
Expand All @@ -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)
}
}
Expand Down
55 changes: 27 additions & 28 deletions src/librustc_typeck/check/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ use middle::traits::{predicate_for_trait_def, report_selection_error};
use middle::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef};
use middle::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer};
use middle::ty::adjustment::{AdjustUnsafeFnPointer};
use middle::ty::{self, LvaluePreference, TypeAndMut, Ty};
use middle::ty::{self, HasTypeFlags, LvaluePreference, TypeAndMut, Ty};
use middle::ty::error::TypeError;
use middle::ty::relate::RelateResult;
use util::common::indent;
Expand Down Expand Up @@ -110,10 +110,15 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
a,
b);

let a = self.fcx.infcx().shallow_resolve(a);

// Just ignore error types.
if a.references_error() || b.references_error() {
return Ok(None);
}

// Consider coercing the subtype to a DST
let unsize = self.unpack_actual_value(a, |a| {
self.coerce_unsized(a, b)
});
let unsize = self.coerce_unsized(a, b);
if unsize.is_ok() {
return unsize;
}
Expand All @@ -124,39 +129,33 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// See above for details.
match b.sty {
ty::TyRawPtr(mt_b) => {
return self.unpack_actual_value(a, |a| {
self.coerce_unsafe_ptr(a, b, mt_b.mutbl)
});
return self.coerce_unsafe_ptr(a, b, mt_b.mutbl);
}

ty::TyRef(_, mt_b) => {
return self.unpack_actual_value(a, |a| {
self.coerce_borrowed_pointer(expr_a, a, b, mt_b.mutbl)
});
return self.coerce_borrowed_pointer(expr_a, a, b, mt_b.mutbl);
}

_ => {}
}

self.unpack_actual_value(a, |a| {
match a.sty {
ty::TyBareFn(Some(_), a_f) => {
// Function items are coercible to any closure
// type; function pointers are not (that would
// require double indirection).
self.coerce_from_fn_item(a, a_f, b)
}
ty::TyBareFn(None, a_f) => {
// We permit coercion of fn pointers to drop the
// unsafe qualifier.
self.coerce_from_fn_pointer(a, a_f, b)
}
_ => {
// Otherwise, just use subtyping rules.
self.subtype(a, b)
}
match a.sty {
ty::TyBareFn(Some(_), a_f) => {
// Function items are coercible to any closure
// type; function pointers are not (that would
// require double indirection).
self.coerce_from_fn_item(a, a_f, b)
}
})
ty::TyBareFn(None, a_f) => {
// We permit coercion of fn pointers to drop the
// unsafe qualifier.
self.coerce_from_fn_pointer(a, a_f, b)
}
_ => {
// Otherwise, just use subtyping rules.
self.subtype(a, b)
}
}
}

/// Reborrows `&mut A` to `&mut B` and `&(mut) A` to `&B`.
Expand Down
6 changes: 5 additions & 1 deletion src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1059,6 +1059,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);
fcx.type_error_message(span, |actual| {
format!("cast to unsized type: `{}` as `{}`", actual, tstr)
Expand Down Expand Up @@ -3507,9 +3510,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
let t_cast = structurally_resolved_type(fcx, expr.span, t_cast);
check_expr_with_expectation(fcx, e, ExpectCastableToType(t_cast));
let t_expr = fcx.expr_ty(e);
let t_cast = fcx.infcx().resolve_type_vars_if_possible(&t_cast);

// Eagerly check for some obvious errors.
if t_expr.references_error() {
if t_expr.references_error() || t_cast.references_error() {
fcx.write_error(id);
} else if !fcx.type_is_known_to_be_sized(t_cast, expr.span) {
report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_cast, t_expr, id);
Expand Down
22 changes: 22 additions & 0 deletions src/test/compile-fail/coherence-projection-conflict-ty-param.rs
Original file line number Diff line number Diff line change
@@ -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() {}
2 changes: 1 addition & 1 deletion src/test/compile-fail/const-eval-overflow-4b.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-19692.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(); //~ ERROR the type of this value must be known
}

fn main() { }
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-21950.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
4 changes: 3 additions & 1 deletion src/test/compile-fail/issue-23966.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
2 changes: 1 addition & 1 deletion src/test/compile-fail/issue-24352.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,5 @@

fn main() {
1.0f64 - 1.0;
1.0f64 - 1 //~ ERROR: is not implemented
1.0f64 - 1 //~ ERROR E0277
}
31 changes: 31 additions & 0 deletions src/test/compile-fail/issue-29857.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// 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.


#![feature(rustc_attrs)]

use std::marker::PhantomData;

pub trait Foo<P> {}

impl <P, T: Foo<P>> Foo<P> for Option<T> {}

pub struct Qux<T> (PhantomData<*mut T>);

impl<T> Foo<*mut T> for Option<Qux<T>> {}

pub trait Bar {
type Output: 'static;
}

impl<T: 'static, W: Bar<Output = T>> Foo<*mut T> for W {}

#[rustc_error]
fn main() {} //~ ERROR compilation successful
4 changes: 3 additions & 1 deletion src/test/run-pass/issue-25810.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ fn main() {
println!("{:?}",y);
}

trait Foo {
trait Foo
where for<'a> &'a Self: Bar
{
fn foo<'a>(&'a self) -> <&'a Self as Bar>::Output;
}

Expand Down