Avoid storing the ImplPolarity and Constness next to a TraitRef and use TraitPredicate instead

This commit is contained in:
Oli Scherer 2021-10-25 14:29:54 +00:00 committed by Deadbeef
parent d161cc2071
commit a848c4ba3f
No known key found for this signature in database
GPG Key ID: 6D017A96D8E6C2F9
11 changed files with 59 additions and 53 deletions

View File

@ -328,8 +328,8 @@ pub fn transitive_bounds_that_define_assoc_type<'tcx>(
)); ));
for (super_predicate, _) in super_predicates.predicates { for (super_predicate, _) in super_predicates.predicates {
let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref); let subst_predicate = super_predicate.subst_supertrait(tcx, &trait_ref);
if let Some(binder) = subst_predicate.to_opt_poly_trait_ref() { if let Some(binder) = subst_predicate.to_opt_poly_trait_pred() {
stack.push(binder.value); stack.push(binder.map_bound(|t| t.trait_ref));
} }
} }
@ -362,8 +362,8 @@ impl<'tcx, I: Iterator<Item = PredicateObligation<'tcx>>> Iterator for FilterToT
fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> { fn next(&mut self) -> Option<ty::PolyTraitRef<'tcx>> {
while let Some(obligation) = self.base_iterator.next() { while let Some(obligation) = self.base_iterator.next() {
if let Some(data) = obligation.predicate.to_opt_poly_trait_ref() { if let Some(data) = obligation.predicate.to_opt_poly_trait_pred() {
return Some(data.value); return Some(data.map_bound(|t| t.trait_ref));
} }
} }
None None

View File

@ -101,7 +101,7 @@ pub enum SelectionCandidate<'tcx> {
/// `false` if there are no *further* obligations. /// `false` if there are no *further* obligations.
has_nested: bool, has_nested: bool,
}, },
ParamCandidate((ty::ConstnessAnd<ty::PolyTraitRef<'tcx>>, ty::ImplPolarity)), ParamCandidate(ty::PolyTraitPredicate<'tcx>),
ImplCandidate(DefId), ImplCandidate(DefId),
AutoImplCandidate(DefId), AutoImplCandidate(DefId),

View File

@ -885,12 +885,10 @@ impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> {
} }
impl<'tcx> Predicate<'tcx> { impl<'tcx> Predicate<'tcx> {
pub fn to_opt_poly_trait_ref(self) -> Option<ConstnessAnd<PolyTraitRef<'tcx>>> { pub fn to_opt_poly_trait_pred(self) -> Option<PolyTraitPredicate<'tcx>> {
let predicate = self.kind(); let predicate = self.kind();
match predicate.skip_binder() { match predicate.skip_binder() {
PredicateKind::Trait(t) => { PredicateKind::Trait(t) => Some(predicate.rebind(t)),
Some(ConstnessAnd { constness: t.constness, value: predicate.rebind(t.trait_ref) })
}
PredicateKind::Projection(..) PredicateKind::Projection(..)
| PredicateKind::Subtype(..) | PredicateKind::Subtype(..)
| PredicateKind::Coerce(..) | PredicateKind::Coerce(..)

View File

@ -574,14 +574,17 @@ fn prepare_vtable_segments<'tcx, T>(
.predicates .predicates
.into_iter() .into_iter()
.filter_map(move |(pred, _)| { .filter_map(move |(pred, _)| {
pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_ref() pred.subst_supertrait(tcx, &inner_most_trait_ref).to_opt_poly_trait_pred()
}); });
'diving_in_skip_visited_traits: loop { 'diving_in_skip_visited_traits: loop {
if let Some(next_super_trait) = direct_super_traits_iter.next() { if let Some(next_super_trait) = direct_super_traits_iter.next() {
if visited.insert(next_super_trait.to_predicate(tcx)) { if visited.insert(next_super_trait.to_predicate(tcx)) {
// We're throwing away potential constness of super traits here.
// FIXME: handle ~const super traits
let next_super_trait = next_super_trait.map_bound(|t| t.trait_ref);
stack.push(( stack.push((
next_super_trait.value, next_super_trait,
emit_vptr_on_new_entry, emit_vptr_on_new_entry,
Some(direct_super_traits_iter), Some(direct_super_traits_iter),
)); ));
@ -613,7 +616,11 @@ fn prepare_vtable_segments<'tcx, T>(
if let Some(siblings) = siblings_opt { if let Some(siblings) = siblings_opt {
if let Some(next_inner_most_trait_ref) = siblings.next() { if let Some(next_inner_most_trait_ref) = siblings.next() {
if visited.insert(next_inner_most_trait_ref.to_predicate(tcx)) { if visited.insert(next_inner_most_trait_ref.to_predicate(tcx)) {
*inner_most_trait_ref = next_inner_most_trait_ref.value; // We're throwing away potential constness of super traits here.
// FIXME: handle ~const super traits
let next_inner_most_trait_ref =
next_inner_most_trait_ref.map_bound(|t| t.trait_ref);
*inner_most_trait_ref = next_inner_most_trait_ref;
*emit_vptr = emit_vptr_on_new_entry; *emit_vptr = emit_vptr_on_new_entry;
break 'exiting_out; break 'exiting_out;
} else { } else {

View File

@ -383,17 +383,19 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
.param_env .param_env
.caller_bounds() .caller_bounds()
.iter() .iter()
.filter_map(|o| o.to_opt_poly_trait_ref()); .filter_map(|o| o.to_opt_poly_trait_pred());
// Micro-optimization: filter out predicates relating to different traits. // Micro-optimization: filter out predicates relating to different traits.
let matching_bounds = let matching_bounds =
all_bounds.filter(|p| p.value.def_id() == stack.obligation.predicate.def_id()); all_bounds.filter(|p| p.def_id() == stack.obligation.predicate.def_id());
// Keep only those bounds which may apply, and propagate overflow if it occurs. // Keep only those bounds which may apply, and propagate overflow if it occurs.
for bound in matching_bounds { for bound in matching_bounds {
let wc = self.evaluate_where_clause(stack, bound.value)?; // FIXME(oli-obk): it is suspicious that we are dropping the constness and
// polarity here.
let wc = self.evaluate_where_clause(stack, bound.map_bound(|t| t.trait_ref))?;
if wc.may_apply() { if wc.may_apply() {
candidates.vec.push(ParamCandidate((bound, stack.obligation.polarity()))); candidates.vec.push(ParamCandidate(bound));
} }
} }

View File

@ -58,8 +58,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} }
ParamCandidate(param) => { ParamCandidate(param) => {
let obligations = self.confirm_param_candidate(obligation, param.0.value); let obligations =
Ok(ImplSource::Param(obligations, param.0.constness)) self.confirm_param_candidate(obligation, param.map_bound(|t| t.trait_ref));
Ok(ImplSource::Param(obligations, param.skip_binder().constness))
} }
ImplCandidate(impl_def_id) => { ImplCandidate(impl_def_id) => {
@ -139,7 +140,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let trait_predicate = self.infcx.shallow_resolve(obligation.predicate); let trait_predicate = self.infcx.shallow_resolve(obligation.predicate);
let placeholder_trait_predicate = let placeholder_trait_predicate =
self.infcx().replace_bound_vars_with_placeholders(trait_predicate); self.infcx().replace_bound_vars_with_placeholders(trait_predicate).trait_ref;
let placeholder_self_ty = placeholder_trait_predicate.self_ty(); let placeholder_self_ty = placeholder_trait_predicate.self_ty();
let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate); let placeholder_trait_predicate = ty::Binder::dummy(placeholder_trait_predicate);
let (def_id, substs) = match *placeholder_self_ty.kind() { let (def_id, substs) = match *placeholder_self_ty.kind() {
@ -150,8 +151,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let candidate_predicate = tcx.item_bounds(def_id)[idx].subst(tcx, substs); let candidate_predicate = tcx.item_bounds(def_id)[idx].subst(tcx, substs);
let candidate = candidate_predicate let candidate = candidate_predicate
.to_opt_poly_trait_ref() .to_opt_poly_trait_pred()
.expect("projection candidate is not a trait predicate"); .expect("projection candidate is not a trait predicate")
.map_bound(|t| t.trait_ref);
let mut obligations = Vec::new(); let mut obligations = Vec::new();
let candidate = normalize_with_depth_to( let candidate = normalize_with_depth_to(
self, self,
@ -165,7 +167,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
obligations.extend(self.infcx.commit_if_ok(|_| { obligations.extend(self.infcx.commit_if_ok(|_| {
self.infcx self.infcx
.at(&obligation.cause, obligation.param_env) .at(&obligation.cause, obligation.param_env)
.sup(placeholder_trait_predicate.to_poly_trait_ref(), candidate.value) .sup(placeholder_trait_predicate, candidate)
.map(|InferOk { obligations, .. }| obligations) .map(|InferOk { obligations, .. }| obligations)
.map_err(|_| Unimplemented) .map_err(|_| Unimplemented)
})?); })?);

View File

@ -1089,10 +1089,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
ImplCandidate(def_id) ImplCandidate(def_id)
if tcx.impl_constness(def_id) == hir::Constness::Const => {} if tcx.impl_constness(def_id) == hir::Constness::Const => {}
// const param // const param
ParamCandidate(( ParamCandidate(trait_pred)
ty::ConstnessAnd { constness: ty::BoundConstness::ConstIfConst, .. }, if trait_pred.skip_binder().constness
_, == ty::BoundConstness::ConstIfConst => {}
)) => {}
// auto trait impl // auto trait impl
AutoImplCandidate(..) => {} AutoImplCandidate(..) => {}
// generator, this will raise error in other places // generator, this will raise error in other places
@ -1474,7 +1473,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// Check if a bound would previously have been removed when normalizing // Check if a bound would previously have been removed when normalizing
// the param_env so that it can be given the lowest priority. See // the param_env so that it can be given the lowest priority. See
// #50825 for the motivation for this. // #50825 for the motivation for this.
let is_global = |cand: &ty::PolyTraitRef<'tcx>| { let is_global = |cand: &ty::PolyTraitPredicate<'tcx>| {
cand.is_global(self.infcx.tcx) && !cand.has_late_bound_regions() cand.is_global(self.infcx.tcx) && !cand.has_late_bound_regions()
}; };
@ -1507,25 +1506,22 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| ConstDropCandidate, | ConstDropCandidate,
) => false, ) => false,
( (ParamCandidate(other), ParamCandidate(victim)) => {
ParamCandidate((other, other_polarity)), let same_except_bound_vars = other.skip_binder().trait_ref
ParamCandidate((victim, victim_polarity)), == victim.skip_binder().trait_ref
) => { && other.skip_binder().constness == victim.skip_binder().constness
let same_except_bound_vars = other.value.skip_binder() && other.skip_binder().polarity == victim.skip_binder().polarity
== victim.value.skip_binder() && !other.skip_binder().trait_ref.has_escaping_bound_vars();
&& other.constness == victim.constness
&& other_polarity == victim_polarity
&& !other.value.skip_binder().has_escaping_bound_vars();
if same_except_bound_vars { if same_except_bound_vars {
// See issue #84398. In short, we can generate multiple ParamCandidates which are // See issue #84398. In short, we can generate multiple ParamCandidates which are
// the same except for unused bound vars. Just pick the one with the fewest bound vars // the same except for unused bound vars. Just pick the one with the fewest bound vars
// or the current one if tied (they should both evaluate to the same answer). This is // or the current one if tied (they should both evaluate to the same answer). This is
// probably best characterized as a "hack", since we might prefer to just do our // probably best characterized as a "hack", since we might prefer to just do our
// best to *not* create essentially duplicate candidates in the first place. // best to *not* create essentially duplicate candidates in the first place.
other.value.bound_vars().len() <= victim.value.bound_vars().len() other.bound_vars().len() <= victim.bound_vars().len()
} else if other.value == victim.value } else if other.skip_binder().trait_ref == victim.skip_binder().trait_ref
&& victim.constness == ty::BoundConstness::NotConst && victim.skip_binder().constness == ty::BoundConstness::NotConst
&& other_polarity == victim_polarity && other.skip_binder().polarity == victim.skip_binder().polarity
{ {
// Drop otherwise equivalent non-const candidates in favor of const candidates. // Drop otherwise equivalent non-const candidates in favor of const candidates.
true true
@ -1555,11 +1551,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
| TraitAliasCandidate(..) | TraitAliasCandidate(..)
| ObjectCandidate(_) | ObjectCandidate(_)
| ProjectionCandidate(_), | ProjectionCandidate(_),
) => !is_global(&cand.0.value), ) => !is_global(cand),
(ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => { (ObjectCandidate(_) | ProjectionCandidate(_), ParamCandidate(ref cand)) => {
// Prefer these to a global where-clause bound // Prefer these to a global where-clause bound
// (see issue #50825). // (see issue #50825).
is_global(&cand.0.value) is_global(cand)
} }
( (
ImplCandidate(_) ImplCandidate(_)
@ -1575,7 +1571,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
) => { ) => {
// Prefer these to a global where-clause bound // Prefer these to a global where-clause bound
// (see issue #50825). // (see issue #50825).
is_global(&cand.0.value) && other.evaluation.must_apply_modulo_regions() is_global(cand) && other.evaluation.must_apply_modulo_regions()
} }
(ProjectionCandidate(i), ProjectionCandidate(j)) (ProjectionCandidate(i), ProjectionCandidate(j))

View File

@ -508,9 +508,9 @@ crate fn to_pretty_impl_header(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Option<St
Vec::with_capacity(predicates.len() + types_without_default_bounds.len()); Vec::with_capacity(predicates.len() + types_without_default_bounds.len());
for (p, _) in predicates { for (p, _) in predicates {
if let Some(poly_trait_ref) = p.to_opt_poly_trait_ref() { if let Some(poly_trait_ref) = p.to_opt_poly_trait_pred() {
if Some(poly_trait_ref.value.def_id()) == sized_trait { if Some(poly_trait_ref.def_id()) == sized_trait {
types_without_default_bounds.remove(poly_trait_ref.value.self_ty().skip_binder()); types_without_default_bounds.remove(poly_trait_ref.self_ty().skip_binder());
continue; continue;
} }
} }

View File

@ -126,8 +126,8 @@ impl<'tcx> TraitAliasExpander<'tcx> {
let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| { let items = predicates.predicates.iter().rev().filter_map(|(pred, span)| {
pred.subst_supertrait(tcx, &trait_ref) pred.subst_supertrait(tcx, &trait_ref)
.to_opt_poly_trait_ref() .to_opt_poly_trait_pred()
.map(|trait_ref| item.clone_and_push(trait_ref.value, *span)) .map(|trait_ref| item.clone_and_push(trait_ref.map_bound(|t| t.trait_ref), *span))
}); });
debug!("expand_trait_aliases: items={:?}", items.clone()); debug!("expand_trait_aliases: items={:?}", items.clone());
@ -183,8 +183,8 @@ impl Iterator for SupertraitDefIds<'tcx> {
predicates predicates
.predicates .predicates
.iter() .iter()
.filter_map(|(pred, _)| pred.to_opt_poly_trait_ref()) .filter_map(|(pred, _)| pred.to_opt_poly_trait_pred())
.map(|trait_ref| trait_ref.value.def_id()) .map(|trait_ref| trait_ref.def_id())
.filter(|&super_def_id| visited.insert(super_def_id)), .filter(|&super_def_id| visited.insert(super_def_id)),
); );
Some(def_id) Some(def_id)

View File

@ -298,9 +298,10 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
let extend = |obligation: traits::PredicateObligation<'tcx>| { let extend = |obligation: traits::PredicateObligation<'tcx>| {
let mut cause = cause.clone(); let mut cause = cause.clone();
if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() { if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_pred() {
let derived_cause = traits::DerivedObligationCause { let derived_cause = traits::DerivedObligationCause {
parent_trait_ref: parent_trait_ref.value, // TODO: sus
parent_trait_ref: parent_trait_ref.map_bound(|t| t.trait_ref),
parent_code: Lrc::new(obligation.cause.code.clone()), parent_code: Lrc::new(obligation.cause.code.clone()),
}; };
cause.make_mut().code = cause.make_mut().code =

View File

@ -1588,7 +1588,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
traits::transitive_bounds_that_define_assoc_type( traits::transitive_bounds_that_define_assoc_type(
tcx, tcx,
predicates.iter().filter_map(|(p, _)| { predicates.iter().filter_map(|(p, _)| {
p.to_opt_poly_trait_ref().map(|trait_ref| trait_ref.value) Some(p.to_opt_poly_trait_pred()?.map_bound(|t| t.trait_ref))
}), }),
assoc_name, assoc_name,
) )