-
Notifications
You must be signed in to change notification settings - Fork 13.1k
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
Maintain predicate obligation chain for more detailed diagnostics #69709
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -138,7 +138,7 @@ pub enum ObligationCauseCode<'tcx> { | |
|
||
/// In an impl of trait `X` for type `Y`, type `Y` must | ||
/// also implement all supertraits of `X`. | ||
ItemObligation(DefId), | ||
ItemObligation(DefId, Option<Span>), | ||
|
||
/// Like `ItemObligation`, but with extra detail on the source of the obligation. | ||
BindingObligation(DefId, Span), | ||
Comment on lines
143
to
144
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wait, looks like a version with a Or I guess There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. At the very least seeing this tells me that having a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #69745 acknowledges this and uses |
||
|
@@ -193,6 +193,8 @@ pub enum ObligationCauseCode<'tcx> { | |
|
||
ImplDerivedObligation(DerivedObligationCause<'tcx>), | ||
|
||
DerivedCauseCode(Box<ObligationCauseCode<'tcx>>), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Don't we have a system for this already? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The closest is what is above but that requires a predicates to be available always, and that wasn't feasible for the cases I was handling. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. WF definitely has WF predicates, so at least that should be doable. I'll take a second look at the diff and note the places There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay, I see, But still, I'd prefer if this side of the PR was done separately from the |
||
|
||
/// Error derived when matching traits/impls; see ObligationCause for more details | ||
CompareImplMethodObligation { | ||
item_name: ast::Name, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -410,7 +410,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { | |
super::SliceOrArrayElem => Some(super::SliceOrArrayElem), | ||
super::TupleElem => Some(super::TupleElem), | ||
super::ProjectionWf(proj) => tcx.lift(&proj).map(super::ProjectionWf), | ||
super::ItemObligation(def_id) => Some(super::ItemObligation(def_id)), | ||
super::ItemObligation(def_id, span) => Some(super::ItemObligation(def_id, span)), | ||
super::BindingObligation(def_id, span) => Some(super::BindingObligation(def_id, span)), | ||
super::ReferenceOutlivesReferent(ty) => { | ||
tcx.lift(&ty).map(super::ReferenceOutlivesReferent) | ||
|
@@ -442,6 +442,7 @@ impl<'a, 'tcx> Lift<'tcx> for traits::ObligationCauseCode<'a> { | |
super::ImplDerivedObligation(ref cause) => { | ||
tcx.lift(cause).map(super::ImplDerivedObligation) | ||
} | ||
super::DerivedCauseCode(ref x) => tcx.lift(&**x).map(|x| x), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is stripping |
||
super::CompareImplMethodObligation { | ||
item_name, | ||
impl_item_def_id, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,9 +28,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | |
body_id: hir::HirId, | ||
) { | ||
let self_ty = trait_ref.self_ty(); | ||
let (param_ty, projection) = match &self_ty.kind { | ||
ty::Param(_) => (true, None), | ||
ty::Projection(projection) => (false, Some(projection)), | ||
let projection = match &self_ty.kind { | ||
ty::Param(_) => None, | ||
ty::Projection(projection) => Some(projection), | ||
_ => return, | ||
}; | ||
|
||
|
@@ -64,7 +64,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | |
generics, | ||
kind: hir::TraitItemKind::Method(..), | ||
.. | ||
}) if param_ty && self_ty == self.tcx.types.self_param => { | ||
}) if self_ty.is_some_param() && self_ty == self.tcx.types.self_param => { | ||
// Restricting `Self` for a single method. | ||
suggest_restriction(&generics, "`Self`", err); | ||
return; | ||
|
@@ -138,7 +138,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | |
}) | ||
| hir::Node::TraitItem(hir::TraitItem { generics, span, .. }) | ||
| hir::Node::ImplItem(hir::ImplItem { generics, span, .. }) | ||
if param_ty => | ||
if self_ty.is_some_param() => | ||
{ | ||
// Missing generic type parameter bound. | ||
let param_name = self_ty.to_string(); | ||
|
@@ -1421,7 +1421,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | |
debug!("note_obligation_cause_for_async_await: next_code={:?}", next_code); | ||
self.note_obligation_cause_code( | ||
err, | ||
&obligation.predicate, | ||
Some(&obligation.predicate), | ||
next_code.unwrap(), | ||
&mut Vec::new(), | ||
); | ||
|
@@ -1430,7 +1430,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | |
crate fn note_obligation_cause_code<T>( | ||
&self, | ||
err: &mut DiagnosticBuilder<'_>, | ||
predicate: &T, | ||
predicate: Option<&T>, | ||
cause_code: &ObligationCauseCode<'tcx>, | ||
obligated_types: &mut Vec<&ty::TyS<'tcx>>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a weird name and type. I assume this was meant to be There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This should indeed trip the internal lint. I want to revisit this lint anyway, to improve its suggestions. I'll look into this then. |
||
) where | ||
|
@@ -1470,15 +1470,30 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | |
region, object_ty, | ||
)); | ||
} | ||
ObligationCauseCode::ItemObligation(item_def_id) => { | ||
ObligationCauseCode::ItemObligation(item_def_id, bound_span) => { | ||
let item_name = tcx.def_path_str(item_def_id); | ||
let msg = format!("required by `{}`", item_name); | ||
|
||
if let Some(sp) = tcx.hir().span_if_local(item_def_id) { | ||
let sp = tcx.sess.source_map().def_span(sp); | ||
err.span_label(sp, &msg); | ||
} else { | ||
err.note(&msg); | ||
match ( | ||
tcx.hir().span_if_local(item_def_id).map(|s| tcx.sess.source_map().def_span(s)), | ||
bound_span, | ||
) { | ||
(Some(item_span), Some(bound_span)) if item_span.overlaps(bound_span) => { | ||
err.span_label(bound_span, &format!("{} here", msg)); | ||
} | ||
(Some(item_span), Some(bound_span)) => { | ||
err.span_label(item_span, &msg); | ||
err.span_label(bound_span, &format!("{} here", msg)); | ||
} | ||
(None, Some(bound_span)) => { | ||
err.span_label(bound_span, &format!("{} here", msg)); | ||
} | ||
(Some(item_span), None) => { | ||
err.span_label(item_span, &msg); | ||
} | ||
_ => { | ||
err.note(&msg); | ||
} | ||
} | ||
} | ||
ObligationCauseCode::BindingObligation(item_def_id, span) => { | ||
|
@@ -1576,6 +1591,10 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | |
ObligationCauseCode::SharedStatic => { | ||
err.note("shared static variables must have a type that implements `Sync`"); | ||
} | ||
ObligationCauseCode::DerivedCauseCode(ref data) => { | ||
let mut obligated_types = vec![]; | ||
self.note_obligation_cause_code(err, None::<&T>, &**data, &mut obligated_types); | ||
} | ||
ObligationCauseCode::BuiltinDerivedObligation(ref data) => { | ||
let parent_trait_ref = self.resolve_vars_if_possible(&data.parent_trait_ref); | ||
let ty = parent_trait_ref.skip_binder().self_ty(); | ||
|
@@ -1586,7 +1605,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | |
if !self.is_recursive_obligation(obligated_types, &data.parent_code) { | ||
self.note_obligation_cause_code( | ||
err, | ||
&parent_predicate, | ||
Some(&parent_predicate), | ||
&data.parent_code, | ||
obligated_types, | ||
); | ||
|
@@ -1602,7 +1621,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | |
let parent_predicate = parent_trait_ref.without_const().to_predicate(); | ||
self.note_obligation_cause_code( | ||
err, | ||
&parent_predicate, | ||
Some(&parent_predicate), | ||
&data.parent_code, | ||
obligated_types, | ||
); | ||
|
@@ -1611,14 +1630,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { | |
err.note(&format!( | ||
"the requirement `{}` appears on the impl method \ | ||
but not on the corresponding trait method", | ||
predicate | ||
predicate.unwrap() | ||
)); | ||
} | ||
ObligationCauseCode::CompareImplTypeObligation { .. } => { | ||
err.note(&format!( | ||
"the requirement `{}` appears on the associated impl type \ | ||
but not on the corresponding associated trait type", | ||
predicate | ||
predicate.unwrap() | ||
)); | ||
} | ||
ObligationCauseCode::ReturnType | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh wow this comment is incredibly outdated (/me pokes @nikomatsakis).