Make SelfTraitThatDefines a tighter filter

This commit is contained in:
Michael Goulet 2024-10-26 19:25:10 +00:00
parent ac67d295b9
commit 697eda5f9a
4 changed files with 55 additions and 27 deletions

View File

@ -43,7 +43,7 @@ fn associated_type_bounds<'tcx>(
match filter { match filter {
PredicateFilter::All PredicateFilter::All
| PredicateFilter::SelfOnly | PredicateFilter::SelfOnly
| PredicateFilter::SelfThatDefines(_) | PredicateFilter::SelfTraitThatDefines(_)
| PredicateFilter::SelfAndAssociatedTypeBounds => { | PredicateFilter::SelfAndAssociatedTypeBounds => {
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span); icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);
} }
@ -122,7 +122,7 @@ fn remap_gat_vars_and_recurse_into_nested_projections<'tcx>(
PredicateFilter::SelfOnly => { PredicateFilter::SelfOnly => {
return None; return None;
} }
PredicateFilter::SelfThatDefines(_) PredicateFilter::SelfTraitThatDefines(_)
| PredicateFilter::SelfConstIfConst | PredicateFilter::SelfConstIfConst
| PredicateFilter::SelfAndAssociatedTypeBounds | PredicateFilter::SelfAndAssociatedTypeBounds
| PredicateFilter::ConstIfConst => { | PredicateFilter::ConstIfConst => {
@ -329,7 +329,7 @@ fn opaque_type_bounds<'tcx>(
match filter { match filter {
PredicateFilter::All PredicateFilter::All
| PredicateFilter::SelfOnly | PredicateFilter::SelfOnly
| PredicateFilter::SelfThatDefines(_) | PredicateFilter::SelfTraitThatDefines(_)
| PredicateFilter::SelfAndAssociatedTypeBounds => { | PredicateFilter::SelfAndAssociatedTypeBounds => {
// Associated types are implicitly sized unless a `?Sized` bound is found // Associated types are implicitly sized unless a `?Sized` bound is found
icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span); icx.lowerer().add_sized_bound(&mut bounds, item_ty, hir_bounds, None, span);

View File

@ -557,7 +557,11 @@ pub(super) fn explicit_supertraits_containing_assoc_item<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
(trait_def_id, assoc_name): (DefId, Ident), (trait_def_id, assoc_name): (DefId, Ident),
) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> { ) -> ty::EarlyBinder<'tcx, &'tcx [(ty::Clause<'tcx>, Span)]> {
implied_predicates_with_filter(tcx, trait_def_id, PredicateFilter::SelfThatDefines(assoc_name)) implied_predicates_with_filter(
tcx,
trait_def_id,
PredicateFilter::SelfTraitThatDefines(assoc_name),
)
} }
pub(super) fn explicit_implied_predicates_of<'tcx>( pub(super) fn explicit_implied_predicates_of<'tcx>(
@ -586,7 +590,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
let Some(trait_def_id) = trait_def_id.as_local() else { let Some(trait_def_id) = trait_def_id.as_local() else {
// if `assoc_name` is None, then the query should've been redirected to an // if `assoc_name` is None, then the query should've been redirected to an
// external provider // external provider
assert_matches!(filter, PredicateFilter::SelfThatDefines(_)); assert_matches!(filter, PredicateFilter::SelfTraitThatDefines(_));
return tcx.explicit_super_predicates_of(trait_def_id); return tcx.explicit_super_predicates_of(trait_def_id);
}; };
@ -660,7 +664,7 @@ pub(super) fn assert_only_contains_predicates_from<'tcx>(
} }
match filter { match filter {
PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => { PredicateFilter::SelfOnly => {
for (clause, _) in bounds { for (clause, _) in bounds {
match clause.kind().skip_binder() { match clause.kind().skip_binder() {
ty::ClauseKind::Trait(trait_predicate) => { ty::ClauseKind::Trait(trait_predicate) => {
@ -700,6 +704,33 @@ pub(super) fn assert_only_contains_predicates_from<'tcx>(
} }
} }
} }
PredicateFilter::SelfTraitThatDefines(_) => {
for (clause, _) in bounds {
match clause.kind().skip_binder() {
ty::ClauseKind::Trait(trait_predicate) => {
assert_eq!(
trait_predicate.self_ty(),
ty,
"expected `Self` predicate when computing \
`{filter:?}` implied bounds: {clause:?}"
);
}
ty::ClauseKind::Projection(_)
| ty::ClauseKind::TypeOutlives(_)
| ty::ClauseKind::RegionOutlives(_)
| ty::ClauseKind::ConstArgHasType(_, _)
| ty::ClauseKind::WellFormed(_)
| ty::ClauseKind::ConstEvaluatable(_)
| ty::ClauseKind::HostEffect(..) => {
bug!(
"unexpected non-`Self` predicate when computing \
`{filter:?}` implied bounds: {clause:?}"
);
}
}
}
}
PredicateFilter::ConstIfConst => { PredicateFilter::ConstIfConst => {
for (clause, _) in bounds { for (clause, _) in bounds {
match clause.kind().skip_binder() { match clause.kind().skip_binder() {
@ -771,11 +802,10 @@ pub(super) fn type_param_predicates<'tcx>(
let param_id = tcx.local_def_id_to_hir_id(def_id); let param_id = tcx.local_def_id_to_hir_id(def_id);
let param_owner = tcx.hir().ty_param_owner(def_id); let param_owner = tcx.hir().ty_param_owner(def_id);
let generics = tcx.generics_of(param_owner);
let index = generics.param_def_id_to_index[&def_id.to_def_id()];
// Don't look for bounds where the type parameter isn't in scope. // Don't look for bounds where the type parameter isn't in scope.
let parent = if item_def_id == param_owner { let parent = if item_def_id == param_owner {
// FIXME: Shouldn't this be unreachable?
None None
} else { } else {
tcx.generics_of(item_def_id).parent.map(|def_id| def_id.expect_local()) tcx.generics_of(item_def_id).parent.map(|def_id| def_id.expect_local())
@ -795,6 +825,7 @@ pub(super) fn type_param_predicates<'tcx>(
let Some(hir_generics) = hir_node.generics() else { let Some(hir_generics) = hir_node.generics() else {
return result; return result;
}; };
if let Node::Item(item) = hir_node if let Node::Item(item) = hir_node
&& let ItemKind::Trait(..) = item.kind && let ItemKind::Trait(..) = item.kind
// Implied `Self: Trait` and supertrait bounds. // Implied `Self: Trait` and supertrait bounds.
@ -805,18 +836,11 @@ pub(super) fn type_param_predicates<'tcx>(
} }
let icx = ItemCtxt::new(tcx, item_def_id); let icx = ItemCtxt::new(tcx, item_def_id);
let extra_predicates = extend.into_iter().chain( let extra_predicates = extend.into_iter().chain(icx.probe_ty_param_bounds_in_generics(
icx.probe_ty_param_bounds_in_generics(
hir_generics, hir_generics,
def_id, def_id,
PredicateFilter::SelfThatDefines(assoc_name), PredicateFilter::SelfTraitThatDefines(assoc_name),
) ));
.into_iter()
.filter(|(predicate, _)| match predicate.kind().skip_binder() {
ty::ClauseKind::Trait(data) => data.self_ty().is_param(index),
_ => false,
}),
);
ty::EarlyBinder::bind( ty::EarlyBinder::bind(
tcx.arena.alloc_from_iter(result.skip_binder().iter().copied().chain(extra_predicates)), tcx.arena.alloc_from_iter(result.skip_binder().iter().copied().chain(extra_predicates)),
@ -851,7 +875,7 @@ fn probe_ty_param_bounds_in_generics(
// Ok // Ok
} }
PredicateFilter::SelfOnly PredicateFilter::SelfOnly
| PredicateFilter::SelfThatDefines(_) | PredicateFilter::SelfTraitThatDefines(_)
| PredicateFilter::SelfConstIfConst | PredicateFilter::SelfConstIfConst
| PredicateFilter::SelfAndAssociatedTypeBounds => continue, | PredicateFilter::SelfAndAssociatedTypeBounds => continue,
PredicateFilter::ConstIfConst => unreachable!(), PredicateFilter::ConstIfConst => unreachable!(),

View File

@ -152,9 +152,9 @@ pub(crate) fn lower_bounds<'hir, I: IntoIterator<Item = &'hir hir::GenericBound<
'tcx: 'hir, 'tcx: 'hir,
{ {
for hir_bound in hir_bounds { for hir_bound in hir_bounds {
// In order to avoid cycles, when we're lowering `SelfThatDefines`, // In order to avoid cycles, when we're lowering `SelfTraitThatDefines`,
// we skip over any traits that don't define the given associated type. // we skip over any traits that don't define the given associated type.
if let PredicateFilter::SelfThatDefines(assoc_name) = predicate_filter { if let PredicateFilter::SelfTraitThatDefines(assoc_name) = predicate_filter {
if let Some(trait_ref) = hir_bound.trait_ref() if let Some(trait_ref) = hir_bound.trait_ref()
&& let Some(trait_did) = trait_ref.trait_def_id() && let Some(trait_did) = trait_ref.trait_def_id()
&& self.tcx().trait_may_define_assoc_item(trait_did, assoc_name) && self.tcx().trait_may_define_assoc_item(trait_did, assoc_name)
@ -395,7 +395,6 @@ pub(super) fn lower_assoc_item_constraint(
match predicate_filter { match predicate_filter {
PredicateFilter::All PredicateFilter::All
| PredicateFilter::SelfOnly | PredicateFilter::SelfOnly
| PredicateFilter::SelfThatDefines(_)
| PredicateFilter::SelfAndAssociatedTypeBounds => { | PredicateFilter::SelfAndAssociatedTypeBounds => {
bounds.push_projection_bound( bounds.push_projection_bound(
tcx, tcx,
@ -406,6 +405,8 @@ pub(super) fn lower_assoc_item_constraint(
constraint.span, constraint.span,
); );
} }
// SelfTraitThatDefines is only interested in trait predicates.
PredicateFilter::SelfTraitThatDefines(_) => {}
// `ConstIfConst` is only interested in `~const` bounds. // `ConstIfConst` is only interested in `~const` bounds.
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {} PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
} }
@ -432,7 +433,7 @@ pub(super) fn lower_assoc_item_constraint(
); );
} }
PredicateFilter::SelfOnly PredicateFilter::SelfOnly
| PredicateFilter::SelfThatDefines(_) | PredicateFilter::SelfTraitThatDefines(_)
| PredicateFilter::SelfConstIfConst => {} | PredicateFilter::SelfConstIfConst => {}
} }
} }

View File

@ -75,7 +75,7 @@ pub enum PredicateFilter {
/// Only traits that reference `Self: ..` and define an associated type /// Only traits that reference `Self: ..` and define an associated type
/// with the given ident are implied by the trait. This mode exists to /// with the given ident are implied by the trait. This mode exists to
/// side-step query cycles when lowering associated types. /// side-step query cycles when lowering associated types.
SelfThatDefines(Ident), SelfTraitThatDefines(Ident),
/// Only traits that reference `Self: ..` and their associated type bounds. /// Only traits that reference `Self: ..` and their associated type bounds.
/// For example, given `Self: Tr<A: B>`, this would expand to `Self: Tr` /// For example, given `Self: Tr<A: B>`, this would expand to `Self: Tr`
@ -708,9 +708,12 @@ pub(crate) fn lower_poly_trait_ref(
); );
match predicate_filter { match predicate_filter {
// This is only concerned with trait predicates.
PredicateFilter::SelfTraitThatDefines(..) => {
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
}
PredicateFilter::All PredicateFilter::All
| PredicateFilter::SelfOnly | PredicateFilter::SelfOnly
| PredicateFilter::SelfThatDefines(..)
| PredicateFilter::SelfAndAssociatedTypeBounds => { | PredicateFilter::SelfAndAssociatedTypeBounds => {
debug!(?poly_trait_ref); debug!(?poly_trait_ref);
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity); bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);