about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2015-08-07 10:28:51 -0400
committerNiko Matsakis <niko@alum.mit.edu>2015-08-12 17:58:22 -0400
commit75ee8f156204cef3140d6e153d36f9970ca2bfa1 (patch)
tree6bd154df8cee3efa70a947b8230ef68c52eec19d
parent39d164d0421a7560ea1e35a2347fda223cd43f6e (diff)
downloadrust-75ee8f156204cef3140d6e153d36f9970ca2bfa1.tar.gz
rust-75ee8f156204cef3140d6e153d36f9970ca2bfa1.zip
Introduce a "origin/cause" for new requirements (or bugfixes...) introduced by RFC 1214,
and issue a warning (and explanatory note) when we encounter such a
thing.
-rw-r--r--src/librustc/middle/infer/error_reporting.rs70
-rw-r--r--src/librustc/middle/infer/mod.rs21
-rw-r--r--src/librustc/middle/traits/error_reporting.rs303
-rw-r--r--src/librustc/middle/traits/mod.rs29
-rw-r--r--src/librustc/middle/traits/select.rs22
-rw-r--r--src/librustc/session/mod.rs14
-rw-r--r--src/libsyntax/diagnostics/macros.rs12
7 files changed, 339 insertions, 132 deletions
diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs
index 663746ac2dd..44eceb1f213 100644
--- a/src/librustc/middle/infer/error_reporting.rs
+++ b/src/librustc/middle/infer/error_reporting.rs
@@ -239,8 +239,7 @@ pub trait ErrorReporting<'tcx> {
     fn report_generic_bound_failure(&self,
                                     origin: SubregionOrigin<'tcx>,
                                     kind: GenericKind<'tcx>,
-                                    sub: Region,
-                                    sups: Vec<Region>);
+                                    sub: Region);
 
     fn report_sub_sup_conflict(&self,
                                var_origin: RegionVariableOrigin,
@@ -292,8 +291,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     self.report_concrete_failure(origin, sub, sup);
                 }
 
