diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 508261ddfdd6c..814263a0b00ca 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -244,6 +244,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { predicate, error.err); self.note_obligation_cause(&mut err, obligation); + self.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 4c338219ffbf7..d28c8096dcfaa 100644 --- a/src/librustc/traits/project.rs +++ b/src/librustc/traits/project.rs @@ -87,8 +87,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. @@ -697,7 +698,7 @@ fn project_type<'cx, 'gcx, '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 @@ -721,8 +722,6 @@ fn project_type<'cx, 'gcx, '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 d43d2de1f1fbc..31b7657916957 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -93,7 +93,7 @@ pub fn translate_substs<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, '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, diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index b5190f313309f..169eed3ab1b56 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<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, '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 80c727f022127..a90f02d8da1b5 100644 --- a/src/librustc/ty/relate.rs +++ b/src/librustc/ty/relate.rs @@ -582,6 +582,11 @@ pub fn super_relate_tys<'a, 'gcx, 'tcx, 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))) diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 77e980ff31965..78e20c2625076 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -317,6 +317,9 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { TyParamDefaultMismatch(ref x) => { return tcx.lift(x).map(TyParamDefaultMismatch) } + UnnormalizedProjectionMismatch(ref x) => { + return tcx.lift(x).map(UnnormalizedProjectionMismatch) + } }) } }