mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 11:48:30 +00:00
Avoid storing the ImplPolarity and Constness next to a TraitRef and use TraitPredicate instead
This commit is contained in:
parent
d161cc2071
commit
a848c4ba3f
@ -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
|
||||||
|
@ -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),
|
||||||
|
|
||||||
|
@ -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(..)
|
||||||
|
@ -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 {
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
||||||
})?);
|
})?);
|
||||||
|
@ -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))
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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)
|
||||||
|
@ -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 =
|
||||||
|
@ -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,
|
||||||
)
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user