summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_hir_analysis/src/collect/predicates_of.rs')
-rw-r--r--compiler/rustc_hir_analysis/src/collect/predicates_of.rs200
1 files changed, 125 insertions, 75 deletions
diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
index 2badd66e3..9358ed612 100644
--- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs
@@ -62,15 +62,16 @@ pub(super) fn predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredic
/// Returns a list of user-specified type predicates for the definition with ID `def_id`.
/// N.B., this does not include any implied/inferred constraints.
#[instrument(level = "trace", skip(tcx), ret)]
-fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericPredicates<'_> {
+fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::GenericPredicates<'_> {
use rustc_hir::*;
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let node = tcx.hir().get(hir_id);
let mut is_trait = None;
let mut is_default_impl_trait = None;
+ // FIXME: Should ItemCtxt take a LocalDefId?
let icx = ItemCtxt::new(tcx, def_id);
const NO_GENERICS: &hir::Generics<'_> = hir::Generics::empty();
@@ -99,7 +100,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
| ItemKind::Union(_, generics) => generics,
ItemKind::Trait(_, _, generics, ..) | ItemKind::TraitAlias(generics, _) => {
- is_trait = Some(ty::TraitRef::identity(tcx, def_id));
+ is_trait = Some(ty::TraitRef::identity(tcx, def_id.to_def_id()));
generics
}
ItemKind::OpaqueTy(OpaqueTy { generics, .. }) => generics,
@@ -124,7 +125,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
// on a trait we need to add in the supertrait bounds and bounds found on
// associated types.
if let Some(_trait_ref) = is_trait {
- predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned());
+ predicates.extend(tcx.implied_predicates_of(def_id).predicates.iter().cloned());
}
// In default impls, we can assume that the self type implements
@@ -253,7 +254,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::GenericP
}
if tcx.features().generic_const_exprs {
- predicates.extend(const_evaluatable_predicates_of(tcx, def_id.expect_local()));
+ predicates.extend(const_evaluatable_predicates_of(tcx, def_id));
}
let mut predicates: Vec<_> = predicates.into_iter().collect();
@@ -392,18 +393,18 @@ pub(super) fn trait_explicit_predicates_and_bounds(
def_id: LocalDefId,
) -> ty::GenericPredicates<'_> {
assert_eq!(tcx.def_kind(def_id), DefKind::Trait);
- gather_explicit_predicates_of(tcx, def_id.to_def_id())
+ gather_explicit_predicates_of(tcx, def_id)
}
pub(super) fn explicit_predicates_of<'tcx>(
tcx: TyCtxt<'tcx>,
- def_id: DefId,
+ def_id: LocalDefId,
) -> ty::GenericPredicates<'tcx> {
let def_kind = tcx.def_kind(def_id);
if let DefKind::Trait = def_kind {
// Remove bounds on associated types from the predicates, they will be
// returned by `explicit_item_bounds`.
- let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id.expect_local());
+ let predicates_and_bounds = tcx.trait_explicit_predicates_and_bounds(def_id);
let trait_identity_substs = InternalSubsts::identity_for_item(tcx, def_id);
let is_assoc_item_ty = |ty: Ty<'tcx>| {
@@ -418,7 +419,8 @@ pub(super) fn explicit_predicates_of<'tcx>(
// supertrait).
if let ty::Alias(ty::Projection, projection) = ty.kind() {
projection.substs == trait_identity_substs
- && tcx.associated_item(projection.def_id).container_id(tcx) == def_id
+ && tcx.associated_item(projection.def_id).container_id(tcx)
+ == def_id.to_def_id()
} else {
false
}
@@ -449,7 +451,7 @@ pub(super) fn explicit_predicates_of<'tcx>(
}
} else {
if matches!(def_kind, DefKind::AnonConst) && tcx.lazy_normalization() {
- let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+ let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let parent_def_id = tcx.hir().get_parent_item(hir_id);
if let Some(defaulted_param_def_id) =
@@ -532,89 +534,136 @@ pub(super) fn explicit_predicates_of<'tcx>(
}
}
+#[derive(Copy, Clone, Debug)]
+pub enum PredicateFilter {
+ /// All predicates may be implied by the trait
+ All,
+
+ /// Only traits that reference `Self: ..` are implied by the trait
+ SelfOnly,
+
+ /// Only traits that reference `Self: ..` and define an associated type
+ /// with the given ident are implied by the trait
+ SelfThatDefines(Ident),
+}
+
/// Ensures that the super-predicates of the trait with a `DefId`
/// of `trait_def_id` are converted and stored. This also ensures that
/// the transitive super-predicates are converted.
pub(super) fn super_predicates_of(
tcx: TyCtxt<'_>,
- trait_def_id: DefId,
+ trait_def_id: LocalDefId,
+) -> ty::GenericPredicates<'_> {
+ implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::SelfOnly)
+}
+
+pub(super) fn super_predicates_that_define_assoc_type(
+ tcx: TyCtxt<'_>,
+ (trait_def_id, assoc_name): (DefId, Ident),
+) -> ty::GenericPredicates<'_> {
+ implied_predicates_with_filter(tcx, trait_def_id, PredicateFilter::SelfThatDefines(assoc_name))
+}
+
+pub(super) fn implied_predicates_of(
+ tcx: TyCtxt<'_>,
+ trait_def_id: LocalDefId,
) -> ty::GenericPredicates<'_> {
- tcx.super_predicates_that_define_assoc_type((trait_def_id, None))
+ if tcx.is_trait_alias(trait_def_id.to_def_id()) {
+ implied_predicates_with_filter(tcx, trait_def_id.to_def_id(), PredicateFilter::All)
+ } else {
+ tcx.super_predicates_of(trait_def_id)
+ }
}
/// Ensures that the super-predicates of the trait with a `DefId`
/// of `trait_def_id` are converted and stored. This also ensures that
/// the transitive super-predicates are converted.
-pub(super) fn super_predicates_that_define_assoc_type(
+pub(super) fn implied_predicates_with_filter(
tcx: TyCtxt<'_>,
- (trait_def_id, assoc_name): (DefId, Option<Ident>),
+ trait_def_id: DefId,
+ filter: PredicateFilter,
) -> ty::GenericPredicates<'_> {
- if trait_def_id.is_local() {
- debug!("local trait");
- let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id.expect_local());
-
- let Node::Item(item) = tcx.hir().get(trait_hir_id) else {
- bug!("trait_node_id {} is not an item", trait_hir_id);
- };
+ 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
+ // external provider
+ assert!(matches!(filter, PredicateFilter::SelfThatDefines(_)));
+ return tcx.super_predicates_of(trait_def_id);
+ };
- let (generics, bounds) = match item.kind {
- hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits),
- hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits),
- _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
- };
+ let trait_hir_id = tcx.hir().local_def_id_to_hir_id(trait_def_id);
- let icx = ItemCtxt::new(tcx, trait_def_id);
+ let Node::Item(item) = tcx.hir().get(trait_hir_id) else {
+ bug!("trait_node_id {} is not an item", trait_hir_id);
+ };
- // Convert the bounds that follow the colon, e.g., `Bar + Zed` in `trait Foo: Bar + Zed`.
- let self_param_ty = tcx.types.self_param;
- let superbounds1 = if let Some(assoc_name) = assoc_name {
- icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name)
- } else {
- icx.astconv().compute_bounds(self_param_ty, bounds)
- };
+ let (generics, bounds) = match item.kind {
+ hir::ItemKind::Trait(.., generics, supertraits, _) => (generics, supertraits),
+ hir::ItemKind::TraitAlias(generics, supertraits) => (generics, supertraits),
+ _ => span_bug!(item.span, "super_predicates invoked on non-trait"),
+ };
- let superbounds1 = superbounds1.predicates();
-
- // Convert any explicit superbounds in the where-clause,
- // e.g., `trait Foo where Self: Bar`.
- // In the case of trait aliases, however, we include all bounds in the where-clause,
- // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>`
- // as one of its "superpredicates".
- let is_trait_alias = tcx.is_trait_alias(trait_def_id);
- let superbounds2 = icx.type_parameter_bounds_in_generics(
- generics,
- item.owner_id.def_id,
- self_param_ty,
- OnlySelfBounds(!is_trait_alias),
- assoc_name,
- );
+ let icx = ItemCtxt::new(tcx, trait_def_id);
+
+ let self_param_ty = tcx.types.self_param;
+ let (superbounds, where_bounds_that_match) = match filter {
+ PredicateFilter::All => (
+ // Convert the bounds that follow the colon (or equal in trait aliases)
+ icx.astconv().compute_bounds(self_param_ty, bounds),
+ // Also include all where clause bounds
+ icx.type_parameter_bounds_in_generics(
+ generics,
+ item.owner_id.def_id,
+ self_param_ty,
+ OnlySelfBounds(false),
+ None,
+ ),
+ ),
+ PredicateFilter::SelfOnly => (
+ // Convert the bounds that follow the colon (or equal in trait aliases)
+ icx.astconv().compute_bounds(self_param_ty, bounds),
+ // Include where clause bounds for `Self`
+ icx.type_parameter_bounds_in_generics(
+ generics,
+ item.owner_id.def_id,
+ self_param_ty,
+ OnlySelfBounds(true),
+ None,
+ ),
+ ),
+ PredicateFilter::SelfThatDefines(assoc_name) => (
+ // Convert the bounds that follow the colon (or equal) that reference the associated name
+ icx.astconv().compute_bounds_that_match_assoc_type(self_param_ty, bounds, assoc_name),
+ // Include where clause bounds for `Self` that reference the associated name
+ icx.type_parameter_bounds_in_generics(
+ generics,
+ item.owner_id.def_id,
+ self_param_ty,
+ OnlySelfBounds(true),
+ Some(assoc_name),
+ ),
+ ),
+ };
- // Combine the two lists to form the complete set of superbounds:
- let superbounds = &*tcx.arena.alloc_from_iter(superbounds1.into_iter().chain(superbounds2));
- debug!(?superbounds);
+ // Combine the two lists to form the complete set of superbounds:
+ let implied_bounds = &*tcx
+ .arena
+ .alloc_from_iter(superbounds.predicates().into_iter().chain(where_bounds_that_match));
+ debug!(?implied_bounds);
+ // Now require that immediate supertraits are converted,
+ // which will, in turn, reach indirect supertraits.
+ if matches!(filter, PredicateFilter::SelfOnly) {
// Now require that immediate supertraits are converted,
// which will, in turn, reach indirect supertraits.
- if assoc_name.is_none() {
- // Now require that immediate supertraits are converted,
- // which will, in turn, reach indirect supertraits.
- for &(pred, span) in superbounds {
- debug!("superbound: {:?}", pred);
- if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) =
- pred.kind().skip_binder()
- {
- tcx.at(span).super_predicates_of(bound.def_id());
- }
+ for &(pred, span) in implied_bounds {
+ debug!("superbound: {:?}", pred);
+ if let ty::PredicateKind::Clause(ty::Clause::Trait(bound)) = pred.kind().skip_binder() {
+ tcx.at(span).super_predicates_of(bound.def_id());
}
}
-
- ty::GenericPredicates { parent: None, predicates: superbounds }
- } else {
- // if `assoc_name` is None, then the query should've been redirected to an
- // external provider
- assert!(assoc_name.is_some());
- tcx.super_predicates_of(trait_def_id)
}
+
+ ty::GenericPredicates { parent: None, predicates: implied_bounds }
}
/// Returns the predicates defined on `item_def_id` of the form
@@ -622,7 +671,7 @@ pub(super) fn super_predicates_that_define_assoc_type(
#[instrument(level = "trace", skip(tcx))]
pub(super) fn type_param_predicates(
tcx: TyCtxt<'_>,
- (item_def_id, def_id, assoc_name): (DefId, LocalDefId, Ident),
+ (item_def_id, def_id, assoc_name): (LocalDefId, LocalDefId, Ident),
) -> ty::GenericPredicates<'_> {
use rustc_hir::*;
@@ -637,21 +686,21 @@ pub(super) fn type_param_predicates(
let ty = tcx.mk_ty_param(index, tcx.hir().ty_param_name(def_id));
// Don't look for bounds where the type parameter isn't in scope.
- let parent = if item_def_id == param_owner.to_def_id() {
+ let parent = if item_def_id == param_owner {
None
} else {
- tcx.generics_of(item_def_id).parent
+ tcx.generics_of(item_def_id).parent.map(|def_id| def_id.expect_local())
};
let mut result = parent
.map(|parent| {
let icx = ItemCtxt::new(tcx, parent);
- icx.get_type_parameter_bounds(DUMMY_SP, def_id.to_def_id(), assoc_name)
+ icx.get_type_parameter_bounds(DUMMY_SP, def_id, assoc_name)
})
.unwrap_or_default();
let mut extend = None;
- let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id.expect_local());
+ let item_hir_id = tcx.hir().local_def_id_to_hir_id(item_def_id);
let ast_generics = match tcx.hir().get(item_hir_id) {
Node::TraitItem(item) => &item.generics,
@@ -673,7 +722,8 @@ pub(super) fn type_param_predicates(
ItemKind::Trait(_, _, generics, ..) => {
// Implied `Self: Trait` and supertrait bounds.
if param_id == item_hir_id {
- let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id);
+ let identity_trait_ref =
+ ty::TraitRef::identity(tcx, item_def_id.to_def_id());
extend =
Some((identity_trait_ref.without_const().to_predicate(tcx), item.span));
}