-                GenericBoundFailure(kind, param_ty, sub, sups) => {
-                    self.report_generic_bound_failure(kind, param_ty, sub, sups);
+                GenericBoundFailure(kind, param_ty, sub) => {
+                    self.report_generic_bound_failure(kind, param_ty, sub);
                 }
 
                 SubSupConflict(var_origin,
@@ -527,14 +526,18 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
     fn report_generic_bound_failure(&self,
                                     origin: SubregionOrigin<'tcx>,
                                     bound_kind: GenericKind<'tcx>,
-                                    sub: Region,
-                                    _sups: Vec<Region>)
+                                    sub: Region)
     {
         // FIXME: it would be better to report the first error message
         // with the span of the parameter itself, rather than the span
         // where the error was detected. But that span is not readily
         // accessible.
 
+        let is_warning = match origin {
+            infer::RFC1214Subregion(_) => true,
+            _ => false,
+        };
+
         let labeled_user_string = match bound_kind {
             GenericKind::Param(ref p) =>
                 format!("the parameter type `{}`", p),
@@ -545,7 +548,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
         match sub {
             ty::ReFree(ty::FreeRegion {bound_region: ty::BrNamed(..), ..}) => {
                 // Does the required lifetime have a nice name we can print?
-                span_err!(self.tcx.sess, origin.span(), E0309,
+                span_err_or_warn!(
+                    is_warning, self.tcx.sess, origin.span(), E0309,
                     "{} may not live long enough", labeled_user_string);
                 self.tcx.sess.fileline_help(
                     origin.span(),
@@ -557,7 +561,8 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
 
             ty::ReStatic => {
                 // Does the required lifetime have a nice name we can print?
-                span_err!(self.tcx.sess, origin.span(), E0310,
+                span_err_or_warn!(
+                    is_warning, self.tcx.sess, origin.span(), E0310,
                     "{} may not live long enough", labeled_user_string);
                 self.tcx.sess.fileline_help(
                     origin.span(),
@@ -568,9 +573,10 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
 
             _ => {
                 // If not, be less specific.
-                span_err!(self.tcx.sess, origin.span(), E0311,
-                        "{} may not live long enough",
-                        labeled_user_string);
+                span_err_or_warn!(
+                    is_warning, self.tcx.sess, origin.span(), E0311,
+                    "{} may not live long enough",
+                    labeled_user_string);
                 self.tcx.sess.fileline_help(
                     origin.span(),
                     &format!(
@@ -583,6 +589,10 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
             }
         }
 
+        if is_warning {
+            self.tcx.sess.note_rfc_1214(origin.span());
+        }
+
         self.note_region_origin(&origin);
     }
 
@@ -591,6 +601,13 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                                sub: Region,
                                sup: Region) {
         match origin {
+            infer::RFC1214Subregion(ref suborigin) => {
+                // Ideally, this would be a warning, but it doesn't
+                // seem to come up in practice, since the changes from
+                // RFC1214 mostly trigger errors in type definitions
+                // that don't wind up coming down this path.
+                self.report_concrete_failure((**suborigin).clone(), sub, sup);
+            }
             infer::Subtype(trace) => {
                 let terr = TypeError::RegionsDoesNotOutlive(sup, sub);
                 self.report_and_explain_type_error(trace, &terr);
@@ -819,6 +836,23 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     sup,
                     "");
             }
+            infer::ParameterInScope(_, span) => {
+                self.tcx.sess.span_err(
+                    span,
+                    &format!("type/lifetime parameter not in scope here"));
+                self.tcx.note_and_explain_region(
+                    "the parameter is only valid for ",
+                    sub,
+                    "");
+            }
+            infer::DataBorrowed(ty, span) => {
+                self.tcx.sess.span_err(
+                    span,
+                    &format!("a value of type `{}` is borrowed for too long",
+                             self.ty_to_string(ty)));
+                self.tcx.note_and_explain_region("the type is valid for ", sub, "");
+                self.tcx.note_and_explain_region("but the borrow lasts for ", sup, "");
+            }
             infer::ReferenceOutlivesReferent(ty, span) => {
                 self.tcx.sess.span_err(
                     span,
@@ -1567,6 +1601,9 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
 
     fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
         match *origin {
+            infer::RFC1214Subregion(ref suborigin) => {
+                self.note_region_origin(suborigin);
+            }
             infer::Subtype(ref trace) => {
                 let desc = match trace.origin {
                     infer::Misc(_) => {
@@ -1714,6 +1751,17 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
                     span,
                     "...so that variable is valid at time of its declaration");
             }
+            infer::ParameterInScope(_, span) => {
+                self.tcx.sess.span_note(
+                    span,
+                    &format!("...so that a type/lifetime parameter is in scope here"));
+            }
+            infer::DataBorrowed(ty, span) => {
+                self.tcx.sess.span_note(
+                    span,
+                    &format!("...so that the type `{}` is not borrowed for too long",
+                             self.ty_to_string(ty)));
+            }
             infer::ReferenceOutlivesReferent(ty, span) => {
                 self.tcx.sess.span_note(
                     span,
diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs
index f63154af724..da3749979b6 100644
--- a/src/librustc/middle/infer/mod.rs
+++ b/src/librustc/middle/infer/mod.rs
@@ -35,6 +35,7 @@ use middle::ty_relate::{Relate, RelateResult, TypeRelation};
 use rustc_data_structures::unify::{self, UnificationTable};
 use std::cell::{RefCell, Ref};
 use std::fmt;
+use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap;
 use syntax::codemap::{Span, DUMMY_SP};
@@ -188,6 +189,8 @@ pub struct TypeTrace<'tcx> {
 /// See `error_reporting.rs` for more details
 #[derive(Clone, Debug)]
 pub enum SubregionOrigin<'tcx> {
+    RFC1214Subregion(Rc<SubregionOrigin<'tcx>>),
+
     // Arose from a subtyping relation
     Subtype(TypeTrace<'tcx>),
 
@@ -229,9 +232,15 @@ pub enum SubregionOrigin<'tcx> {
     // Creating a pointer `b` to contents of an upvar
     ReborrowUpvar(Span, ty::UpvarId),
 
+    // Data with type `Ty<'tcx>` was borrowed
+    DataBorrowed(Ty<'tcx>, Span),
+
     // (&'a &'b T) where a >= b
     ReferenceOutlivesReferent(Ty<'tcx>, Span),
 
+    // Type or region parameters must be in scope.
+    ParameterInScope(ParameterOrigin, Span),
+
     // The type T of an expression E must outlive the lifetime for E.
     ExprTypeIsNotInScope(Ty<'tcx>, Span),
 
@@ -260,6 +269,15 @@ pub enum SubregionOrigin<'tcx> {
     SafeDestructor(Span),
 }
 
+/// Places that type/region parameters can appear.
+#[derive(Clone, Copy, Debug)]
+pub enum ParameterOrigin {
+    Path, // foo::bar
+    MethodCall, // foo.bar() <-- parameters on impl providing bar()
+    OverloadedOperator, // a + b when overloaded
+    OverloadedDeref, // *a when overloaded
+}
+
 /// Times when we replace late-bound regions with variables:
 #[derive(Clone, Copy, Debug)]
 pub enum LateBoundRegionConversionTime {
@@ -1565,6 +1583,7 @@ impl TypeOrigin {
 impl<'tcx> SubregionOrigin<'tcx> {
     pub fn span(&self) -> Span {
         match *self {
+            RFC1214Subregion(ref a) => a.span(),
             Subtype(ref a) => a.span(),
             InfStackClosure(a) => a,
             InvokeClosure(a) => a,
@@ -1577,7 +1596,9 @@ impl<'tcx> SubregionOrigin<'tcx> {
             RelateDefaultParamBound(a, _) => a,
             Reborrow(a) => a,
             ReborrowUpvar(a, _) => a,
+            DataBorrowed(_, a) => a,
             ReferenceOutlivesReferent(_, a) => a,
+            ParameterInScope(_, a) => a,
             ExprTypeIsNotInScope(_, a) => a,
             BindingTypeIsNotValidAtDecl(a) => a,
             CallRcvr(a) => a,
diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs
index 1f79db9e523..fb2db5089c9 100644
--- a/src/librustc/middle/traits/error_reporting.rs
+++ b/src/librustc/middle/traits/error_reporting.rs
@@ -25,11 +25,12 @@ use super::{
 
 use fmt_macros::{Parser, Piece, Position};
 use middle::infer::InferCtxt;
-use middle::ty::{self, ToPredicate, HasTypeFlags, ToPolyTraitRef, TraitRef};
+use middle::ty::{self, ToPredicate, HasTypeFlags, ToPolyTraitRef, TraitRef, Ty};
 use middle::ty_fold::TypeFoldable;
 use std::collections::HashMap;
 use std::fmt;
 use syntax::codemap::Span;
+use syntax::ast;
 use syntax::attr::{AttributeMethods, AttrMetaMethods};
 
 pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
@@ -54,22 +55,28 @@ fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
     }
 }
 
+fn is_warning<T>(obligation: &Obligation<T>) -> bool {
+    obligation.cause.code.is_rfc1214()
+}
+
 pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                          obligation: &PredicateObligation<'tcx>,
                                          error: &MismatchedProjectionTypes<'tcx>)
 {
     let predicate =
         infcx.resolve_type_vars_if_possible(&obligation.predicate);
+
     // The TyError created by normalize_to_error can end up being unified
     // into all obligations: for example, if our obligation is something
     // like `$X = <() as Foo<$X>>::Out` and () does not implement Foo<_>,
     // then $X will be unified with TyError, but the error still needs to be
     // reported.
     if !infcx.tcx.sess.has_errors() || !predicate.references_error() {
-        span_err!(infcx.tcx.sess, obligation.cause.span, E0271,
-                "type mismatch resolving `{}`: {}",
-                predicate,
-                error.err);
+        span_err_or_warn!(
+            is_warning(obligation), infcx.tcx.sess, obligation.cause.span, E0271,
+            "type mismatch resolving `{}`: {}",
+            predicate,
+            error.err);
         note_obligation_cause(infcx, obligation);
     }
 }
@@ -173,66 +180,93 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                         obligation: &PredicateObligation<'tcx>,
                                         error: &SelectionError<'tcx>)
 {
+    let is_warning = is_warning(obligation);
     match *error {
         SelectionError::Unimplemented => {
-            match &obligation.cause.code {
-                &ObligationCauseCode::CompareImplMethodObligation => {
-                    span_err!(infcx.tcx.sess, obligation.cause.span, E0276,
-                            "the requirement `{}` appears on the impl \
-                            method but not on the corresponding trait method",
-                            obligation.predicate);;
-                }
-                _ => {
-                    match obligation.predicate {
-                        ty::Predicate::Trait(ref trait_predicate) => {
-                            let trait_predicate =
-                                infcx.resolve_type_vars_if_possible(trait_predicate);
-
-                            if !infcx.tcx.sess.has_errors() ||
-                               !trait_predicate.references_error() {
-                                let trait_ref = trait_predicate.to_poly_trait_ref();
-                                span_err!(infcx.tcx.sess, obligation.cause.span, E0277,
-                                        "the trait `{}` is not implemented for the type `{}`",
-                                        trait_ref,
-                                        trait_ref.self_ty());
-                                // Check if it has a custom "#[rustc_on_unimplemented]"
-                                // error message, report with that message if it does
-                                let custom_note = report_on_unimplemented(infcx, &trait_ref.0,
-                                                                          obligation.cause.span);
-                                if let Some(s) = custom_note {
-                                    infcx.tcx.sess.span_note(obligation.cause.span,
-                                                             &s);
-                                }
+            if let ObligationCauseCode::CompareImplMethodObligation = obligation.cause.code {
+                span_err_or_warn!(
+                    is_warning, infcx.tcx.sess, obligation.cause.span, E0276,
+                    "the requirement `{}` appears on the impl \
+                     method but not on the corresponding trait method",
+                    obligation.predicate);;
+            } else {
+                match obligation.predicate {
+                    ty::Predicate::Trait(ref trait_predicate) => {
+                        let trait_predicate =
+                            infcx.resolve_type_vars_if_possible(trait_predicate);
+
+                        if !infcx.tcx.sess.has_errors() || !trait_predicate.references_error() {
+                            let trait_ref = trait_predicate.to_poly_trait_ref();
+                            span_err_or_warn!(
+                                is_warning, infcx.tcx.sess, obligation.cause.span, E0277,
+                                "the trait `{}` is not implemented for the type `{}`",
+                                trait_ref, trait_ref.self_ty());
+
+                            // Check if it has a custom "#[rustc_on_unimplemented]"
+                            // error message, report with that message if it does
+                            let custom_note = report_on_unimplemented(infcx, &trait_ref.0,
+                                                                      obligation.cause.span);
+                            if is_warning {
+                                note_obligation_cause(infcx, obligation);
+                            } else if let Some(s) = custom_note {
+                                infcx.tcx.sess.span_note(obligation.cause.span, &s);
+                            } else {
+                                note_obligation_cause(infcx, obligation);
                             }
                         }
+                    }
 
-                        ty::Predicate::Equate(ref predicate) => {
-                            let predicate = infcx.resolve_type_vars_if_possible(predicate);
-                            let err = infcx.equality_predicate(obligation.cause.span,
-                                                               &predicate).err().unwrap();
-                            span_err!(infcx.tcx.sess, obligation.cause.span, E0278,
-                                    "the requirement `{}` is not satisfied (`{}`)",
-                                    predicate,
-                                    err);
-                        }
+                    ty::Predicate::Equate(ref predicate) => {
+                        let predicate = infcx.resolve_type_vars_if_possible(predicate);
+                        let err = infcx.equality_predicate(obligation.cause.span,
+                                                           &predicate).err().unwrap();
+                        span_err_or_warn!(
+                            is_warning, infcx.tcx.sess, obligation.cause.span, E0278,
+                            "the requirement `{}` is not satisfied (`{}`)",
+                            predicate,
+                            err);
+                        note_obligation_cause(infcx, obligation);
+                    }
 
-                        ty::Predicate::RegionOutlives(ref predicate) => {
-                            let predicate = infcx.resolve_type_vars_if_possible(predicate);
-                            let err = infcx.region_outlives_predicate(obligation.cause.span,
-                                                                      &predicate).err().unwrap();
-                            span_err!(infcx.tcx.sess, obligation.cause.span, E0279,
-                                    "the requirement `{}` is not satisfied (`{}`)",
-                                    predicate,
-                                    err);
-                        }
+                    ty::Predicate::RegionOutlives(ref predicate) => {
+                        let predicate = infcx.resolve_type_vars_if_possible(predicate);
+                        let err = infcx.region_outlives_predicate(obligation.cause.span,
+                                                                  &predicate).err().unwrap();
+                        span_err_or_warn!(
+                            is_warning, infcx.tcx.sess, obligation.cause.span, E0279,
+                            "the requirement `{}` is not satisfied (`{}`)",
+                            predicate,
+                            err);
+                        note_obligation_cause(infcx, obligation);
+                    }
 
-                        ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
-                                let predicate =
-                                    infcx.resolve_type_vars_if_possible(&obligation.predicate);
-                                span_err!(infcx.tcx.sess, obligation.cause.span, E0280,
-                                        "the requirement `{}` is not satisfied",
-                                        predicate);
-                        }
+                    ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
+                        let predicate =
+                            infcx.resolve_type_vars_if_possible(&obligation.predicate);
+                        span_err_or_warn!(
+                            is_warning, infcx.tcx.sess, obligation.cause.span, E0280,
+                            "the requirement `{}` is not satisfied",
+                            predicate);
+                        note_obligation_cause(infcx, obligation);
+                    }
+
+                    ty::Predicate::ObjectSafe(trait_def_id) => {
+                        report_object_safety_error(infcx.tcx,
+                                                   obligation.cause.span,
+                                                   trait_def_id,
+                                                   is_warning);
+                        note_obligation_cause(infcx, obligation);
+                    }
+
+                    ty::Predicate::WellFormed(ty) => {
+                        // WF predicates cannot themselves make
+                        // errors. They can only block due to
+                        // ambiguity; otherwise, they always
+                        // degenerate into other obligations
+                        // (which may fail).
+                        infcx.tcx.sess.span_bug(
+                            obligation.cause.span,
+                            &format!("WF predicate not satisfied for {:?}", ty));
                     }
                 }
             }
@@ -242,62 +276,73 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
             let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
             let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
             if !actual_trait_ref.self_ty().references_error() {
-                span_err!(infcx.tcx.sess, obligation.cause.span, E0281,
-                        "type mismatch: the type `{}` implements the trait `{}`, \
-                        but the trait `{}` is required ({})",
-                        expected_trait_ref.self_ty(),
-                        expected_trait_ref,
-                        actual_trait_ref,
-                        e);
-                    note_obligation_cause(infcx, obligation);
+                span_err_or_warn!(
+                    is_warning, infcx.tcx.sess, obligation.cause.span, E0281,
+                    "type mismatch: the type `{}` implements the trait `{}`, \
+                     but the trait `{}` is required ({})",
+                    expected_trait_ref.self_ty(),
+                    expected_trait_ref,
+                    actual_trait_ref,
+                    e);
+                note_obligation_cause(infcx, obligation);
             }
         }
 
         TraitNotObjectSafe(did) => {
-            span_err!(infcx.tcx.sess, obligation.cause.span, E0038,
-                "cannot convert to a trait object because trait `{}` is not object-safe",
-                infcx.tcx.item_path_str(did));
-
-            for violation in object_safety_violations(infcx.tcx, did) {
-                match violation {
-                    ObjectSafetyViolation::SizedSelf => {
-                        infcx.tcx.sess.span_note(
-                            obligation.cause.span,
-                            "the trait cannot require that `Self : Sized`");
-                    }
+            report_object_safety_error(infcx.tcx, obligation.cause.span, did, is_warning);
+            note_obligation_cause(infcx, obligation);
+        }
+    }
+}
 
-                    ObjectSafetyViolation::SupertraitSelf => {
-                        infcx.tcx.sess.span_note(
-                            obligation.cause.span,
-                            "the trait cannot use `Self` as a type parameter \
-                            in the supertrait listing");
-                    }
+pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                        span: Span,
+                                        trait_def_id: ast::DefId,
+                                        is_warning: bool)
+{
+    span_err_or_warn!(
+        is_warning, tcx.sess, span, E0038,
+        "the trait `{}` cannot be made into an object",
+        tcx.item_path_str(trait_def_id));
 
-                    ObjectSafetyViolation::Method(method,
-                            MethodViolationCode::StaticMethod) => {
-                        infcx.tcx.sess.span_note(
-                            obligation.cause.span,
-                            &format!("method `{}` has no receiver",
-                                    method.name));
-                    }
+    for violation in object_safety_violations(tcx, trait_def_id) {
+        match violation {
+            ObjectSafetyViolation::SizedSelf => {
+                tcx.sess.span_note(
+                    span,
+                    "the trait cannot require that `Self : Sized`");
+            }
 
-                    ObjectSafetyViolation::Method(method,
-                            MethodViolationCode::ReferencesSelf) => {
-                        infcx.tcx.sess.span_note(
-                            obligation.cause.span,
-                            &format!("method `{}` references the `Self` type \
-                                    in its arguments or return type",
-                                    method.name));
-                    }
+            ObjectSafetyViolation::SupertraitSelf => {
+                tcx.sess.span_note(
+                    span,
+                    "the trait cannot use `Self` as a type parameter \
+                     in the supertrait listing");
+            }
 
-                    ObjectSafetyViolation::Method(method,
-                            MethodViolationCode::Generic) => {
-                        infcx.tcx.sess.span_note(
-                            obligation.cause.span,
-                            &format!("method `{}` has generic type parameters",
-                                    method.name));
-                    }
-                }
+            ObjectSafetyViolation::Method(method,
+                                          MethodViolationCode::StaticMethod) => {
+                tcx.sess.span_note(
+                    span,
+                    &format!("method `{}` has no receiver",
+                             method.name));
+            }
+
+            ObjectSafetyViolation::Method(method,
+                                          MethodViolationCode::ReferencesSelf) => {
+                tcx.sess.span_note(
+                    span,
+                    &format!("method `{}` references the `Self` type \
+                              in its arguments or return type",
+                             method.name));
+            }
+
+            ObjectSafetyViolation::Method(method,
+                                          MethodViolationCode::Generic) => {
+                tcx.sess.span_note(
+                    span,
+                    &format!("method `{}` has generic type parameters",
+                             method.name));
             }
         }
     }
@@ -342,14 +387,11 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                         infcx.tcx.lang_items.sized_trait()
                         .map_or(false, |sized_id| sized_id == trait_ref.def_id())
                     {
-                        span_err!(infcx.tcx.sess, obligation.cause.span, E0282,
-                                "unable to infer enough type information about `{}`; \
-                                 type annotations or generic parameter binding required",
-                                self_ty);
+                        need_type_info(infcx, obligation.cause.span, self_ty);
                     } else {
                         span_err!(infcx.tcx.sess, obligation.cause.span, E0283,
                                 "type annotations required: cannot resolve `{}`",
-                                predicate);;
+                                predicate);
                         note_obligation_cause(infcx, obligation);
                     }
                 }
@@ -366,6 +408,14 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
             }
         }
 
+        ty::Predicate::WellFormed(ty) => {
+            // Same hacky approach as above to avoid deluging user
+            // with error messages.
+            if !ty.references_error() && !infcx.tcx.sess.has_errors() {
+                need_type_info(infcx, obligation.cause.span, ty);
+            }
+        }
+
         _ => {
             if !infcx.tcx.sess.has_errors() {
                 span_err!(infcx.tcx.sess, obligation.cause.span, E0284,
@@ -377,6 +427,16 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
     }
 }
 
+fn need_type_info<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
+                            span: Span,
+                            ty: Ty<'tcx>)
+{
+    span_err!(infcx.tcx.sess, span, E0282,
+              "unable to infer enough type information about `{}`; \
+               type annotations or generic parameter binding required",
+              ty);
+}
+
 fn note_obligation_cause<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
                                       obligation: &Obligation<'tcx, T>)
     where T: fmt::Display
@@ -396,6 +456,27 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
     let tcx = infcx.tcx;
     match *cause_code {
         ObligationCauseCode::MiscObligation => { }
+        ObligationCauseCode::RFC1214(ref subcode) => {
+            tcx.sess.note_rfc_1214(cause_span);
+            note_obligation_cause_code(infcx, predicate, cause_span, subcode);
+        }
+        ObligationCauseCode::SliceOrArrayElem => {
+            tcx.sess.span_note(
+                cause_span,
+                &format!("slice and array elements must have `Sized` type"));
+        }
+        ObligationCauseCode::ProjectionWf(data) => {
+            tcx.sess.span_note(
+                cause_span,
+                &format!("required so that the projection `{}` is well-formed",
+                         data));
+        }
+        ObligationCauseCode::ReferenceOutlivesReferent(ref_ty) => {
+            tcx.sess.span_note(
+                cause_span,
+                &format!("required so that reference `{}` does not outlive its referent",
+                         ref_ty));
+        }
         ObligationCauseCode::ItemObligation(item_def_id) => {
             let item_name = tcx.item_path_str(item_def_id);
             tcx.sess.span_note(
diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs
index 376430e87c6..14ab6c505d0 100644
--- a/src/librustc/middle/traits/mod.rs
+++ b/src/librustc/middle/traits/mod.rs
@@ -27,6 +27,7 @@ use syntax::codemap::{Span, DUMMY_SP};
 pub use self::error_reporting::report_fulfillment_errors;
 pub use self::error_reporting::report_overflow_error;
 pub use self::error_reporting::report_selection_error;
+pub use self::error_reporting::report_object_safety_error;
 pub use self::error_reporting::suggest_new_overflow_limit;
 pub use self::coherence::orphan_check;
 pub use self::coherence::overlapping_impls;
@@ -80,7 +81,7 @@ pub type PredicateObligation<'tcx> = Obligation<'tcx, ty::Predicate<'tcx>>;
 pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>;
 
 /// Why did we incur this obligation? Used for error reporting.
-#[derive(Clone, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub struct ObligationCause<'tcx> {
     pub span: Span,
 
@@ -95,15 +96,27 @@ pub struct ObligationCause<'tcx> {
     pub code: ObligationCauseCode<'tcx>
 }
 
-#[derive(Clone, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub enum ObligationCauseCode<'tcx> {
     /// Not well classified or should be obvious from span.
     MiscObligation,
 
+    /// Obligation that triggers warning until RFC 1214 is fully in place.
+    RFC1214(Rc<ObligationCauseCode<'tcx>>),
+
+    /// This is the trait reference from the given projection
+    SliceOrArrayElem,
+
+    /// This is the trait reference from the given projection
+    ProjectionWf(ty::ProjectionTy<'tcx>),
+
     /// In an impl of trait X for type Y, type Y must
     /// also implement all supertraits of X.
     ItemObligation(ast::DefId),
 
+    /// A type like `&'a T` is WF only if `T: 'a`.
+    ReferenceOutlivesReferent(Ty<'tcx>),
+
     /// Obligation incurred due to an object cast.
     ObjectCastObligation(/* Object type */ Ty<'tcx>),
 
@@ -124,7 +137,6 @@ pub enum ObligationCauseCode<'tcx> {
     // static items must have `Sync` type
     SharedStatic,
 
-
     BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
 
     ImplDerivedObligation(DerivedObligationCause<'tcx>),
@@ -132,7 +144,7 @@ pub enum ObligationCauseCode<'tcx> {
     CompareImplMethodObligation,
 }
 
-#[derive(Clone, PartialEq, Eq)]
+#[derive(Clone, Debug, PartialEq, Eq)]
 pub struct DerivedObligationCause<'tcx> {
     /// The trait reference of the parent obligation that led to the
     /// current obligation. Note that only trait obligations lead to
@@ -516,6 +528,15 @@ impl<'tcx> ObligationCause<'tcx> {
     }
 }
 
+impl<'tcx> ObligationCauseCode<'tcx> {
+    pub fn is_rfc1214(&self) -> bool {
+        match *self {
+            ObligationCauseCode::RFC1214(..) => true,
+            _ => false,
+        }
+    }
+}
+
 impl<'tcx, N> Vtable<'tcx, N> {
     pub fn nested_obligations(self) -> Vec<N> {
         match self {
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index 6c568b656c0..713b7394b59 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -2920,13 +2920,23 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // chain. Ideally, we should have a way to configure this either
         // by using -Z verbose or just a CLI argument.
         if obligation.recursion_depth >= 0 {
-            let derived_cause = DerivedObligationCause {
-                parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
-                parent_code: Rc::new(obligation.cause.code.clone()),
+            let derived_code = match obligation.cause.code {
+                ObligationCauseCode::RFC1214(ref base_code) => {
+                    let derived_cause = DerivedObligationCause {
+                        parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
+                        parent_code: base_code.clone(),
+                    };
+                    ObligationCauseCode::RFC1214(Rc::new(variant(derived_cause)))
+                }
+                _ => {
+                    let derived_cause = DerivedObligationCause {
+                        parent_trait_ref: obligation.predicate.to_poly_trait_ref(),
+                        parent_code: Rc::new(obligation.cause.code.clone())
+                    };
+                    variant(derived_cause)
+                }
             };
-            ObligationCause::new(obligation.cause.span,
-                                 obligation.cause.body_id,
-                                 variant(derived_cause))
+            ObligationCause::new(obligation.cause.span, obligation.cause.body_id, derived_code)
         } else {
             obligation.cause.clone()
         }
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 99a58f07ae6..ffb3a8ccb36 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -90,6 +90,13 @@ impl Session {
         }
         self.diagnostic().handler().fatal(msg)
     }
+    pub fn span_err_or_warn(&self, is_warning: bool, sp: Span, msg: &str) {
+        if is_warning {
+            self.span_warn(sp, msg);
+        } else {
+            self.span_err(sp, msg);
+        }
+    }
     pub fn span_err(&self, sp: Span, msg: &str) {
         if self.opts.treat_err_as_bug {
             self.span_bug(sp, msg);
@@ -99,6 +106,13 @@ impl Session {
             None => self.diagnostic().span_err(sp, msg)
         }
     }
+    pub fn note_rfc_1214(&self, span: Span) {
+        self.span_note(
+            span,
+            &format!("this warning results from recent bug fixes and clarifications; \
+                      it will become a HARD ERROR in the next release. \
+                      See RFC 1214 for details."));
+    }
     pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
         if self.opts.treat_err_as_bug {
             self.span_bug(sp, msg);
diff --git a/src/libsyntax/diagnostics/macros.rs b/src/libsyntax/diagnostics/macros.rs
index 669b930ecc9..3c8347f8a8e 100644
--- a/src/libsyntax/diagnostics/macros.rs
+++ b/src/libsyntax/diagnostics/macros.rs
@@ -31,6 +31,18 @@ macro_rules! span_err {
 }
 
 #[macro_export]
+macro_rules! span_err_or_warn {
+    ($is_warning:expr, $session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
+        __diagnostic_used!($code);
+        if $is_warning {
+            $session.span_warn_with_code($span, &format!($($message)*), stringify!($code))
+        } else {
+            $session.span_err_with_code($span, &format!($($message)*), stringify!($code))
+        }
+    })
+}
+
+#[macro_export]
 macro_rules! span_warn {
     ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);