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.
This commit is contained in:
parent
39d164d042
commit
75ee8f1562
7 changed files with 337 additions and 130 deletions
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 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!(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 !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));
|
||||
report_object_safety_error(infcx.tcx, obligation.cause.span, did, is_warning);
|
||||
note_obligation_cause(infcx, obligation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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`");
|
||||
}
|
||||
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::SupertraitSelf => {
|
||||
infcx.tcx.sess.span_note(
|
||||
obligation.cause.span,
|
||||
"the trait cannot use `Self` as a type parameter \
|
||||
in the supertrait listing");
|
||||
}
|
||||
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::StaticMethod) => {
|
||||
infcx.tcx.sess.span_note(
|
||||
obligation.cause.span,
|
||||
&format!("method `{}` has no receiver",
|
||||
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::ReferencesSelf) => {
|
||||
infcx.tcx.sess.span_note(
|
||||
obligation.cause.span,
|
||||
&format!("method `{}` references the `Self` type \
|
||||
in its arguments or return type",
|
||||
method.name));
|
||||
}
|
||||
ObjectSafetyViolation::Method(method,
|
||||
MethodViolationCode::StaticMethod) => {
|
||||
tcx.sess.span_note(
|
||||
span,
|
||||
&format!("method `{}` has no receiver",
|
||||
method.name));
|
||||
}
|
||||
|
||||
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::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(
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -30,6 +30,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)*) => ({
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue