Use PredicateFilter instead of OnlySelfBounds

This commit is contained in:
Michael Goulet 2024-10-19 11:13:11 -04:00
parent a2a1206811
commit 9989b1b0d5
5 changed files with 61 additions and 95 deletions

View File

@ -9,7 +9,7 @@
use rustc_span::Span; use rustc_span::Span;
use rustc_span::def_id::DefId; use rustc_span::def_id::DefId;
use crate::hir_ty_lowering::OnlySelfBounds; use crate::hir_ty_lowering::PredicateFilter;
/// Collects together a list of type bounds. These lists of bounds occur in many places /// Collects together a list of type bounds. These lists of bounds occur in many places
/// in Rust's syntax: /// in Rust's syntax:
@ -52,7 +52,7 @@ pub(crate) fn push_trait_bound(
span: Span, span: Span,
polarity: ty::PredicatePolarity, polarity: ty::PredicatePolarity,
constness: ty::BoundConstness, constness: ty::BoundConstness,
only_self_bounds: OnlySelfBounds, predicate_filter: PredicateFilter,
) { ) {
let clause = ( let clause = (
bound_trait_ref bound_trait_ref
@ -72,9 +72,18 @@ pub(crate) fn push_trait_bound(
// FIXME(effects): Lift this out of `push_trait_bound`, and move it somewhere else. // FIXME(effects): Lift this out of `push_trait_bound`, and move it somewhere else.
// Perhaps moving this into `lower_poly_trait_ref`, just like we lower associated // Perhaps moving this into `lower_poly_trait_ref`, just like we lower associated
// type bounds. // type bounds.
if !tcx.features().effects || only_self_bounds.0 { if !tcx.features().effects {
return; return;
} }
match predicate_filter {
PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {
return;
}
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
// Ok.
}
}
// For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the // For `T: ~const Tr` or `T: const Tr`, we need to add an additional bound on the
// associated type of `<T as Tr>` and make sure that the effect is compatible. // associated type of `<T as Tr>` and make sure that the effect is compatible.
let compat_val = match (tcx.def_kind(defining_def_id), constness) { let compat_val = match (tcx.def_kind(defining_def_id), constness) {

View File

@ -16,7 +16,7 @@
use crate::collect::ItemCtxt; use crate::collect::ItemCtxt;
use crate::constrained_generic_params as cgp; use crate::constrained_generic_params as cgp;
use crate::delegation::inherit_predicates_for_delegation_item; use crate::delegation::inherit_predicates_for_delegation_item;
use crate::hir_ty_lowering::{HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason}; use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter, RegionInferReason};
/// Returns a list of all type predicates (explicit and implicit) for the definition with /// Returns a list of all type predicates (explicit and implicit) for the definition with
/// ID `def_id`. This includes all predicates returned by `explicit_predicates_of`, plus /// ID `def_id`. This includes all predicates returned by `explicit_predicates_of`, plus
@ -270,7 +270,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
bound_pred.bounds.iter(), bound_pred.bounds.iter(),
&mut bounds, &mut bounds,
bound_vars, bound_vars,
OnlySelfBounds(false), PredicateFilter::All,
); );
predicates.extend(bounds.clauses(tcx)); predicates.extend(bounds.clauses(tcx));
effects_min_tys.extend(bounds.effects_min_tys()); effects_min_tys.extend(bounds.effects_min_tys());
@ -825,20 +825,6 @@ fn probe_ty_param_bounds_in_generics(
continue; continue;
}; };
// Subtle: If we're collecting `SelfAndAssociatedTypeBounds`, then we
// want to only consider predicates with `Self: ...`, but we don't want
// `OnlySelfBounds(true)` since we want to collect the nested associated
// type bound as well.
let (only_self_bounds, assoc_name) = match filter {
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
(OnlySelfBounds(false), None)
}
PredicateFilter::SelfOnly => (OnlySelfBounds(true), None),
PredicateFilter::SelfThatDefines(assoc_name) => {
(OnlySelfBounds(true), Some(assoc_name))
}
};
let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) { let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
ty ty
} else if matches!(filter, PredicateFilter::All) { } else if matches!(filter, PredicateFilter::All) {
@ -850,31 +836,13 @@ fn probe_ty_param_bounds_in_generics(
let bound_vars = self.tcx.late_bound_vars(predicate.hir_id); let bound_vars = self.tcx.late_bound_vars(predicate.hir_id);
self.lowerer().lower_poly_bounds( self.lowerer().lower_poly_bounds(
bound_ty, bound_ty,
predicate.bounds.iter().filter(|bound| { predicate.bounds.iter(),
assoc_name
.map_or(true, |assoc_name| self.bound_defines_assoc_item(bound, assoc_name))
}),
&mut bounds, &mut bounds,
bound_vars, bound_vars,
only_self_bounds, filter,
); );
} }
bounds.clauses(self.tcx).collect() bounds.clauses(self.tcx).collect()
} }
#[instrument(level = "trace", skip(self))]
fn bound_defines_assoc_item(&self, b: &hir::GenericBound<'_>, assoc_name: Ident) -> bool {
match b {
hir::GenericBound::Trait(poly_trait_ref) => {
let trait_ref = &poly_trait_ref.trait_ref;
if let Some(trait_did) = trait_ref.trait_def_id() {
self.tcx.trait_may_define_assoc_item(trait_did, assoc_name)
} else {
false
}
}
_ => false,
}
}
} }

