Auto merge of #132196 - compiler-errors:probe_ty_param_bounds, r=petrochenkov
Some where clause lowering simplifications Rename `PredicateFilter::SelfThatDefines` to `PredicateFilter::SelfTraitThatDefines` to make it clear that it's only concerned with converting *traits*, and make it do a bit less work when converting bounds. Also, make the predicate filter matching in `probe_ty_param_bounds_in_generics` explicit, and simply the args it receives a bit.
This commit is contained in:
commit
5ca0e9fa9b
@ -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);
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -606,12 +610,8 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
|
|||||||
let mut bounds = Bounds::default();
|
let mut bounds = Bounds::default();
|
||||||
icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter);
|
icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter);
|
||||||
|
|
||||||
let where_bounds_that_match = icx.probe_ty_param_bounds_in_generics(
|
let where_bounds_that_match =
|
||||||
generics,
|
icx.probe_ty_param_bounds_in_generics(generics, item.owner_id.def_id, filter);
|
||||||
item.owner_id.def_id,
|
|
||||||
self_param_ty,
|
|
||||||
filter,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Combine the two lists to form the complete set of superbounds:
|
// Combine the two lists to form the complete set of superbounds:
|
||||||
let implied_bounds =
|
let implied_bounds =
|
||||||
@ -652,7 +652,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Make sure when elaborating supertraits, probing for associated types, etc.,
|
// Make sure when elaborating supertraits, probing for associated types, etc.,
|
||||||
// we really truly are elaborating clauses that have `Self` as their self type.
|
// we really truly are elaborating clauses that have `ty` as their self type.
|
||||||
// This is very important since downstream code relies on this being correct.
|
// This is very important since downstream code relies on this being correct.
|
||||||
pub(super) fn assert_only_contains_predicates_from<'tcx>(
|
pub(super) fn assert_only_contains_predicates_from<'tcx>(
|
||||||
filter: PredicateFilter,
|
filter: PredicateFilter,
|
||||||
@ -664,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) => {
|
||||||
@ -704,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() {
|
||||||
@ -767,21 +794,16 @@ pub(super) fn type_param_predicates<'tcx>(
|
|||||||
None => {}
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
use rustc_hir::*;
|
|
||||||
use rustc_middle::ty::Ty;
|
|
||||||
|
|
||||||
// In the HIR, bounds can derive from two places. Either
|
// In the HIR, bounds can derive from two places. Either
|
||||||
// written inline like `<T: Foo>` or in a where-clause like
|
// written inline like `<T: Foo>` or in a where-clause like
|
||||||
// `where T: Foo`.
|
// `where T: Foo`.
|
||||||
|
|
||||||
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()];
|
|
||||||
let ty = Ty::new_param(tcx, index, tcx.hir().ty_param_name(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())
|
||||||
@ -801,8 +823,9 @@ 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 hir::ItemKind::Trait(..) = item.kind
|
||||||
// Implied `Self: Trait` and supertrait bounds.
|
// Implied `Self: Trait` and supertrait bounds.
|
||||||
&& param_id == item_hir_id
|
&& param_id == item_hir_id
|
||||||
{
|
{
|
||||||
@ -811,23 +834,34 @@ 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,
|
||||||
ty,
|
PredicateFilter::SelfTraitThatDefines(assoc_name),
|
||||||
PredicateFilter::SelfThatDefines(assoc_name),
|
));
|
||||||
)
|
|
||||||
.into_iter()
|
let bounds =
|
||||||
.filter(|(predicate, _)| match predicate.kind().skip_binder() {
|
&*tcx.arena.alloc_from_iter(result.skip_binder().iter().copied().chain(extra_predicates));
|
||||||
ty::ClauseKind::Trait(data) => data.self_ty().is_param(index),
|
|
||||||
_ => false,
|
// Double check that the bounds *only* contain `SelfTy: Trait` preds.
|
||||||
}),
|
let self_ty = match tcx.def_kind(def_id) {
|
||||||
|
DefKind::TyParam => Ty::new_param(
|
||||||
|
tcx,
|
||||||
|
tcx.generics_of(item_def_id)
|
||||||
|
.param_def_id_to_index(tcx, def_id.to_def_id())
|
||||||
|
.expect("expected generic param to be owned by item"),
|
||||||
|
tcx.item_name(def_id.to_def_id()),
|
||||||
|
),
|
||||||
|
DefKind::Trait | DefKind::TraitAlias => tcx.types.self_param,
|
||||||
|
_ => unreachable!(),
|
||||||
|
};
|
||||||
|
assert_only_contains_predicates_from(
|
||||||
|
PredicateFilter::SelfTraitThatDefines(assoc_name),
|
||||||
|
bounds,
|
||||||
|
self_ty,
|
||||||
);
|
);
|
||||||
|
|
||||||
ty::EarlyBinder::bind(
|
ty::EarlyBinder::bind(bounds)
|
||||||
tcx.arena.alloc_from_iter(result.skip_binder().iter().copied().chain(extra_predicates)),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> ItemCtxt<'tcx> {
|
impl<'tcx> ItemCtxt<'tcx> {
|
||||||
@ -841,7 +875,6 @@ fn probe_ty_param_bounds_in_generics(
|
|||||||
&self,
|
&self,
|
||||||
hir_generics: &'tcx hir::Generics<'tcx>,
|
hir_generics: &'tcx hir::Generics<'tcx>,
|
||||||
param_def_id: LocalDefId,
|
param_def_id: LocalDefId,
|
||||||
ty: Ty<'tcx>,
|
|
||||||
filter: PredicateFilter,
|
filter: PredicateFilter,
|
||||||
) -> Vec<(ty::Clause<'tcx>, Span)> {
|
) -> Vec<(ty::Clause<'tcx>, Span)> {
|
||||||
let mut bounds = Bounds::default();
|
let mut bounds = Bounds::default();
|
||||||
@ -851,13 +884,21 @@ fn probe_ty_param_bounds_in_generics(
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let bound_ty = if predicate.is_param_bound(param_def_id.to_def_id()) {
|
match filter {
|
||||||
ty
|
_ if predicate.is_param_bound(param_def_id.to_def_id()) => {
|
||||||
} else if matches!(filter, PredicateFilter::All) {
|
// Ok
|
||||||
self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty)
|
}
|
||||||
} else {
|
PredicateFilter::All => {
|
||||||
continue;
|
// Ok
|
||||||
};
|
}
|
||||||
|
PredicateFilter::SelfOnly
|
||||||
|
| PredicateFilter::SelfTraitThatDefines(_)
|
||||||
|
| PredicateFilter::SelfConstIfConst
|
||||||
|
| PredicateFilter::SelfAndAssociatedTypeBounds => continue,
|
||||||
|
PredicateFilter::ConstIfConst => unreachable!(),
|
||||||
|
}
|
||||||
|
|
||||||
|
let bound_ty = self.lowerer().lower_ty_maybe_return_type_notation(predicate.bounded_ty);
|
||||||
|
|
||||||
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_bounds(
|
self.lowerer().lower_bounds(
|
||||||
|
@ -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)
|
||||||
@ -389,7 +389,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,
|
||||||
@ -400,6 +399,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 => {}
|
||||||
}
|
}
|
||||||
@ -426,7 +427,7 @@ pub(super) fn lower_assoc_item_constraint(
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
PredicateFilter::SelfOnly
|
PredicateFilter::SelfOnly
|
||||||
| PredicateFilter::SelfThatDefines(_)
|
| PredicateFilter::SelfTraitThatDefines(_)
|
||||||
| PredicateFilter::SelfConstIfConst => {}
|
| PredicateFilter::SelfConstIfConst => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,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`
|
||||||
@ -730,9 +730,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);
|
||||||
|
Loading…
Reference in New Issue
Block a user