Do not use ImplDerivedObligationCause for inherent impl method error reporting

This commit is contained in:
Michael Goulet 2023-04-10 06:06:01 +00:00
parent 39bf7777aa
commit b369c8ecbd
4 changed files with 124 additions and 35 deletions

View file

@ -1522,23 +1522,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
// Convert the bounds into obligations.
let impl_obligations = traits::predicates_for_generics(
|_idx, span| {
let misc = traits::ObligationCause::misc(span, self.body_id);
let parent_trait_pred = ty::Binder::dummy(ty::TraitPredicate {
trait_ref: ty::TraitRef::from_method(self.tcx, impl_def_id, substs),
constness: ty::BoundConstness::NotConst,
polarity: ty::ImplPolarity::Positive,
});
misc.derived_cause(parent_trait_pred, |derived| {
traits::ImplDerivedObligation(Box::new(
traits::ImplDerivedObligationCause {
derived,
impl_or_alias_def_id: impl_def_id,
impl_def_predicate_index: None,
span,
},
))
})
|idx, span| {
let code = if span.is_dummy() {
traits::ExprItemObligation(impl_def_id, self.scope_expr_id, idx)
} else {
traits::ExprBindingObligation(
impl_def_id,
span,
self.scope_expr_id,
idx,
)
};
ObligationCause::new(self.span, self.body_id, code)
},
self.param_env,
impl_bounds,

View file

@ -661,19 +661,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Find all the requirements that come from a local `impl` block.
let mut skip_list: FxHashSet<_> = Default::default();
let mut spanned_predicates = FxHashMap::default();
for (p, parent_p, impl_def_id, cause) in unsatisfied_predicates
.iter()
.filter_map(|(p, parent, c)| c.as_ref().map(|c| (p, parent, c)))
.filter_map(|(p, parent, c)| match c.code() {
ObligationCauseCode::ImplDerivedObligation(data)
if matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) =>
{
Some((p, parent, data.impl_or_alias_def_id, data))
for (p, parent_p, cause) in unsatisfied_predicates {
// Extract the predicate span and parent def id of the cause,
// if we have one.
let (item_def_id, cause_span) = match cause.as_ref().map(|cause| cause.code()) {
Some(ObligationCauseCode::ImplDerivedObligation(data)) => {
(data.impl_or_alias_def_id, data.span)
}
_ => None,
})
{
match self.tcx.hir().get_if_local(impl_def_id) {
Some(
ObligationCauseCode::ExprBindingObligation(def_id, span, _, _)
| ObligationCauseCode::BindingObligation(def_id, span),
) => (*def_id, *span),
_ => continue,
};
// Don't point out the span of `WellFormed` predicates.
if !matches!(p.kind().skip_binder(), ty::PredicateKind::Clause(_)) {
continue;
};
match self.tcx.hir().get_if_local(item_def_id) {
// Unmet obligation comes from a `derive` macro, point at it once to
// avoid multiple span labels pointing at the same place.
Some(Node::Item(hir::Item {
@ -718,7 +725,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
});
for param in generics.params {
if param.span == cause.span && sized_pred {
if param.span == cause_span && sized_pred {
let (sp, sugg) = match param.colon_span {
Some(sp) => (sp.shrink_to_hi(), " ?Sized +"),
None => (param.span.shrink_to_hi(), ": ?Sized"),
@ -741,9 +748,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(FxHashSet::default(), FxHashSet::default(), Vec::new())
});
entry.2.push(p);
if cause.span != *item_span {
entry.0.insert(cause.span);
entry.1.insert((cause.span, "unsatisfied trait bound introduced here"));
if cause_span != *item_span {
entry.0.insert(cause_span);
entry.1.insert((cause_span, "unsatisfied trait bound introduced here"));
} else {
if let Some(trait_ref) = of_trait {
entry.0.insert(trait_ref.path.span);
@ -775,9 +782,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let entry = entry.or_insert_with(|| {
(FxHashSet::default(), FxHashSet::default(), Vec::new())
});
entry.0.insert(cause.span);
entry.0.insert(cause_span);
entry.1.insert((ident.span, ""));
entry.1.insert((cause.span, "unsatisfied trait bound introduced here"));
entry.1.insert((cause_span, "unsatisfied trait bound introduced here"));
entry.2.push(p);
}
Some(node) => unreachable!("encountered `{node:?}`"),