View File

@ -19,9 +19,7 @@
use super::errors::GenericsArgsErrExtend; use super::errors::GenericsArgsErrExtend;
use crate::bounds::Bounds; use crate::bounds::Bounds;
use crate::errors; use crate::errors;
use crate::hir_ty_lowering::{ use crate::hir_ty_lowering::{AssocItemQSelf, HirTyLowerer, PredicateFilter, RegionInferReason};
AssocItemQSelf, HirTyLowerer, OnlySelfBounds, PredicateFilter, RegionInferReason,
};
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
/// Add a `Sized` bound to the `bounds` if appropriate. /// Add a `Sized` bound to the `bounds` if appropriate.
@ -150,11 +148,25 @@ pub(crate) fn lower_poly_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound
hir_bounds: I, hir_bounds: I,
bounds: &mut Bounds<'tcx>, bounds: &mut Bounds<'tcx>,
bound_vars: &'tcx ty::List<ty::BoundVariableKind>, bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
only_self_bounds: OnlySelfBounds, predicate_filter: PredicateFilter,
) where ) where
'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`,
// we skip over any traits that don't define the given associated type.
if let PredicateFilter::SelfThatDefines(assoc_name) = predicate_filter {
if let Some(trait_ref) = hir_bound.trait_ref()
&& let Some(trait_did) = trait_ref.trait_def_id()
&& self.tcx().trait_may_define_assoc_item(trait_did, assoc_name)
{
// Okay
} else {
continue;
}
}
match hir_bound { match hir_bound {
hir::GenericBound::Trait(poly_trait_ref) => { hir::GenericBound::Trait(poly_trait_ref) => {
let (constness, polarity) = match poly_trait_ref.modifiers { let (constness, polarity) = match poly_trait_ref.modifiers {
@ -179,7 +191,7 @@ pub(crate) fn lower_poly_bounds<'hir, I: Iterator<Item = &'hir hir::GenericBound
polarity, polarity,
param_ty, param_ty,
bounds, bounds,
only_self_bounds, predicate_filter,
); );
} }
hir::GenericBound::Outlives(lifetime) => { hir::GenericBound::Outlives(lifetime) => {
@ -213,37 +225,16 @@ pub(crate) fn lower_mono_bounds(
&self, &self,
param_ty: Ty<'tcx>, param_ty: Ty<'tcx>,
hir_bounds: &[hir::GenericBound<'tcx>], hir_bounds: &[hir::GenericBound<'tcx>],
filter: PredicateFilter, predicate_filter: PredicateFilter,
) -> Bounds<'tcx> { ) -> Bounds<'tcx> {
let mut bounds = Bounds::default(); let mut bounds = Bounds::default();
let only_self_bounds = match filter {
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
OnlySelfBounds(false)
}
PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => OnlySelfBounds(true),
};
self.lower_poly_bounds( self.lower_poly_bounds(
param_ty, param_ty,
hir_bounds.iter().filter(|bound| match filter { hir_bounds.iter(),
PredicateFilter::All
| PredicateFilter::SelfOnly
| PredicateFilter::SelfAndAssociatedTypeBounds => true,
PredicateFilter::SelfThatDefines(assoc_name) => {
if let Some(trait_ref) = bound.trait_ref()
&& let Some(trait_did) = trait_ref.trait_def_id()
&& self.tcx().trait_may_define_assoc_item(trait_did, assoc_name)
{
true
} else {
false
}
}
}),
&mut bounds, &mut bounds,
ty::List::empty(), ty::List::empty(),
only_self_bounds, predicate_filter,
); );
debug!(?bounds); debug!(?bounds);
@ -267,7 +258,7 @@ pub(super) fn lower_assoc_item_constraint(
bounds: &mut Bounds<'tcx>, bounds: &mut Bounds<'tcx>,
duplicates: &mut FxIndexMap<DefId, Span>, duplicates: &mut FxIndexMap<DefId, Span>,
path_span: Span, path_span: Span,
only_self_bounds: OnlySelfBounds, predicate_filter: PredicateFilter,
) -> Result<(), ErrorGuaranteed> { ) -> Result<(), ErrorGuaranteed> {
let tcx = self.tcx(); let tcx = self.tcx();
@ -444,24 +435,26 @@ pub(super) fn lower_assoc_item_constraint(
// Lower a constraint like `Item: Debug` as found in HIR bound `T: Iterator<Item: Debug>` // Lower a constraint like `Item: Debug` as found in HIR bound `T: Iterator<Item: Debug>`
// to a bound involving a projection: `<T as Iterator>::Item: Debug`. // to a bound involving a projection: `<T as Iterator>::Item: Debug`.
hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => { hir::AssocItemConstraintKind::Bound { bounds: hir_bounds } => {
// NOTE: If `only_self_bounds` is true, do NOT expand this associated type bound into match predicate_filter {
// a trait predicate, since we only want to add predicates for the `Self` type. PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => {}
if !only_self_bounds.0 { PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
let projection_ty = projection_term let projection_ty = projection_term
.map_bound(|projection_term| projection_term.expect_ty(self.tcx())); .map_bound(|projection_term| projection_term.expect_ty(self.tcx()));
// Calling `skip_binder` is okay, because `lower_bounds` expects the `param_ty` // Calling `skip_binder` is okay, because `lower_bounds` expects the `param_ty`
// parameter to have a skipped binder. // parameter to have a skipped binder.
let param_ty = Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder()); let param_ty =
Ty::new_alias(tcx, ty::Projection, projection_ty.skip_binder());
self.lower_poly_bounds( self.lower_poly_bounds(
param_ty, param_ty,
hir_bounds.iter(), hir_bounds.iter(),
bounds, bounds,
projection_ty.bound_vars(), projection_ty.bound_vars(),
only_self_bounds, predicate_filter,
); );
} }
} }
} }
}
Ok(()) Ok(())
} }

