2023-03-21 18:06:04 +00:00
|
|
|
use rustc_data_structures::fx::FxIndexSet;
|
2024-03-19 09:00:57 +00:00
|
|
|
use rustc_hir as hir;
|
2022-12-16 20:15:34 +00:00
|
|
|
use rustc_hir::def::DefKind;
|
2023-02-21 10:35:19 +00:00
|
|
|
use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
|
2022-10-26 19:38:32 +00:00
|
|
|
use rustc_hir::intravisit::{self, Visitor};
|
2023-05-15 04:24:45 +00:00
|
|
|
use rustc_middle::query::Providers;
|
2024-06-14 12:16:15 +00:00
|
|
|
use rustc_middle::ty::{self, ImplTraitInTraitData, Ty, TyCtxt};
|
2024-05-08 10:35:52 +00:00
|
|
|
use rustc_middle::{bug, span_bug};
|
2024-06-14 12:16:15 +00:00
|
|
|
use rustc_span::sym;
|
2023-02-28 16:05:37 +00:00
|
|
|
use rustc_span::symbol::kw;
|
2021-11-18 21:44:45 +00:00
|
|
|
|
2023-11-16 06:08:27 +00:00
|
|
|
pub(crate) fn provide(providers: &mut Providers) {
|
2023-05-15 04:24:45 +00:00
|
|
|
*providers = Providers {
|
2021-11-18 21:44:45 +00:00
|
|
|
associated_item,
|
|
|
|
associated_item_def_ids,
|
|
|
|
associated_items,
|
2023-03-17 03:45:14 +00:00
|
|
|
associated_types_for_impl_traits_in_associated_fn,
|
2024-06-14 12:16:15 +00:00
|
|
|
associated_type_for_effects,
|
2023-03-17 03:45:14 +00:00
|
|
|
associated_type_for_impl_trait_in_trait,
|
2021-11-18 22:29:07 +00:00
|
|
|
impl_item_implementor_ids,
|
2021-11-18 21:44:45 +00:00
|
|
|
..*providers
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2023-03-13 18:54:05 +00:00
|
|
|
fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] {
|
|
|
|
let item = tcx.hir().expect_item(def_id);
|
2021-11-18 21:44:45 +00:00
|
|
|
match item.kind {
|
2023-11-21 19:07:32 +00:00
|
|
|
hir::ItemKind::Trait(.., trait_item_refs) => {
|
2023-06-24 03:00:08 +00:00
|
|
|
// We collect RPITITs for each trait method's return type and create a
|
|
|
|
// corresponding associated item using associated_types_for_impl_traits_in_associated_fn
|
|
|
|
// query.
|
|
|
|
tcx.arena.alloc_from_iter(
|
|
|
|
trait_item_refs
|
|
|
|
.iter()
|
|
|
|
.map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id())
|
|
|
|
.chain(
|
|
|
|
trait_item_refs
|
|
|
|
.iter()
|
|
|
|
.filter(|trait_item_ref| {
|
|
|
|
matches!(trait_item_ref.kind, hir::AssocItemKind::Fn { .. })
|
|
|
|
})
|
|
|
|
.flat_map(|trait_item_ref| {
|
|
|
|
let trait_fn_def_id = trait_item_ref.id.owner_id.def_id.to_def_id();
|
|
|
|
tcx.associated_types_for_impl_traits_in_associated_fn(
|
|
|
|
trait_fn_def_id,
|
|
|
|
)
|
|
|
|
})
|
2023-11-03 16:18:19 +00:00
|
|
|
.copied(),
|
2024-06-14 12:16:15 +00:00
|
|
|
)
|
|
|
|
.chain(tcx.associated_type_for_effects(def_id)),
|
2023-06-24 03:00:08 +00:00
|
|
|
)
|
2023-02-28 16:05:37 +00:00
|
|
|
}
|
2023-11-21 19:07:32 +00:00
|
|
|
hir::ItemKind::Impl(impl_) => {
|
2023-06-24 03:00:08 +00:00
|
|
|
// We collect RPITITs for each trait method's return type, on the impl side too and
|
|
|
|
// create a corresponding associated item using
|
|
|
|
// associated_types_for_impl_traits_in_associated_fn query.
|
|
|
|
tcx.arena.alloc_from_iter(
|
|
|
|
impl_
|
|
|
|
.items
|
|
|
|
.iter()
|
|
|
|
.map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id())
|
|
|
|
.chain(impl_.of_trait.iter().flat_map(|_| {
|
|
|
|
impl_
|
|
|
|
.items
|
|
|
|
.iter()
|
|
|
|
.filter(|impl_item_ref| {
|
|
|
|
matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. })
|
|
|
|
})
|
|
|
|
.flat_map(|impl_item_ref| {
|
|
|
|
let impl_fn_def_id = impl_item_ref.id.owner_id.def_id.to_def_id();
|
|
|
|
tcx.associated_types_for_impl_traits_in_associated_fn(
|
|
|
|
impl_fn_def_id,
|
|
|
|
)
|
|
|
|
})
|
2023-11-03 16:18:19 +00:00
|
|
|
.copied()
|
2024-06-14 12:16:15 +00:00
|
|
|
}))
|
|
|
|
.chain(tcx.associated_type_for_effects(def_id)),
|
2023-06-24 03:00:08 +00:00
|
|
|
)
|
2023-03-02 19:20:48 +00:00
|
|
|
}
|
2021-11-18 21:44:45 +00:00
|
|
|
_ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-06 08:57:34 +00:00
|
|
|
fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems {
|
2023-02-05 12:28:12 +00:00
|
|
|
if tcx.is_trait_alias(def_id) {
|
|
|
|
ty::AssocItems::new(Vec::new())
|
|
|
|
} else {
|
|
|
|
let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did));
|
|
|
|
ty::AssocItems::new(items)
|
|
|
|
}
|
2021-11-18 21:44:45 +00:00
|
|
|
}
|
|
|
|
|
2023-02-21 10:35:19 +00:00
|
|
|
fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> DefIdMap<DefId> {
|
2021-11-18 22:29:07 +00:00
|
|
|
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()
|
|
|
|
}
|
|
|
|
|
2023-03-13 18:54:05 +00:00
|
|
|
fn associated_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AssocItem {
|
2023-11-24 16:28:19 +00:00
|
|
|
let id = tcx.local_def_id_to_hir_id(def_id);
|
2021-10-21 17:41:47 +00:00
|
|
|
let parent_def_id = tcx.hir().get_parent_item(id);
|
2022-09-20 05:11:23 +00:00
|
|
|
let parent_item = tcx.hir().expect_item(parent_def_id.def_id);
|
2021-11-18 21:44:45 +00:00
|
|
|
match parent_item.kind {
|
2023-11-21 19:07:32 +00:00
|
|
|
hir::ItemKind::Impl(impl_) => {
|
2023-03-13 18:54:05 +00:00
|
|
|
if let Some(impl_item_ref) = impl_.items.iter().find(|i| i.id.owner_id.def_id == def_id)
|
2021-11-18 21:44:45 +00:00
|
|
|
{
|
2022-03-12 23:52:25 +00:00
|
|
|
let assoc_item = associated_item_from_impl_item_ref(impl_item_ref);
|
2023-03-13 18:54:05 +00:00
|
|
|
debug_assert_eq!(assoc_item.def_id.expect_local(), def_id);
|
2021-11-18 21:44:45 +00:00
|
|
|
return assoc_item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-11-21 19:07:32 +00:00
|
|
|
hir::ItemKind::Trait(.., trait_item_refs) => {
|
2021-11-18 21:44:45 +00:00
|
|
|
if let Some(trait_item_ref) =
|
2023-03-13 18:54:05 +00:00
|
|
|
trait_item_refs.iter().find(|i| i.id.owner_id.def_id == def_id)
|
2021-11-18 21:44:45 +00:00
|
|
|
{
|
2022-03-12 23:52:25 +00:00
|
|
|
let assoc_item = associated_item_from_trait_item_ref(trait_item_ref);
|
2023-03-13 18:54:05 +00:00
|
|
|
debug_assert_eq!(assoc_item.def_id.expect_local(), def_id);
|
2021-11-18 21:44:45 +00:00
|
|
|
return assoc_item;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
span_bug!(
|
|
|
|
parent_item.span,
|
|
|
|
"unexpected parent of trait or impl item or item not found: {:?}",
|
|
|
|
parent_item.kind
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-03-12 23:52:25 +00:00
|
|
|
fn associated_item_from_trait_item_ref(trait_item_ref: &hir::TraitItemRef) -> ty::AssocItem {
|
2022-10-27 03:02:18 +00:00
|
|
|
let owner_id = trait_item_ref.id.owner_id;
|
2021-11-18 21:44:45 +00:00
|
|
|
let (kind, has_self) = match trait_item_ref.kind {
|
|
|
|
hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
|
|
|
|
hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
|
|
|
|
hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
|
|
|
|
};
|
|
|
|
|
|
|
|
ty::AssocItem {
|
2022-01-13 02:15:51 +00:00
|
|
|
name: trait_item_ref.ident.name,
|
2021-11-18 21:44:45 +00:00
|
|
|
kind,
|
2022-10-27 03:02:18 +00:00
|
|
|
def_id: owner_id.to_def_id(),
|
|
|
|
trait_item_def_id: Some(owner_id.to_def_id()),
|
2022-03-12 23:52:25 +00:00
|
|
|
container: ty::TraitContainer,
|
2021-11-18 21:44:45 +00:00
|
|
|
fn_has_self_parameter: has_self,
|
2023-03-12 20:32:50 +00:00
|
|
|
opt_rpitit_info: None,
|
2024-06-14 12:16:15 +00:00
|
|
|
is_effects_desugaring: false,
|
2021-11-18 21:44:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-03-12 23:52:25 +00:00
|
|
|
fn associated_item_from_impl_item_ref(impl_item_ref: &hir::ImplItemRef) -> ty::AssocItem {
|
2022-10-27 03:02:18 +00:00
|
|
|
let def_id = impl_item_ref.id.owner_id;
|
2021-11-18 21:44:45 +00:00
|
|
|
let (kind, has_self) = match impl_item_ref.kind {
|
|
|
|
hir::AssocItemKind::Const => (ty::AssocKind::Const, false),
|
|
|
|
hir::AssocItemKind::Fn { has_self } => (ty::AssocKind::Fn, has_self),
|
|
|
|
hir::AssocItemKind::Type => (ty::AssocKind::Type, false),
|
|
|
|
};
|
|
|
|
|
|
|
|
ty::AssocItem {
|
2022-01-13 02:15:51 +00:00
|
|
|
name: impl_item_ref.ident.name,
|
2021-11-18 21:44:45 +00:00
|
|
|
kind,
|
|
|
|
def_id: def_id.to_def_id(),
|
2022-01-08 11:22:06 +00:00
|
|
|
trait_item_def_id: impl_item_ref.trait_item_def_id,
|
2022-03-12 23:52:25 +00:00
|
|
|
container: ty::ImplContainer,
|
2021-11-18 21:44:45 +00:00
|
|
|
fn_has_self_parameter: has_self,
|
2023-03-12 20:32:50 +00:00
|
|
|
opt_rpitit_info: None,
|
2024-06-14 12:16:15 +00:00
|
|
|
is_effects_desugaring: false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Given an `def_id` of a trait or a trait impl:
|
|
|
|
///
|
|
|
|
/// If `def_id` is a trait that has `#[const_trait]`, then it synthesizes
|
|
|
|
/// a new def id corresponding to a new associated type for the effects.
|
|
|
|
///
|
|
|
|
/// If `def_id` is an impl, then synthesize the associated type according
|
|
|
|
/// to the constness of the impl.
|
|
|
|
fn associated_type_for_effects(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option<DefId> {
|
2024-06-25 07:52:44 +00:00
|
|
|
// don't synthesize the associated type even if the user has written `const_trait`
|
|
|
|
// if the effects feature is disabled.
|
|
|
|
if !tcx.features().effects {
|
|
|
|
return None;
|
|
|
|
}
|
2024-06-14 12:16:15 +00:00
|
|
|
match tcx.def_kind(def_id) {
|
|
|
|
DefKind::Trait => {
|
|
|
|
let trait_def_id = def_id;
|
|
|
|
let Some(attr) = tcx.get_attr(def_id, sym::const_trait) else {
|
|
|
|
return None;
|
|
|
|
};
|
|
|
|
|
|
|
|
let span = attr.span;
|
|
|
|
let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, kw::Empty, DefKind::AssocTy);
|
|
|
|
|
|
|
|
let local_def_id = trait_assoc_ty.def_id();
|
|
|
|
let def_id = local_def_id.to_def_id();
|
|
|
|
|
|
|
|
trait_assoc_ty.feed_hir();
|
|
|
|
|
|
|
|
// Copy span of the attribute.
|
|
|
|
trait_assoc_ty.def_ident_span(Some(span));
|
|
|
|
|
|
|
|
trait_assoc_ty.associated_item(ty::AssocItem {
|
|
|
|
name: kw::Empty,
|
|
|
|
kind: ty::AssocKind::Type,
|
|
|
|
def_id,
|
|
|
|
trait_item_def_id: None,
|
|
|
|
container: ty::TraitContainer,
|
|
|
|
fn_has_self_parameter: false,
|
|
|
|
opt_rpitit_info: None,
|
|
|
|
is_effects_desugaring: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
// visibility is public.
|
|
|
|
trait_assoc_ty.visibility(ty::Visibility::Public);
|
|
|
|
|
|
|
|
// No default type
|
|
|
|
trait_assoc_ty.defaultness(hir::Defaultness::Default { has_value: false });
|
|
|
|
|
|
|
|
trait_assoc_ty.is_type_alias_impl_trait(false);
|
|
|
|
|
|
|
|
// Copy generics_of of the trait, making the trait as parent.
|
|
|
|
trait_assoc_ty.generics_of({
|
|
|
|
let parent_generics = tcx.generics_of(trait_def_id);
|
|
|
|
let parent_count = parent_generics.parent_count + parent_generics.own_params.len();
|
|
|
|
|
|
|
|
ty::Generics {
|
|
|
|
parent: Some(trait_def_id.to_def_id()),
|
|
|
|
parent_count,
|
|
|
|
own_params: vec![],
|
|
|
|
param_def_id_to_index: parent_generics.param_def_id_to_index.clone(),
|
|
|
|
has_self: false,
|
|
|
|
has_late_bound_regions: None,
|
|
|
|
host_effect_index: parent_generics.host_effect_index,
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
trait_assoc_ty.explicit_item_bounds(ty::EarlyBinder::bind(&[]));
|
|
|
|
trait_assoc_ty.explicit_item_super_predicates(ty::EarlyBinder::bind(&[]));
|
|
|
|
|
|
|
|
// There are no inferred outlives for the synthesized associated type.
|
|
|
|
trait_assoc_ty.inferred_outlives_of(&[]);
|
|
|
|
|
|
|
|
Some(def_id)
|
|
|
|
}
|
|
|
|
DefKind::Impl { .. } => {
|
|
|
|
let impl_def_id = def_id;
|
|
|
|
let Some(trait_id) = tcx.trait_id_of_impl(def_id.to_def_id()) else { return None };
|
|
|
|
|
|
|
|
// first get the DefId of the assoc type on the trait, if there is not,
|
|
|
|
// then we don't need to generate it on the impl.
|
|
|
|
let Some(trait_assoc_id) = tcx.associated_type_for_effects(trait_id) else {
|
|
|
|
return None;
|
|
|
|
};
|
|
|
|
|
|
|
|
// TODO span is bad
|
|
|
|
let span = tcx.def_ident_span(def_id).unwrap();
|
|
|
|
|
|
|
|
let impl_assoc_ty = tcx.at(span).create_def(def_id, kw::Empty, DefKind::AssocTy);
|
|
|
|
|
|
|
|
let local_def_id = impl_assoc_ty.def_id();
|
|
|
|
let def_id = local_def_id.to_def_id();
|
|
|
|
|
|
|
|
impl_assoc_ty.feed_hir();
|
|
|
|
|
|
|
|
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_id),
|
|
|
|
container: ty::ImplContainer,
|
|
|
|
fn_has_self_parameter: false,
|
|
|
|
opt_rpitit_info: None,
|
|
|
|
is_effects_desugaring: true,
|
|
|
|
});
|
|
|
|
|
|
|
|
// visibility is public.
|
|
|
|
impl_assoc_ty.visibility(ty::Visibility::Public);
|
|
|
|
|
|
|
|
// no default value.
|
|
|
|
impl_assoc_ty.defaultness(hir::Defaultness::Final);
|
|
|
|
|
|
|
|
// set the type of the associated type! If this is a const impl,
|
|
|
|
// we set to Maybe, otherwise we set to `Runtime`.
|
|
|
|
let type_def_id = if tcx.is_const_trait_impl_raw(impl_def_id.to_def_id()) {
|
|
|
|
tcx.require_lang_item(hir::LangItem::EffectsMaybe, Some(span))
|
|
|
|
} else {
|
|
|
|
tcx.require_lang_item(hir::LangItem::EffectsRuntime, Some(span))
|
|
|
|
};
|
|
|
|
// TODO this is wrong
|
|
|
|
impl_assoc_ty.type_of(ty::EarlyBinder::bind(Ty::new_adt(
|
|
|
|
tcx,
|
|
|
|
tcx.adt_def(type_def_id),
|
|
|
|
ty::GenericArgs::empty(),
|
|
|
|
)));
|
|
|
|
|
|
|
|
// Copy generics_of of the impl, making the impl as parent.
|
|
|
|
impl_assoc_ty.generics_of({
|
|
|
|
let parent_generics = tcx.generics_of(impl_def_id);
|
|
|
|
let parent_count = parent_generics.parent_count + parent_generics.own_params.len();
|
|
|
|
|
|
|
|
ty::Generics {
|
|
|
|
parent: Some(impl_def_id.to_def_id()),
|
|
|
|
parent_count,
|
|
|
|
own_params: vec![],
|
|
|
|
param_def_id_to_index: parent_generics.param_def_id_to_index.clone(),
|
|
|
|
has_self: false,
|
|
|
|
has_late_bound_regions: None,
|
|
|
|
host_effect_index: parent_generics.host_effect_index,
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
2024-06-25 07:52:44 +00:00
|
|
|
// impl_assoc_ty.explicit_item_bounds(ty::EarlyBinder::bind(&[]));
|
2024-06-14 12:16:15 +00:00
|
|
|
impl_assoc_ty.explicit_item_super_predicates(ty::EarlyBinder::bind(&[]));
|
|
|
|
|
|
|
|
// There are no inferred outlives for the synthesized associated type.
|
|
|
|
impl_assoc_ty.inferred_outlives_of(&[]);
|
|
|
|
|
|
|
|
Some(def_id)
|
|
|
|
}
|
|
|
|
def_kind => bug!(
|
|
|
|
"associated_type_for_effects: {:?} should be Trait or Impl but is {:?}",
|
|
|
|
def_id,
|
|
|
|
def_kind
|
|
|
|
),
|
2021-11-18 21:44:45 +00:00
|
|
|
}
|
|
|
|
}
|
2022-10-26 19:38:32 +00:00
|
|
|
|
2023-03-17 03:45:14 +00:00
|
|
|
/// 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<'_>,
|
2023-03-13 18:54:05 +00:00
|
|
|
fn_def_id: LocalDefId,
|
2023-03-17 03:45:14 +00:00
|
|
|
) -> &'_ [DefId] {
|
2023-03-13 18:54:05 +00:00
|
|
|
let parent_def_id = tcx.local_parent(fn_def_id);
|
2022-10-26 19:38:32 +00:00
|
|
|
|
2023-02-16 21:12:53 +00:00
|
|
|
match tcx.def_kind(parent_def_id) {
|
|
|
|
DefKind::Trait => {
|
2023-03-21 18:06:04 +00:00
|
|
|
struct RPITVisitor<'tcx> {
|
|
|
|
rpits: FxIndexSet<LocalDefId>,
|
|
|
|
tcx: TyCtxt<'tcx>,
|
2022-10-26 19:38:32 +00:00
|
|
|
}
|
|
|
|
|
2023-03-21 18:06:04 +00:00
|
|
|
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);
|
|
|
|
}
|
2023-02-16 21:12:53 +00:00
|
|
|
}
|
|
|
|
intravisit::walk_ty(self, ty)
|
|
|
|
}
|
|
|
|
}
|
2022-10-26 19:38:32 +00:00
|
|
|
|
2023-03-21 18:06:04 +00:00
|
|
|
let mut visitor = RPITVisitor { tcx, rpits: FxIndexSet::default() };
|
2022-10-26 19:38:32 +00:00
|
|
|
|
2023-03-13 18:54:05 +00:00
|
|
|
if let Some(output) = tcx.hir().get_fn_output(fn_def_id) {
|
2023-02-16 21:12:53 +00:00
|
|
|
visitor.visit_fn_ret_ty(output);
|
|
|
|
|
|
|
|
tcx.arena.alloc_from_iter(visitor.rpits.iter().map(|opaque_ty_def_id| {
|
2023-03-17 03:45:14 +00:00
|
|
|
tcx.associated_type_for_impl_trait_in_trait(opaque_ty_def_id).to_def_id()
|
2023-02-16 21:12:53 +00:00
|
|
|
}))
|
|
|
|
} else {
|
|
|
|
&[]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
DefKind::Impl { .. } => {
|
|
|
|
let Some(trait_fn_def_id) = tcx.associated_item(fn_def_id).trait_item_def_id else {
|
|
|
|
return &[];
|
|
|
|
};
|
|
|
|
|
|
|
|
tcx.arena.alloc_from_iter(
|
2023-03-17 03:45:14 +00:00
|
|
|
tcx.associated_types_for_impl_traits_in_associated_fn(trait_fn_def_id).iter().map(
|
2023-03-21 18:06:04 +00:00
|
|
|
move |&trait_assoc_def_id| {
|
|
|
|
associated_type_for_impl_trait_in_impl(tcx, trait_assoc_def_id, fn_def_id)
|
|
|
|
.to_def_id()
|
2023-02-16 21:12:53 +00:00
|
|
|
},
|
|
|
|
),
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
|
|
|
def_kind => bug!(
|
2023-03-17 03:45:14 +00:00
|
|
|
"associated_types_for_impl_traits_in_associated_fn: {:?} should be Trait or Impl but is {:?}",
|
2023-02-16 21:12:53 +00:00
|
|
|
parent_def_id,
|
|
|
|
def_kind
|
|
|
|
),
|
2022-10-26 19:38:32 +00:00
|
|
|
}
|
|
|
|
}
|
2022-12-16 20:15:34 +00:00
|
|
|
|
2023-03-17 03:45:14 +00:00
|
|
|
/// 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(
|
2022-12-16 20:15:34 +00:00
|
|
|
tcx: TyCtxt<'_>,
|
|
|
|
opaque_ty_def_id: LocalDefId,
|
|
|
|
) -> LocalDefId {
|
2023-03-20 17:05:46 +00:00
|
|
|
let (hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id)) =
|
2023-06-15 07:40:17 +00:00
|
|
|
tcx.opaque_type_origin(opaque_ty_def_id)
|
2023-03-20 17:05:46 +00:00
|
|
|
else {
|
|
|
|
bug!("expected opaque for {opaque_ty_def_id:?}");
|
|
|
|
};
|
|
|
|
let trait_def_id = tcx.local_parent(fn_def_id);
|
2022-12-16 20:15:34 +00:00
|
|
|
assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
|
|
|
|
|
|
|
|
let span = tcx.def_span(opaque_ty_def_id);
|
2023-12-03 09:29:59 +00:00
|
|
|
let trait_assoc_ty = tcx.at(span).create_def(trait_def_id, kw::Empty, DefKind::AssocTy);
|
2023-02-28 16:05:37 +00:00
|
|
|
|
|
|
|
let local_def_id = trait_assoc_ty.def_id();
|
|
|
|
let def_id = local_def_id.to_def_id();
|
|
|
|
|
2024-03-19 09:00:57 +00:00
|
|
|
trait_assoc_ty.feed_hir();
|
2023-02-28 16:05:37 +00:00
|
|
|
|
|
|
|
// Copy span of the opaque.
|
|
|
|
trait_assoc_ty.def_ident_span(Some(span));
|
|
|
|
|
|
|
|
trait_assoc_ty.associated_item(ty::AssocItem {
|
|
|
|
name: kw::Empty,
|
|
|
|
kind: ty::AssocKind::Type,
|
|
|
|
def_id,
|
|
|
|
trait_item_def_id: None,
|
|
|
|
container: ty::TraitContainer,
|
|
|
|
fn_has_self_parameter: false,
|
2023-03-12 20:32:50 +00:00
|
|
|
opt_rpitit_info: Some(ImplTraitInTraitData::Trait {
|
2023-03-20 17:05:46 +00:00
|
|
|
fn_def_id: fn_def_id.to_def_id(),
|
2023-03-12 20:32:50 +00:00
|
|
|
opaque_def_id: opaque_ty_def_id.to_def_id(),
|
|
|
|
}),
|
2024-06-14 12:16:15 +00:00
|
|
|
is_effects_desugaring: false,
|
2023-02-28 16:05:37 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
// Copy visility of the containing function.
|
|
|
|
trait_assoc_ty.visibility(tcx.visibility(fn_def_id));
|
|
|
|
|
2023-06-01 06:14:06 +00:00
|
|
|
// Copy defaultness of the containing function.
|
|
|
|
trait_assoc_ty.defaultness(tcx.defaultness(fn_def_id));
|
2023-02-28 16:05:37 +00:00
|
|
|
|
2023-03-13 22:02:28 +00:00
|
|
|
trait_assoc_ty.is_type_alias_impl_trait(false);
|
|
|
|
|
2023-02-28 16:05:37 +00:00
|
|
|
// There are no inferred outlives for the synthesized associated type.
|
|
|
|
trait_assoc_ty.inferred_outlives_of(&[]);
|
|
|
|
|
|
|
|
local_def_id
|
2022-12-16 20:15:34 +00:00
|
|
|
}
|
2023-02-16 21:12:53 +00:00
|
|
|
|
2023-03-17 03:45:14 +00:00
|
|
|
/// 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(
|
2023-02-16 21:12:53 +00:00
|
|
|
tcx: TyCtxt<'_>,
|
2023-03-21 18:06:04 +00:00
|
|
|
trait_assoc_def_id: DefId,
|
2023-02-16 21:12:53 +00:00
|
|
|
impl_fn_def_id: LocalDefId,
|
|
|
|
) -> LocalDefId {
|
2023-03-03 15:40:32 +00:00
|
|
|
let impl_local_def_id = tcx.local_parent(impl_fn_def_id);
|
2023-02-16 21:12:53 +00:00
|
|
|
|
2024-03-14 18:05:06 +00:00
|
|
|
let decl = tcx.hir_node_by_def_id(impl_fn_def_id).fn_decl().expect("expected decl");
|
2023-07-27 22:20:32 +00:00
|
|
|
let span = match decl.output {
|
|
|
|
hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn_def_id),
|
|
|
|
hir::FnRetTy::Return(ty) => ty.span,
|
|
|
|
};
|
2023-12-03 09:29:59 +00:00
|
|
|
let impl_assoc_ty = tcx.at(span).create_def(impl_local_def_id, kw::Empty, DefKind::AssocTy);
|
2023-02-16 21:12:53 +00:00
|
|
|
|
2023-03-02 19:20:48 +00:00
|
|
|
let local_def_id = impl_assoc_ty.def_id();
|
|
|
|
let def_id = local_def_id.to_def_id();
|
|
|
|
|
2024-03-19 09:00:57 +00:00
|
|
|
impl_assoc_ty.feed_hir();
|
2023-03-02 19:20:48 +00:00
|
|
|
|
2023-03-08 20:59:06 +00:00
|
|
|
// Copy span of the opaque.
|
|
|
|
impl_assoc_ty.def_ident_span(Some(span));
|
|
|
|
|
2023-03-02 19:20:48 +00:00
|
|
|
impl_assoc_ty.associated_item(ty::AssocItem {
|
|
|
|
name: kw::Empty,
|
|
|
|
kind: ty::AssocKind::Type,
|
|
|
|
def_id,
|
2023-03-21 18:06:04 +00:00
|
|
|
trait_item_def_id: Some(trait_assoc_def_id),
|
2023-03-02 19:20:48 +00:00
|
|
|
container: ty::ImplContainer,
|
|
|
|
fn_has_self_parameter: false,
|
2023-03-12 20:32:50 +00:00
|
|
|
opt_rpitit_info: Some(ImplTraitInTraitData::Impl { fn_def_id: impl_fn_def_id.to_def_id() }),
|
2024-06-14 12:16:15 +00:00
|
|
|
is_effects_desugaring: false,
|
2023-03-02 19:20:48 +00:00
|
|
|
});
|
|
|
|
|
2023-03-08 20:59:06 +00:00
|
|
|
// Copy visility of the containing function.
|
|
|
|
impl_assoc_ty.visibility(tcx.visibility(impl_fn_def_id));
|
|
|
|
|
2023-06-01 06:14:06 +00:00
|
|
|
// Copy defaultness of the containing function.
|
|
|
|
impl_assoc_ty.defaultness(tcx.defaultness(impl_fn_def_id));
|
2023-03-02 19:20:48 +00:00
|
|
|
|
2023-03-03 15:40:32 +00:00
|
|
|
// Copy generics_of the trait's associated item but the impl as the parent.
|
2024-03-05 15:55:04 +00:00
|
|
|
// FIXME: This may be detrimental to diagnostics, as we resolve the early-bound vars
|
|
|
|
// here to paramswhose parent are items in the trait. We could synthesize new params
|
|
|
|
// here, but it seems overkill.
|
2023-03-03 15:40:32 +00:00
|
|
|
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;
|
2024-05-10 00:56:44 +00:00
|
|
|
let mut own_params = trait_assoc_generics.own_params.clone();
|
2023-03-03 15:40:32 +00:00
|
|
|
|
2023-03-20 17:05:46 +00:00
|
|
|
let parent_generics = tcx.generics_of(impl_local_def_id.to_def_id());
|
2024-05-10 00:56:44 +00:00
|
|
|
let parent_count = parent_generics.parent_count + parent_generics.own_params.len();
|
2023-03-03 15:40:32 +00:00
|
|
|
|
2024-05-10 00:56:44 +00:00
|
|
|
for param in &mut own_params {
|
2023-03-17 17:05:26 +00:00
|
|
|
param.index = param.index + parent_count as u32 - trait_assoc_parent_count as u32;
|
2023-03-03 15:40:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
let param_def_id_to_index =
|
2024-05-10 00:56:44 +00:00
|
|
|
own_params.iter().map(|param| (param.def_id, param.index)).collect();
|
2023-03-03 15:40:32 +00:00
|
|
|
|
|
|
|
ty::Generics {
|
2023-03-20 17:05:46 +00:00
|
|
|
parent: Some(impl_local_def_id.to_def_id()),
|
2023-03-03 15:40:32 +00:00
|
|
|
parent_count,
|
2024-05-10 00:56:44 +00:00
|
|
|
own_params,
|
2023-03-03 15:40:32 +00:00
|
|
|
param_def_id_to_index,
|
|
|
|
has_self: false,
|
|
|
|
has_late_bound_regions: trait_assoc_generics.has_late_bound_regions,
|
2023-07-04 13:49:08 +00:00
|
|
|
host_effect_index: parent_generics.host_effect_index,
|
2023-03-03 15:40:32 +00:00
|
|
|
}
|
|
|
|
});
|
2023-03-02 19:20:48 +00:00
|
|
|
|
2023-03-03 15:41:22 +00:00
|
|
|
// There are no inferred outlives for the synthesized associated type.
|
|
|
|
impl_assoc_ty.inferred_outlives_of(&[]);
|
2023-03-02 19:20:48 +00:00
|
|
|
|
|
|
|
local_def_id
|
2023-02-16 21:12:53 +00:00
|
|
|
}
|