diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index b89ce2ce3b2cf..26822aba8e994 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -62,14 +62,14 @@ impl<'tcx> TraitErrorKey<'tcx> { } pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, - errors: &Vec>) { + errors: &[FulfillmentError<'tcx>]) { for error in errors { report_fulfillment_error(infcx, error, None); } } pub fn report_fulfillment_errors_as_warnings<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, - errors: &Vec>, + errors: &[FulfillmentError<'tcx>], node_id: ast::NodeId) { for error in errors { @@ -123,6 +123,7 @@ pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, predicate, error.err); note_obligation_cause(infcx, &mut err, obligation); + infcx.tcx.note_and_explain_type_err(&mut err, &error.err, obligation.cause.span); err.emit(); } } diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs index a0d6f5f912b2c..0b764951ef919 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -88,8 +88,9 @@ pub enum ProjectionMode { /// } /// /// fn main() { - /// let <() as Assoc>::Output = true; + /// let x: <() as Assoc>::Output = true; /// } + /// ``` AnyFinal, /// At trans time, all projections will succeed. @@ -695,7 +696,7 @@ fn project_type<'cx,'tcx>( return None; } } else { - // Normally this situation could only arise througha + // Normally this situation could only arise through a // compiler bug, but at coherence-checking time we only look // at the topmost impl (we don't even consider the trait // itself) for the definition -- so we can fail to find a @@ -719,8 +720,6 @@ fn project_type<'cx,'tcx>( // trait Foo {} // impl Foo for ::Output {} // impl Foo for ::Output {} - // return None; - // } // ``` // // The essential problem here is that the projection fails, diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index e78a490bc4cc1..4f674f00780a8 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -93,7 +93,7 @@ pub fn translate_substs<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, fulfill_implication(infcx, source_trait_ref, target_impl).unwrap_or_else(|_| { bug!("When translating substitutions for specialization, the expected \ - specializaiton failed to hold") + specialization failed to hold") }) } specialization_graph::Node::Trait(..) => source_trait_ref.substs.clone(), diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 73bafc5e850b9..9528fe09a8cf6 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -11,7 +11,7 @@ use hir::def_id::DefId; use ty::subst; use infer::type_variable; -use ty::{self, BoundRegion, Region, Ty, TyCtxt}; +use ty::{self, BoundRegion, Region, Ty, TyCtxt, TypeFoldable}; use std::fmt; use syntax::abi; @@ -58,7 +58,8 @@ pub enum TypeError<'tcx> { ConvergenceMismatch(ExpectedFound), ProjectionNameMismatched(ExpectedFound), ProjectionBoundsLength(ExpectedFound), - TyParamDefaultMismatch(ExpectedFound>) + TyParamDefaultMismatch(ExpectedFound>), + UnnormalizedProjectionMismatch(ExpectedFound>), } #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] @@ -206,6 +207,10 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { values.expected.ty, values.found.ty) } + UnnormalizedProjectionMismatch(values) => ty::tls::with(|tcx| { + report_maybe_different(f, values.expected.sort_string(tcx), + values.found.sort_string(tcx)) + }), } } } @@ -337,6 +342,23 @@ impl<'tcx> TyCtxt<'tcx> { db.span_note(found.origin_span, "...that also applies to the same type variable here"); } + UnnormalizedProjectionMismatch(values) => { + let (proj, _) = if let &ty::TyProjection(_) = &values.found.sty { + (values.found, values.expected) + } else { + (values.expected, values.found) + }; + + // a type projection failure with no unsubstituted type parameters + // stems from specialization intentionally rejecting type projections for default + // implementations. + if proj.needs_subst() || proj.needs_infer() { + return; + } + + db.note("associated types marked as `default` cannot be projected \ + as a specific type."); + } _ => {} } } diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs index f14e680e9e06f..ca07d5601e4f4 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -581,6 +581,11 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R, Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name)) } + (&ty::TyProjection(_), _) | (_, &ty::TyProjection(_)) => + { + Err(TypeError::UnnormalizedProjectionMismatch(expected_found(relation, &a, &b))) + } + _ => { Err(TypeError::Sorts(expected_found(relation, &a, &b)))