Point at source of trait bound obligations in more places

Be more thorough in using `ItemObligation` and `BindingObligation` when
evaluating obligations so that we can point at trait bounds that
introduced unfulfilled obligations. We no longer incorrectly point at
unrelated trait bounds (`substs-ppaux.verbose.stderr`).

In particular, we now point at trait bounds on method calls.

We no longer point at "obvious" obligation sources (we no longer have a
note pointing at `Trait` saying "required by a bound in `Trait`", like
in `associated-types-no-suitable-supertrait*`).

Address part of #89418.
This commit is contained in:
Esteban Kuber 2021-10-05 23:04:09 +00:00
parent 93542a8240
commit 6b9d910639
101 changed files with 550 additions and 421 deletions

View file

@ -9,7 +9,9 @@ use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness};
use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
pub use rustc_infer::traits::util::*;
pub use rustc_infer::traits::{self, util::*};
use std::iter;
///////////////////////////////////////////////////////////////////////////
// `TraitAliasExpander` iterator
@ -229,11 +231,16 @@ pub fn predicates_for_generics<'tcx>(
) -> impl Iterator<Item = PredicateObligation<'tcx>> {
debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
generic_bounds.predicates.into_iter().map(move |predicate| Obligation {
cause: cause.clone(),
recursion_depth,
param_env,
predicate,
iter::zip(generic_bounds.predicates, generic_bounds.spans).map(move |(predicate, span)| {
let cause = match cause.code {
traits::ItemObligation(def_id) if !span.is_dummy() => traits::ObligationCause::new(
cause.span,
cause.body_id,
traits::BindingObligation(def_id, span),
),
_ => cause.clone(),
};
Obligation { cause, recursion_depth, param_env, predicate }
})
}

View file

@ -709,7 +709,12 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
iter::zip(iter::zip(predicates.predicates, predicates.spans), origins.into_iter().rev())
.map(|((pred, span), origin_def_id)| {
let cause = self.cause(traits::BindingObligation(origin_def_id, span));
let code = if span.is_dummy() {
traits::MiscObligation
} else {
traits::BindingObligation(origin_def_id, span)
};
let cause = self.cause(code);
traits::Obligation::with_depth(cause, self.recursion_depth, self.param_env, pred)
})
.filter(|pred| !pred.has_escaping_bound_vars())