summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_ty_utils/src/assoc.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_ty_utils/src/assoc.rs')
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs245
1 files changed, 162 insertions, 83 deletions
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 0648784b2..de1e1a527 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -1,10 +1,10 @@
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
use rustc_hir::definitions::DefPathData;
use rustc_hir::intravisit::{self, Visitor};
-use rustc_middle::ty::{self, DefIdTree, ImplTraitInTraitData, InternalSubsts, TyCtxt};
+use rustc_middle::ty::{self, ImplTraitInTraitData, InternalSubsts, TyCtxt};
use rustc_span::symbol::kw;
pub fn provide(providers: &mut ty::query::Providers) {
@@ -12,20 +12,20 @@ pub fn provide(providers: &mut ty::query::Providers) {
associated_item,
associated_item_def_ids,
associated_items,
- associated_items_for_impl_trait_in_trait,
- associated_item_for_impl_trait_in_trait,
+ associated_types_for_impl_traits_in_associated_fn,
+ associated_type_for_impl_trait_in_trait,
impl_item_implementor_ids,
..*providers
};
}
-fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
- let item = tcx.hir().expect_item(def_id.expect_local());
+fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] {
+ let item = tcx.hir().expect_item(def_id);
match item.kind {
hir::ItemKind::Trait(.., ref trait_item_refs) => {
- if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty {
+ if tcx.lower_impl_trait_in_trait_to_assoc_ty() {
// We collect RPITITs for each trait method's return type and create a
- // corresponding associated item using associated_items_for_impl_trait_in_trait
+ // corresponding associated item using associated_types_for_impl_traits_in_associated_fn
// query.
tcx.arena.alloc_from_iter(
trait_item_refs
@@ -40,7 +40,9 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
.flat_map(|trait_item_ref| {
let trait_fn_def_id =
trait_item_ref.id.owner_id.def_id.to_def_id();
- tcx.associated_items_for_impl_trait_in_trait(trait_fn_def_id)
+ tcx.associated_types_for_impl_traits_in_associated_fn(
+ trait_fn_def_id,
+ )
})
.map(|def_id| *def_id),
),
@@ -54,10 +56,10 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
}
}
hir::ItemKind::Impl(ref impl_) => {
- if tcx.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty {
+ if tcx.lower_impl_trait_in_trait_to_assoc_ty() {
// We collect RPITITs for each trait method's return type, on the impl side too and
// create a corresponding associated item using
- // associated_items_for_impl_trait_in_trait query.
+ // associated_types_for_impl_traits_in_associated_fn query.
tcx.arena.alloc_from_iter(
impl_
.items
@@ -73,7 +75,9 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: DefId) -> &[DefId] {
.flat_map(|impl_item_ref| {
let impl_fn_def_id =
impl_item_ref.id.owner_id.def_id.to_def_id();
- tcx.associated_items_for_impl_trait_in_trait(impl_fn_def_id)
+ tcx.associated_types_for_impl_traits_in_associated_fn(
+ impl_fn_def_id,
+ )
})
.map(|def_id| *def_id)
})),
@@ -97,34 +101,33 @@ fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems {
}
}
-fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> FxHashMap<DefId, DefId> {
+fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> DefIdMap<DefId> {
tcx.associated_items(impl_id)
.in_definition_order()
.filter_map(|item| item.trait_item_def_id.map(|trait_item| (trait_item, item.def_id)))
.collect()
}
-fn associated_item(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItem {
- let id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+fn associated_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AssocItem {
+ let id = tcx.hir().local_def_id_to_hir_id(def_id);
let parent_def_id = tcx.hir().get_parent_item(id);
let parent_item = tcx.hir().expect_item(parent_def_id.def_id);
match parent_item.kind {
hir::ItemKind::Impl(ref impl_) => {
- if let Some(impl_item_ref) =
- impl_.items.iter().find(|i| i.id.owner_id.to_def_id() == def_id)
+ if let Some(impl_item_ref) = impl_.items.iter().find(|i| i.id.owner_id.def_id == def_id)
{
let assoc_item = associated_item_from_impl_item_ref(impl_item_ref);
- debug_assert_eq!(assoc_item.def_id, def_id);
+ debug_assert_eq!(assoc_item.def_id.expect_local(), def_id);
return assoc_item;
}
}
hir::ItemKind::Trait(.., ref trait_item_refs) => {
if let Some(trait_item_ref) =
- trait_item_refs.iter().find(|i| i.id.owner_id.to_def_id() == def_id)
+ trait_item_refs.iter().find(|i| i.id.owner_id.def_id == def_id)
{
let assoc_item = associated_item_from_trait_item_ref(trait_item_ref);
- debug_assert_eq!(assoc_item.def_id, def_id);
+ debug_assert_eq!(assoc_item.def_id.expect_local(), def_id);
return assoc_item;
}
}
@@ -154,6 +157,7 @@ fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty
trait_item_def_id: Some(owner_id.to_def_id()),
container: ty::TraitContainer,
fn_has_self_parameter: has_self,
+ opt_rpitit_info: None,
}
}
@@ -172,40 +176,53 @@ fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::A
trait_item_def_id: impl_item_ref.trait_item_def_id,
container: ty::ImplContainer,
fn_has_self_parameter: has_self,
+ opt_rpitit_info: None,
}
}
-/// Given an `fn_def_id` of a trait or of an impl that implements a given trait:
-/// if `fn_def_id` is the def id of a function defined inside a trait, then it creates and returns
-/// the associated items that correspond to each impl trait in return position for that trait.
-/// if `fn_def_id` is the def id of a function defined inside an impl that implements a trait, then it
-/// creates and returns the associated items that correspond to each impl trait in return position
-/// of the implemented trait.
-fn associated_items_for_impl_trait_in_trait(tcx: TyCtxt<'_>, fn_def_id: DefId) -> &'_ [DefId] {
- let parent_def_id = tcx.parent(fn_def_id);
+/// Given an `fn_def_id` of a trait or a trait implementation:
+///
+/// if `fn_def_id` is a function defined inside a trait, then it synthesizes
+/// a new def id corresponding to a new associated type for each return-
+/// position `impl Trait` in the signature.
+///
+/// if `fn_def_id` is a function inside of an impl, then for each synthetic
+/// associated type generated for the corresponding trait function described
+/// above, synthesize a corresponding associated type in the impl.
+fn associated_types_for_impl_traits_in_associated_fn(
+ tcx: TyCtxt<'_>,
+ fn_def_id: LocalDefId,
+) -> &'_ [DefId] {
+ let parent_def_id = tcx.local_parent(fn_def_id);
match tcx.def_kind(parent_def_id) {
DefKind::Trait => {
- struct RPITVisitor {
- rpits: Vec<LocalDefId>,
+ struct RPITVisitor<'tcx> {
+ rpits: FxIndexSet<LocalDefId>,
+ tcx: TyCtxt<'tcx>,
}
- impl<'v> Visitor<'v> for RPITVisitor {
- fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
- if let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind {
- self.rpits.push(item_id.owner_id.def_id)
+ impl<'tcx> Visitor<'tcx> for RPITVisitor<'tcx> {
+ fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx>) {
+ if let hir::TyKind::OpaqueDef(item_id, _, _) = ty.kind
+ && self.rpits.insert(item_id.owner_id.def_id)
+ {
+ let opaque_item = self.tcx.hir().expect_item(item_id.owner_id.def_id).expect_opaque_ty();
+ for bound in opaque_item.bounds {
+ intravisit::walk_param_bound(self, bound);
+ }
}
intravisit::walk_ty(self, ty)
}
}
- let mut visitor = RPITVisitor { rpits: Vec::new() };
+ let mut visitor = RPITVisitor { tcx, rpits: FxIndexSet::default() };
- if let Some(output) = tcx.hir().get_fn_output(fn_def_id.expect_local()) {
+ if let Some(output) = tcx.hir().get_fn_output(fn_def_id) {
visitor.visit_fn_ret_ty(output);
tcx.arena.alloc_from_iter(visitor.rpits.iter().map(|opaque_ty_def_id| {
- tcx.associated_item_for_impl_trait_in_trait(opaque_ty_def_id).to_def_id()
+ tcx.associated_type_for_impl_trait_in_trait(opaque_ty_def_id).to_def_id()
}))
} else {
&[]
@@ -216,40 +233,40 @@ fn associated_items_for_impl_trait_in_trait(tcx: TyCtxt<'_>, fn_def_id: DefId) -
let Some(trait_fn_def_id) = tcx.associated_item(fn_def_id).trait_item_def_id else { return &[] };
tcx.arena.alloc_from_iter(
- tcx.associated_items_for_impl_trait_in_trait(trait_fn_def_id).iter().map(
- move |trait_assoc_def_id| {
- impl_associated_item_for_impl_trait_in_trait(
- tcx,
- trait_assoc_def_id.expect_local(),
- fn_def_id.expect_local(),
- )
- .to_def_id()
+ tcx.associated_types_for_impl_traits_in_associated_fn(trait_fn_def_id).iter().map(
+ move |&trait_assoc_def_id| {
+ associated_type_for_impl_trait_in_impl(tcx, trait_assoc_def_id, fn_def_id)
+ .to_def_id()
},
),
)
}
def_kind => bug!(
- "associated_items_for_impl_trait_in_trait: {:?} should be Trait or Impl but is {:?}",
+ "associated_types_for_impl_traits_in_associated_fn: {:?} should be Trait or Impl but is {:?}",
parent_def_id,
def_kind
),
}
}
-/// Given an `opaque_ty_def_id` corresponding to an impl trait in trait, create and return the
-/// corresponding associated item.
-fn associated_item_for_impl_trait_in_trait(
+/// Given an `opaque_ty_def_id` corresponding to an `impl Trait` in an associated
+/// function from a trait, synthesize an associated type for that `impl Trait`
+/// that inherits properties that we infer from the method and the opaque type.
+fn associated_type_for_impl_trait_in_trait(
tcx: TyCtxt<'_>,
opaque_ty_def_id: LocalDefId,
) -> LocalDefId {
- let fn_def_id = tcx.impl_trait_in_trait_parent(opaque_ty_def_id.to_def_id());
- let trait_def_id = tcx.parent(fn_def_id);
+ let (hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id)) =
+ tcx.hir().expect_item(opaque_ty_def_id).expect_opaque_ty().origin
+ else {
+ bug!("expected opaque for {opaque_ty_def_id:?}");
+ };
+ let trait_def_id = tcx.local_parent(fn_def_id);
assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
let span = tcx.def_span(opaque_ty_def_id);
- let trait_assoc_ty =
- tcx.at(span).create_def(trait_def_id.expect_local(), DefPathData::ImplTraitAssocTy);
+ let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, DefPathData::ImplTraitAssocTy);
let local_def_id = trait_assoc_ty.def_id();
let def_id = local_def_id.to_def_id();
@@ -263,12 +280,6 @@ fn associated_item_for_impl_trait_in_trait(
// Copy span of the opaque.
trait_assoc_ty.def_ident_span(Some(span));
- // Add the def_id of the function and opaque that generated this synthesized associated type.
- trait_assoc_ty.opt_rpitit_info(Some(ImplTraitInTraitData::Trait {
- fn_def_id,
- opaque_def_id: opaque_ty_def_id.to_def_id(),
- }));
-
trait_assoc_ty.associated_item(ty::AssocItem {
name: kw::Empty,
kind: ty::AssocKind::Type,
@@ -276,6 +287,10 @@ fn associated_item_for_impl_trait_in_trait(
trait_item_def_id: None,
container: ty::TraitContainer,
fn_has_self_parameter: false,
+ opt_rpitit_info: Some(ImplTraitInTraitData::Trait {
+ fn_def_id: fn_def_id.to_def_id(),
+ opaque_def_id: opaque_ty_def_id.to_def_id(),
+ }),
});
// Copy visility of the containing function.
@@ -287,40 +302,70 @@ fn associated_item_for_impl_trait_in_trait(
// Copy type_of of the opaque.
trait_assoc_ty.type_of(ty::EarlyBinder(tcx.mk_opaque(
opaque_ty_def_id.to_def_id(),
- InternalSubsts::identity_for_item(tcx, opaque_ty_def_id.to_def_id()),
+ InternalSubsts::identity_for_item(tcx, opaque_ty_def_id),
)));
- // Copy generics_of of the opaque.
- trait_assoc_ty.generics_of(tcx.generics_of(opaque_ty_def_id).clone());
+ trait_assoc_ty.is_type_alias_impl_trait(false);
+
+ // Copy generics_of of the opaque type item but the trait is the parent.
+ trait_assoc_ty.generics_of({
+ let opaque_ty_generics = tcx.generics_of(opaque_ty_def_id);
+ let opaque_ty_parent_count = opaque_ty_generics.parent_count;
+ let mut params = opaque_ty_generics.params.clone();
+
+ let parent_generics = tcx.generics_of(trait_def_id);
+ let parent_count = parent_generics.parent_count + parent_generics.params.len();
+
+ let mut trait_fn_params = tcx.generics_of(fn_def_id).params.clone();
+
+ for param in &mut params {
+ param.index = param.index + parent_count as u32 + trait_fn_params.len() as u32
+ - opaque_ty_parent_count as u32;
+ }
+
+ trait_fn_params.extend(params);
+ params = trait_fn_params;
+
+ let param_def_id_to_index =
+ params.iter().map(|param| (param.def_id, param.index)).collect();
+
+ ty::Generics {
+ parent: Some(trait_def_id.to_def_id()),
+ parent_count,
+ params,
+ param_def_id_to_index,
+ has_self: false,
+ has_late_bound_regions: opaque_ty_generics.has_late_bound_regions,
+ }
+ });
// There are no predicates for the synthesized associated type.
trait_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
- parent: Some(trait_def_id),
+ parent: Some(trait_def_id.to_def_id()),
predicates: &[],
});
// There are no inferred outlives for the synthesized associated type.
trait_assoc_ty.inferred_outlives_of(&[]);
- // FIXME implement this.
- trait_assoc_ty.explicit_item_bounds(&[]);
-
local_def_id
}
-/// Given an `trait_assoc_def_id` that corresponds to a previously synthesized impl trait in trait
-/// into an associated type and an `impl_def_id` corresponding to an impl block, create and return
-/// the corresponding associated item inside the impl block.
-fn impl_associated_item_for_impl_trait_in_trait(
+/// Given an `trait_assoc_def_id` corresponding to an associated item synthesized
+/// from an `impl Trait` in an associated function from a trait, and an
+/// `impl_fn_def_id` that represents an implementation of the associated function
+/// that the `impl Trait` comes from, synthesize an associated type for that `impl Trait`
+/// that inherits properties that we infer from the method and the associated type.
+fn associated_type_for_impl_trait_in_impl(
tcx: TyCtxt<'_>,
- trait_assoc_def_id: LocalDefId,
+ trait_assoc_def_id: DefId,
impl_fn_def_id: LocalDefId,
) -> LocalDefId {
- let impl_def_id = tcx.local_parent(impl_fn_def_id);
+ let impl_local_def_id = tcx.local_parent(impl_fn_def_id);
// FIXME fix the span, we probably want the def_id of the return type of the function
let span = tcx.def_span(impl_fn_def_id);
- let impl_assoc_ty = tcx.at(span).create_def(impl_def_id, DefPathData::ImplTraitAssocTy);
+ let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, DefPathData::ImplTraitAssocTy);
let local_def_id = impl_assoc_ty.def_id();
let def_id = local_def_id.to_def_id();
@@ -331,27 +376,61 @@ fn impl_associated_item_for_impl_trait_in_trait(
// `opt_local_def_id_to_hir_id` with `None`.
impl_assoc_ty.opt_local_def_id_to_hir_id(None);
- // Add the def_id of the function that generated this synthesized associated type.
- impl_assoc_ty.opt_rpitit_info(Some(ImplTraitInTraitData::Impl {
- fn_def_id: impl_fn_def_id.to_def_id(),
- }));
+ // Copy span of the opaque.
+ impl_assoc_ty.def_ident_span(Some(span));
impl_assoc_ty.associated_item(ty::AssocItem {
name: kw::Empty,
kind: ty::AssocKind::Type,
def_id,
- trait_item_def_id: Some(trait_assoc_def_id.to_def_id()),
+ trait_item_def_id: Some(trait_assoc_def_id),
container: ty::ImplContainer,
fn_has_self_parameter: false,
+ opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }),
});
+ // Copy visility of the containing function.
+ impl_assoc_ty.visibility(tcx.visibility(impl_fn_def_id));
+
// Copy impl_defaultness of the containing function.
impl_assoc_ty.impl_defaultness(tcx.impl_defaultness(impl_fn_def_id));
- // Copy generics_of the trait's associated item.
- // FIXME: This is not correct, in particular the parent is going to be wrong. So we would need
- // to copy from trait_assoc_def_id and adjust things.
- impl_assoc_ty.generics_of(tcx.generics_of(trait_assoc_def_id).clone());
+ // Copy generics_of the trait's associated item but the impl as the parent.
+ // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) resolves to the trait instead of the impl
+ // generics.
+ impl_assoc_ty.generics_of({
+ let trait_assoc_generics = tcx.generics_of(trait_assoc_def_id);
+ let trait_assoc_parent_count = trait_assoc_generics.parent_count;
+ let mut params = trait_assoc_generics.params.clone();
+
+ let parent_generics = tcx.generics_of(impl_local_def_id.to_def_id());
+ let parent_count = parent_generics.parent_count + parent_generics.params.len();
+
+ for param in &mut params {
+ param.index = param.index + parent_count as u32 - trait_assoc_parent_count as u32;
+ }
+
+ let param_def_id_to_index =
+ params.iter().map(|param| (param.def_id, param.index)).collect();
+
+ ty::Generics {
+ parent: Some(impl_local_def_id.to_def_id()),
+ parent_count,
+ params,
+ param_def_id_to_index,
+ has_self: false,
+ has_late_bound_regions: trait_assoc_generics.has_late_bound_regions,
+ }
+ });
+
+ // There are no predicates for the synthesized associated type.
+ impl_assoc_ty.explicit_predicates_of(ty::GenericPredicates {
+ parent: Some(impl_local_def_id.to_def_id()),
+ predicates: &[],
+ });
+
+ // There are no inferred outlives for the synthesized associated type.
+ impl_assoc_ty.inferred_outlives_of(&[]);
local_def_id
}