diff options
Diffstat (limited to 'compiler/rustc_hir_analysis/src/collect/predicates_of.rs')
-rw-r--r-- | compiler/rustc_hir_analysis/src/collect/predicates_of.rs | 200 |
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)); } |