View File

@ -20,7 +20,7 @@
use super::HirTyLowerer; use super::HirTyLowerer;
use crate::bounds::Bounds; use crate::bounds::Bounds;
use crate::hir_ty_lowering::{ use crate::hir_ty_lowering::{
GenericArgCountMismatch, GenericArgCountResult, OnlySelfBounds, RegionInferReason, GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason,
}; };
impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
@ -55,9 +55,7 @@ pub(super) fn lower_trait_object_ty(
ty::PredicatePolarity::Positive, ty::PredicatePolarity::Positive,
dummy_self, dummy_self,
&mut bounds, &mut bounds,
// True so we don't populate `bounds` with associated type bounds, even PredicateFilter::SelfOnly,
// though they're disallowed from object types.
OnlySelfBounds(true),
) { ) {
potential_assoc_types.extend(cur_potential_assoc_types); potential_assoc_types.extend(cur_potential_assoc_types);
} }

View File

@ -64,9 +64,6 @@
#[derive(Debug)] #[derive(Debug)]
pub struct GenericPathSegment(pub DefId, pub usize); pub struct GenericPathSegment(pub DefId, pub usize);
#[derive(Copy, Clone, Debug)]
pub struct OnlySelfBounds(pub bool);
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum PredicateFilter { pub enum PredicateFilter {
/// All predicates may be implied by the trait. /// All predicates may be implied by the trait.
@ -76,7 +73,8 @@ pub enum PredicateFilter {
SelfOnly, SelfOnly,
/// 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. /// with the given ident are implied by the trait. This mode exists to
/// side-step query cycles when lowering associated types.
SelfThatDefines(Ident), SelfThatDefines(Ident),
/// Only traits that reference `Self: ..` and their associated type bounds. /// Only traits that reference `Self: ..` and their associated type bounds.
@ -683,7 +681,7 @@ pub(crate) fn lower_poly_trait_ref(
polarity: ty::PredicatePolarity, polarity: ty::PredicatePolarity,
self_ty: Ty<'tcx>, self_ty: Ty<'tcx>,
bounds: &mut Bounds<'tcx>, bounds: &mut Bounds<'tcx>,
only_self_bounds: OnlySelfBounds, predicate_filter: PredicateFilter,
) -> GenericArgCountResult { ) -> GenericArgCountResult {
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise()); let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
let trait_segment = trait_ref.path.segments.last().unwrap(); let trait_segment = trait_ref.path.segments.last().unwrap();
@ -720,7 +718,7 @@ pub(crate) fn lower_poly_trait_ref(
span, span,
polarity, polarity,
constness, constness,
only_self_bounds, predicate_filter,
); );
let mut dup_constraints = FxIndexMap::default(); let mut dup_constraints = FxIndexMap::default();
@ -744,7 +742,7 @@ pub(crate) fn lower_poly_trait_ref(
bounds, bounds,
&mut dup_constraints, &mut dup_constraints,
constraint.span, constraint.span,
only_self_bounds, predicate_filter,
); );
// Okay to ignore `Err` because of `ErrorGuaranteed` (see above). // Okay to ignore `Err` because of `ErrorGuaranteed` (see above).
} }