summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_trait_selection/src/traits/select
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_trait_selection/src/traits/select')
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs31
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs55
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs99
3 files changed, 95 insertions, 90 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index e4b70f0d2..2733d9643 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -138,7 +138,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Before we go into the whole placeholder thing, just
// quickly check if the self-type is a projection at all.
match obligation.predicate.skip_binder().trait_ref.self_ty().kind() {
- ty::Projection(_) | ty::Opaque(..) => {}
+ ty::Alias(..) => {}
ty::Infer(ty::TyVar(_)) => {
span_bug!(
obligation.cause.span,
@@ -174,7 +174,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.param_env
.caller_bounds()
.iter()
- .filter_map(|o| o.to_opt_poly_trait_pred());
+ .filter_map(|p| p.to_opt_poly_trait_pred())
+ .filter(|p| !p.references_error());
// Micro-optimization: filter out predicates relating to different traits.
let matching_bounds =
@@ -254,18 +255,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// touch bound regions, they just capture the in-scope
// type/region parameters
match *obligation.self_ty().skip_binder().kind() {
- ty::Closure(_, closure_substs) => {
+ ty::Closure(def_id, closure_substs) => {
+ let is_const = self.tcx().is_const_fn_raw(def_id);
debug!(?kind, ?obligation, "assemble_unboxed_candidates");
match self.infcx.closure_kind(closure_substs) {
Some(closure_kind) => {
debug!(?closure_kind, "assemble_unboxed_candidates");
if closure_kind.extends(kind) {
- candidates.vec.push(ClosureCandidate);
+ candidates.vec.push(ClosureCandidate { is_const });
}
}
None => {
debug!("assemble_unboxed_candidates: closure_kind not yet known");
- candidates.vec.push(ClosureCandidate);
+ candidates.vec.push(ClosureCandidate { is_const });
}
}
}
@@ -355,7 +357,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Before we create the substitutions and everything, first
// consider a "quick reject". This avoids creating more types
// and so forth that we need to.
- let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap();
+ let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
if self.fast_reject_trait_refs(obligation, &impl_trait_ref.0) {
return;
}
@@ -394,9 +396,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// still be provided by a manual implementation for
// this trait and type.
}
- ty::Param(..) | ty::Projection(..) => {
+ ty::Param(..) | ty::Alias(ty::Projection, ..) => {
// In these cases, we don't know what the actual
- // type is. Therefore, we cannot break it down
+ // type is. Therefore, we cannot break it down
// into its constituent types. So we don't
// consider the `..` impl but instead just add no
// candidates: this means that typeck will only
@@ -536,10 +538,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let ty = traits::normalize_projection_type(
self,
param_env,
- ty::ProjectionTy {
- item_def_id: tcx.lang_items().deref_target()?,
- substs: trait_ref.substs,
- },
+ tcx.mk_alias_ty(tcx.lang_items().deref_target()?, trait_ref.substs),
cause.clone(),
0,
// We're *intentionally* throwing these away,
@@ -737,13 +736,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
match self_ty.skip_binder().kind() {
- ty::Opaque(..)
+ ty::Alias(..)
| ty::Dynamic(..)
| ty::Error(_)
| ty::Bound(..)
| ty::Param(_)
- | ty::Placeholder(_)
- | ty::Projection(_) => {
+ | ty::Placeholder(_) => {
// We don't know if these are `~const Destruct`, at least
// not structurally... so don't push a candidate.
}
@@ -829,8 +827,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Generator(_, _, _)
| ty::GeneratorWitness(_)
| ty::Never
- | ty::Projection(_)
- | ty::Opaque(_, _)
+ | ty::Alias(..)
| ty::Param(_)
| ty::Bound(_, _)
| ty::Error(_)
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index fda415155..82a59831b 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -2,7 +2,7 @@
//!
//! Confirmation unifies the output type parameters of the trait
//! with the values found in the obligation, possibly yielding a
-//! type error. See the [rustc dev guide] for more details.
+//! type error. See the [rustc dev guide] for more details.
//!
//! [rustc dev guide]:
//! https://rustc-dev-guide.rust-lang.org/traits/resolution.html#confirmation
@@ -12,9 +12,10 @@ use rustc_index::bit_set::GrowableBitSet;
use rustc_infer::infer::InferOk;
use rustc_infer::infer::LateBoundRegionConversionTime::HigherRankedType;
use rustc_middle::ty::{
- self, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef,
- ToPolyTraitRef, ToPredicate, Ty, TyCtxt,
+ self, Binder, GenericArg, GenericArgKind, GenericParamDefKind, InternalSubsts, SubstsRef,
+ ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt,
};
+use rustc_session::config::TraitSolver;
use rustc_span::def_id::DefId;
use crate::traits::project::{normalize_with_depth, normalize_with_depth_to};
@@ -83,7 +84,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ImplSource::Object(data)
}
- ClosureCandidate => {
+ ClosureCandidate { .. } => {
let vtable_closure = self.confirm_closure_candidate(obligation)?;
ImplSource::Closure(vtable_closure)
}
@@ -98,8 +99,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ImplSource::Future(vtable_future)
}
- FnPointerCandidate { .. } => {
- let data = self.confirm_fn_pointer_candidate(obligation)?;
+ FnPointerCandidate { is_const } => {
+ let data = self.confirm_fn_pointer_candidate(obligation, is_const)?;
ImplSource::FnPointer(data)
}
@@ -155,13 +156,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let placeholder_self_ty = placeholder_trait_predicate.self_ty();
let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
let (def_id, substs) = match *placeholder_self_ty.kind() {
- ty::Projection(proj) => (proj.item_def_id, proj.substs),
- ty::Opaque(def_id, substs) => (def_id, substs),
+ ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
_ => bug!("projection candidate for unexpected type: {:?}", placeholder_self_ty),
};
- let candidate_predicate =
- tcx.bound_item_bounds(def_id).map_bound(|i| i[idx]).subst(tcx, substs);
+ let candidate_predicate = tcx.item_bounds(def_id).map_bound(|i| i[idx]).subst(tcx, substs);
let candidate = candidate_predicate
.to_opt_poly_trait_pred()
.expect("projection candidate is not a trait predicate")
@@ -184,10 +183,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.map_err(|_| Unimplemented)
})?);
- if let ty::Projection(..) = placeholder_self_ty.kind() {
- let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs).predicates;
- debug!(?predicates, "projection predicates");
- for predicate in predicates {
+ if let ty::Alias(ty::Projection, ..) = placeholder_self_ty.kind() {
+ let predicates = tcx.predicates_of(def_id).instantiate_own(tcx, substs);
+ for (predicate, _) in predicates {
let normalized = normalize_with_depth_to(
self,
obligation.param_env,
@@ -357,8 +355,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
nested,
);
- // Adds the predicates from the trait. Note that this contains a `Self: Trait`
- // predicate as usual. It won't have any effect since auto traits are coinductive.
+ // Adds the predicates from the trait. Note that this contains a `Self: Trait`
+ // predicate as usual. It won't have any effect since auto traits are coinductive.
obligations.extend(trait_obligations);
debug!(?obligations, "vtable_auto_impl");
@@ -511,7 +509,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// This maybe belongs in wf, but that can't (doesn't) handle
// higher-ranked things.
// Prevent, e.g., `dyn Iterator<Item = str>`.
- for bound in self.tcx().bound_item_bounds(assoc_type).transpose_iter() {
+ for bound in self.tcx().item_bounds(assoc_type).transpose_iter() {
let subst_bound =
if defs.count() == 0 {
bound.subst(tcx, trait_predicate.trait_ref.substs)
@@ -598,17 +596,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn confirm_fn_pointer_candidate(
&mut self,
obligation: &TraitObligation<'tcx>,
+ is_const: bool,
) -> Result<ImplSourceFnPointerData<'tcx, PredicateObligation<'tcx>>, SelectionError<'tcx>>
{
debug!(?obligation, "confirm_fn_pointer_candidate");
+ let tcx = self.tcx();
let self_ty = self
.infcx
.shallow_resolve(obligation.self_ty().no_bound_vars())
.expect("fn pointer should not capture bound vars from predicate");
- let sig = self_ty.fn_sig(self.tcx());
+ let sig = self_ty.fn_sig(tcx);
let trait_ref = closure_trait_ref_and_return_type(
- self.tcx(),
+ tcx,
obligation.predicate.def_id(),
self_ty,
sig,
@@ -617,9 +617,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.map_bound(|(trait_ref, _)| trait_ref);
let mut nested = self.confirm_poly_trait_refs(obligation, trait_ref)?;
+ let cause = obligation.derived_cause(BuiltinDerivedObligation);
+
+ if obligation.is_const() && !is_const {
+ // function is a trait method
+ if let ty::FnDef(def_id, substs) = self_ty.kind() && let Some(trait_id) = tcx.trait_of_item(*def_id) {
+ let trait_ref = TraitRef::from_method(tcx, trait_id, *substs);
+ let poly_trait_pred = Binder::dummy(trait_ref).with_constness(ty::BoundConstness::ConstIfConst);
+ let obligation = Obligation::new(tcx, cause.clone(), obligation.param_env, poly_trait_pred);
+ nested.push(obligation);
+ }
+ }
// Confirm the `type Output: Sized;` bound that is present on `FnOnce`
- let cause = obligation.derived_cause(BuiltinDerivedObligation);
let output_ty = self.infcx.replace_bound_vars_with_placeholders(sig.output());
let output_ty = normalize_with_depth_to(
self,
@@ -756,8 +766,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug!(?closure_def_id, ?trait_ref, ?nested, "confirm closure candidate obligations");
// FIXME: Chalk
-
- if !self.tcx().sess.opts.unstable_opts.chalk {
+ if self.tcx().sess.opts.unstable_opts.trait_solver != TraitSolver::Chalk {
nested.push(obligation.with(
self.tcx(),
ty::Binder::dummy(ty::PredicateKind::ClosureKind(closure_def_id, substs, kind)),
@@ -1279,7 +1288,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// If we have a projection type, make sure to normalize it so we replace it
// with a fresh infer variable
- ty::Projection(..) => {
+ ty::Alias(ty::Projection, ..) => {
let predicate = normalize_with_depth_to(
self,
obligation.param_env,
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 035deb616..f90da95d5 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -430,7 +430,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// impl<T:Clone> Vec<T> { fn push_clone(...) { ... } }
//
// and we were to see some code `foo.push_clone()` where `boo`
- // is a `Vec<Bar>` and `Bar` does not implement `Clone`. If
+ // is a `Vec<Bar>` and `Bar` does not implement `Clone`. If
// we were to winnow, we'd wind up with zero candidates.
// Instead, we select the right impl now but report "`Bar` does
// not implement `Clone`".
@@ -755,7 +755,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// contain the "'static" lifetime (any other lifetime
// would either be late-bound or local), so it is guaranteed
// to outlive any other lifetime
- if pred.0.is_global() && !pred.0.has_late_bound_regions() {
+ if pred.0.is_global() && !pred.0.has_late_bound_vars() {
Ok(EvaluatedToOk)
} else {
Ok(EvaluatedToOkModuloRegions)
@@ -1171,19 +1171,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
where
I: Iterator<Item = ty::Predicate<'tcx>>,
{
- cycle.all(|predicate| self.coinductive_predicate(predicate))
- }
-
- fn coinductive_predicate(&self, predicate: ty::Predicate<'tcx>) -> bool {
- let result = match predicate.kind().skip_binder() {
- ty::PredicateKind::Clause(ty::Clause::Trait(ref data)) => {
- self.tcx().trait_is_coinductive(data.def_id())
- }
- ty::PredicateKind::WellFormed(_) => true,
- _ => false,
- };
- debug!(?predicate, ?result, "coinductive_predicate");
- result
+ cycle.all(|predicate| predicate.is_coinductive(self.tcx()))
}
/// Further evaluates `candidate` to decide whether all type parameters match and whether nested
@@ -1377,16 +1365,27 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// const param
ParamCandidate(trait_pred) if trait_pred.is_const_if_const() => {}
// const projection
- ProjectionCandidate(_, ty::BoundConstness::ConstIfConst) => {}
+ ProjectionCandidate(_, ty::BoundConstness::ConstIfConst)
// auto trait impl
- AutoImplCandidate => {}
+ | AutoImplCandidate
// generator / future, this will raise error in other places
// or ignore error with const_async_blocks feature
- GeneratorCandidate => {}
- FutureCandidate => {}
+ | GeneratorCandidate
+ | FutureCandidate
// FnDef where the function is const
- FnPointerCandidate { is_const: true } => {}
- ConstDestructCandidate(_) => {}
+ | FnPointerCandidate { is_const: true }
+ | ConstDestructCandidate(_)
+ | ClosureCandidate { is_const: true } => {}
+
+ FnPointerCandidate { is_const: false } => {
+ if let ty::FnDef(def_id, _) = obligation.self_ty().skip_binder().kind() && tcx.trait_of_item(*def_id).is_some() {
+ // Trait methods are not seen as const unless the trait is implemented as const.
+ // We do not filter that out in here, but nested obligations will be needed to confirm this.
+ } else {
+ continue
+ }
+ }
+
_ => {
// reject all other types of candidates
continue;
@@ -1595,8 +1594,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let tcx = self.infcx.tcx;
let (def_id, substs) = match *placeholder_trait_predicate.trait_ref.self_ty().kind() {
- ty::Projection(ref data) => (data.item_def_id, data.substs),
- ty::Opaque(def_id, substs) => (def_id, substs),
+ ty::Alias(_, ty::AliasTy { def_id, substs, .. }) => (def_id, substs),
_ => {
span_bug!(
obligation.cause.span,
@@ -1606,7 +1604,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
);
}
};
- let bounds = tcx.bound_item_bounds(def_id).subst(tcx, substs);
+ let bounds = tcx.item_bounds(def_id).subst(tcx, substs);
// The bounds returned by `item_bounds` may contain duplicates after
// normalization, so try to deduplicate when possible to avoid
@@ -1745,7 +1743,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
});
if is_match {
- let generics = self.tcx().generics_of(obligation.predicate.item_def_id);
+ let generics = self.tcx().generics_of(obligation.predicate.def_id);
// FIXME(generic-associated-types): Addresses aggressive inference in #92917.
// If this type is a GAT, and of the GAT substs resolve to something new,
// that means that we must have newly inferred something about the GAT.
@@ -1790,9 +1788,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Check if a bound would previously have been removed when normalizing
// the param_env so that it can be given the lowest priority. See
// #50825 for the motivation for this.
- let is_global = |cand: &ty::PolyTraitPredicate<'tcx>| {
- cand.is_global() && !cand.has_late_bound_regions()
- };
+ let is_global =
+ |cand: &ty::PolyTraitPredicate<'tcx>| cand.is_global() && !cand.has_late_bound_vars();
// (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
// `DiscriminantKindCandidate`, `ConstDestructCandidate`
@@ -1850,7 +1847,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
(
ParamCandidate(ref cand),
ImplCandidate(..)
- | ClosureCandidate
+ | ClosureCandidate { .. }
| GeneratorCandidate
| FutureCandidate
| FnPointerCandidate { .. }
@@ -1869,7 +1866,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
(
ImplCandidate(_)
- | ClosureCandidate
+ | ClosureCandidate { .. }
| GeneratorCandidate
| FutureCandidate
| FnPointerCandidate { .. }
@@ -1900,7 +1897,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
(
ObjectCandidate(_) | ProjectionCandidate(..),
ImplCandidate(..)
- | ClosureCandidate
+ | ClosureCandidate { .. }
| GeneratorCandidate
| FutureCandidate
| FnPointerCandidate { .. }
@@ -1913,7 +1910,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
(
ImplCandidate(..)
- | ClosureCandidate
+ | ClosureCandidate { .. }
| GeneratorCandidate
| FutureCandidate
| FnPointerCandidate { .. }
@@ -1995,7 +1992,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Everything else is ambiguous
(
ImplCandidate(_)
- | ClosureCandidate
+ | ClosureCandidate { .. }
| GeneratorCandidate
| FutureCandidate
| FnPointerCandidate { .. }
@@ -2005,7 +2002,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| BuiltinCandidate { has_nested: true }
| TraitAliasCandidate,
ImplCandidate(_)
- | ClosureCandidate
+ | ClosureCandidate { .. }
| GeneratorCandidate
| FutureCandidate
| FnPointerCandidate { .. }
@@ -2067,7 +2064,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}))
}
- ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => None,
+ ty::Alias(..) | ty::Param(_) => None,
ty::Infer(ty::TyVar(_)) => Ambiguous,
ty::Placeholder(..)
@@ -2167,7 +2164,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
}
}
- ty::Adt(..) | ty::Projection(..) | ty::Param(..) | ty::Opaque(..) => {
+ ty::Adt(..) | ty::Alias(..) | ty::Param(..) => {
// Fallback to whatever user-defined impls exist in this case.
None
}
@@ -2220,7 +2217,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ty::Dynamic(..)
| ty::Param(..)
| ty::Foreign(..)
- | ty::Projection(..)
+ | ty::Alias(ty::Projection, ..)
| ty::Bound(..)
| ty::Infer(ty::TyVar(_) | ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_)) => {
bug!("asked to assemble constituent types of unexpected type: {:?}", t);
@@ -2260,7 +2257,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
t.rebind(def.all_fields().map(|f| f.ty(self.tcx(), substs)).collect())
}
- ty::Opaque(def_id, substs) => {
+ ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => {
// We can resolve the `impl Trait` to its concrete type,
// which enforces a DAG between the functions requiring
// the auto trait bounds in question.
@@ -2327,7 +2324,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Matching
//
// Matching is a common path used for both evaluation and
- // confirmation. It basically unifies types that appear in impls
+ // confirmation. It basically unifies types that appear in impls
// and traits. This does affect the surrounding environment;
// therefore, when used during evaluation, match routines must be
// run inside of a `probe()` so that their side-effects are
@@ -2338,7 +2335,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
impl_def_id: DefId,
obligation: &TraitObligation<'tcx>,
) -> Normalized<'tcx, SubstsRef<'tcx>> {
- let impl_trait_ref = self.tcx().bound_impl_trait_ref(impl_def_id).unwrap();
+ let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
match self.match_impl(impl_def_id, impl_trait_ref, obligation) {
Ok(substs) => substs,
Err(()) => {
@@ -2383,6 +2380,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let impl_substs = self.infcx.fresh_substs_for_item(obligation.cause.span, impl_def_id);
let impl_trait_ref = impl_trait_ref.subst(self.tcx(), impl_substs);
+ if impl_trait_ref.references_error() {
+ return Err(());
+ }
debug!(?impl_trait_ref);
@@ -2558,12 +2558,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// obligation will normalize to `<$0 as Iterator>::Item = $1` and
// `$1: Copy`, so we must ensure the obligations are emitted in
// that order.
- let predicates = tcx.bound_predicates_of(def_id);
- debug!(?predicates);
- assert_eq!(predicates.0.parent, None);
- let mut obligations = Vec::with_capacity(predicates.0.predicates.len());
- for (predicate, span) in predicates.0.predicates {
- let span = *span;
+ let predicates = tcx.predicates_of(def_id);
+ assert_eq!(predicates.parent, None);
+ let predicates = predicates.instantiate_own(tcx, substs);
+ let mut obligations = Vec::with_capacity(predicates.len());
+ for (predicate, span) in predicates {
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
derived,
@@ -2576,7 +2575,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
param_env,
cause.clone(),
recursion_depth,
- predicates.rebind(*predicate).subst(tcx, substs),
+ predicate,
&mut obligations,
);
obligations.push(Obligation { cause, recursion_depth, param_env, predicate });
@@ -2644,7 +2643,7 @@ impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> {
/// In Issue #60010, we found a bug in rustc where it would cache
/// these intermediate results. This was fixed in #60444 by disabling
/// *all* caching for things involved in a cycle -- in our example,
-/// that would mean we don't cache that `Bar<T>: Send`. But this led
+/// that would mean we don't cache that `Bar<T>: Send`. But this led
/// to large slowdowns.
///
/// Specifically, imagine this scenario, where proving `Baz<T>: Send`
@@ -2670,7 +2669,7 @@ impl<'o, 'tcx> TraitObligationStack<'o, 'tcx> {
/// a result at `reached_depth`, so it marks the *current* solution as
/// provisional as well. If an error is encountered, we toss out any
/// provisional results added from the subtree that encountered the
-/// error. When we pop the node at `reached_depth` from the stack, we
+/// error. When we pop the node at `reached_depth` from the stack, we
/// can commit all the things that remain in the provisional cache.
struct ProvisionalEvaluationCache<'tcx> {
/// next "depth first number" to issue -- just a counter
@@ -2781,7 +2780,7 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> {
}
/// Invoked when the node with dfn `dfn` does not get a successful
- /// result. This will clear out any provisional cache entries
+ /// result. This will clear out any provisional cache entries
/// that were added since `dfn` was created. This is because the
/// provisional entries are things which must assume that the
/// things on the stack at the time of their creation succeeded --