1use rustc_hir::def::DefKind;
2use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId};
3use rustc_hir::definitions::{DefPathData, PerParentDisambiguatorState};
4use rustc_hir::intravisit::{self, Visitor};
5use rustc_hir::{self as hir, ImplItemImplKind, ItemKind};
6use rustc_middle::query::Providers;
7use rustc_middle::ty::{self, ImplTraitInTraitData, TyCtxt};
8use rustc_span::symbol::kw;
9use rustc_span::{Ident, bug, span_bug};
10
11pub(crate) fn provide(providers: &mut Providers) {
12 *providers = Providers {
13 associated_item,
14 associated_item_def_ids,
15 associated_items,
16 associated_types_for_impl_traits_in_trait_or_impl,
17 impl_item_implementor_ids,
18 ..*providers
19 };
20}
21
22fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] {
23 let item = tcx.hir_expect_item(def_id);
24 match item.kind {
25 hir::ItemKind::Trait { items: trait_item_refs, .. } => {
26 let rpitit_items = tcx.associated_types_for_impl_traits_in_trait_or_impl(def_id);
30 tcx.arena.alloc_from_iter(trait_item_refs.iter().flat_map(|trait_item_ref| {
31 let item_def_id = trait_item_ref.owner_id.to_def_id();
32 [item_def_id]
33 .into_iter()
34 .chain(rpitit_items.get(&item_def_id).into_flat_iter().copied())
35 }))
36 }
37 hir::ItemKind::Impl(impl_) => {
38 let rpitit_items = tcx.associated_types_for_impl_traits_in_trait_or_impl(def_id);
42 tcx.arena.alloc_from_iter(impl_.items.iter().flat_map(|impl_item_ref| {
43 let item_def_id = impl_item_ref.owner_id.to_def_id();
44 [item_def_id]
45 .into_iter()
46 .chain(rpitit_items.get(&item_def_id).into_flat_iter().copied())
47 }))
48 }
49 _ => bug_impl(Some(item.span),
format_args!("associated_item_def_ids: not impl or trait"),
Location::caller())span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
50 }
51}
52
53fn associated_items(tcx: TyCtxt<'_>, def_id: DefId) -> ty::AssocItems {
54 if tcx.is_trait_alias(def_id) {
55 ty::AssocItems::new(Vec::new())
56 } else {
57 let items = tcx.associated_item_def_ids(def_id).iter().map(|did| tcx.associated_item(*did));
58 ty::AssocItems::new(items)
59 }
60}
61
62fn impl_item_implementor_ids(tcx: TyCtxt<'_>, impl_id: DefId) -> DefIdMap<DefId> {
63 tcx.associated_items(impl_id)
64 .in_definition_order()
65 .filter_map(|item| item.trait_item_def_id().map(|trait_item| (trait_item, item.def_id)))
66 .collect()
67}
68
69fn associated_item(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::AssocItem {
70 let assoc_item = match tcx.hir_node_by_def_id(def_id) {
71 hir::Node::TraitItem(ti) => associated_item_from_trait_item(tcx, ti),
72 hir::Node::ImplItem(ii) => associated_item_from_impl_item(tcx, ii),
73 node => bug_impl(Some(tcx.def_span(def_id)),
format_args!("impl item or item not found: {0:?}", node),
Location::caller())span_bug!(tcx.def_span(def_id), "impl item or item not found: {:?}", node,),
74 };
75 if true {
{
match (&assoc_item.def_id.expect_local(), &def_id) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};debug_assert_eq!(assoc_item.def_id.expect_local(), def_id);
76 assoc_item
77}
78
79fn fn_has_self_parameter(tcx: TyCtxt<'_>, owner_id: hir::OwnerId) -> bool {
80 #[allow(non_exhaustive_omitted_patterns)] match tcx.fn_arg_idents(owner_id.def_id)
{
[Some(Ident { name: kw::SelfLower, .. }), ..] => true,
_ => false,
}matches!(tcx.fn_arg_idents(owner_id.def_id), [Some(Ident { name: kw::SelfLower, .. }), ..])
81}
82
83fn associated_item_from_trait_item(
84 tcx: TyCtxt<'_>,
85 trait_item: &hir::TraitItem<'_>,
86) -> ty::AssocItem {
87 let owner_id = trait_item.owner_id;
88 let name = trait_item.ident.name;
89 let kind = match trait_item.kind {
90 hir::TraitItemKind::Const(_, _) => ty::AssocKind::Const { name },
91 hir::TraitItemKind::Fn { .. } => {
92 ty::AssocKind::Fn { name, has_self: fn_has_self_parameter(tcx, owner_id) }
93 }
94 hir::TraitItemKind::Type { .. } => {
95 ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) }
96 }
97 };
98
99 ty::AssocItem { kind, def_id: owner_id.to_def_id(), container: ty::AssocContainer::Trait }
100}
101
102fn associated_item_from_impl_item(tcx: TyCtxt<'_>, impl_item: &hir::ImplItem<'_>) -> ty::AssocItem {
103 let owner_id = impl_item.owner_id;
104 let name = impl_item.ident.name;
105 let kind = match impl_item.kind {
106 hir::ImplItemKind::Const(..) => ty::AssocKind::Const { name },
107 hir::ImplItemKind::Fn(..) => {
108 ty::AssocKind::Fn { name, has_self: fn_has_self_parameter(tcx, owner_id) }
109 }
110 hir::ImplItemKind::Type(..) => {
111 ty::AssocKind::Type { data: ty::AssocTypeData::Normal(name) }
112 }
113 };
114
115 let container = match impl_item.impl_kind {
116 ImplItemImplKind::Inherent { .. } => ty::AssocContainer::InherentImpl,
117 ImplItemImplKind::Trait { trait_item_def_id, .. } => {
118 ty::AssocContainer::TraitImpl(trait_item_def_id)
119 }
120 };
121 ty::AssocItem { kind, def_id: owner_id.to_def_id(), container }
122}
123struct RPITVisitor<'a, 'tcx> {
124 tcx: TyCtxt<'tcx>,
125 synthetics: Vec<LocalDefId>,
126 data: DefPathData,
127 disambiguator: &'a mut PerParentDisambiguatorState,
128}
129
130impl<'tcx> Visitor<'tcx> for RPITVisitor<'_, 'tcx> {
131 fn visit_opaque_ty(&mut self, opaque: &'tcx hir::OpaqueTy<'tcx>) -> Self::Result {
132 self.synthetics.push(associated_type_for_impl_trait_in_trait(
133 self.tcx,
134 opaque.def_id,
135 self.data,
136 &mut self.disambiguator,
137 ));
138 intravisit::walk_opaque_ty(self, opaque)
139 }
140}
141
142fn associated_types_for_impl_traits_in_trait_or_impl<'tcx>(
143 tcx: TyCtxt<'tcx>,
144 def_id: LocalDefId,
145) -> DefIdMap<Vec<DefId>> {
146 let item = tcx.hir_expect_item(def_id);
147 let disambiguator = &mut PerParentDisambiguatorState::new(def_id);
148 match item.kind {
149 ItemKind::Trait { items: trait_item_refs, .. } => trait_item_refs
150 .iter()
151 .filter_map(move |item| {
152 if !#[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(item.owner_id) {
DefKind::AssocFn => true,
_ => false,
}matches!(tcx.def_kind(item.owner_id), DefKind::AssocFn) {
153 return None;
154 }
155 let fn_def_id = item.owner_id.def_id;
156 let Some(output) = tcx.hir_get_fn_output(fn_def_id) else {
157 return Some((fn_def_id.to_def_id(), ::alloc::vec::Vec::new()vec![]));
158 };
159 let def_name = tcx.item_name(fn_def_id.to_def_id());
160 let data = DefPathData::AnonAssocTy(def_name);
161 let mut visitor = RPITVisitor { tcx, synthetics: ::alloc::vec::Vec::new()vec![], data, disambiguator };
162 visitor.visit_fn_ret_ty(output);
163 let defs = visitor
164 .synthetics
165 .into_iter()
166 .map(|def_id| def_id.to_def_id())
167 .collect::<Vec<_>>();
168 Some((fn_def_id.to_def_id(), defs))
169 })
170 .collect(),
171 ItemKind::Impl(impl_) => {
172 let Some(of_trait) = impl_.of_trait else {
173 return Default::default();
174 };
175 let Some(trait_def_id) = of_trait.trait_ref.trait_def_id() else {
176 return Default::default();
177 };
178 let in_trait_def = tcx.associated_types_for_impl_traits_in_trait_or_impl(trait_def_id);
179 impl_
180 .items
181 .iter()
182 .filter_map(|item| {
183 if !#[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(item.owner_id) {
DefKind::AssocFn => true,
_ => false,
}matches!(tcx.def_kind(item.owner_id), DefKind::AssocFn) {
184 return None;
185 }
186 let did = item.owner_id.def_id.to_def_id();
187 let item = tcx.hir_impl_item(*item);
188 let ImplItemImplKind::Trait {
189 trait_item_def_id: Ok(trait_item_def_id), ..
190 } = item.impl_kind
191 else {
192 return Some((did, ::alloc::vec::Vec::new()vec![]));
193 };
194 let iter = in_trait_def[&trait_item_def_id].iter().map(|&id| {
195 associated_type_for_impl_trait_in_impl(tcx, id, item, disambiguator)
196 .to_def_id()
197 });
198 Some((did, iter.collect()))
199 })
200 .collect()
201 }
202 _ => {
203 bug_impl(None,
format_args!("associated_types_for_impl_traits_in_trait_or_impl: {0:?} should be Trait or Impl but is {1:?}",
def_id, tcx.def_kind(def_id)), Location::caller())bug!(
204 "associated_types_for_impl_traits_in_trait_or_impl: {:?} should be Trait or Impl but is {:?}",
205 def_id,
206 tcx.def_kind(def_id)
207 )
208 }
209 }
210}
211
212fn associated_type_for_impl_trait_in_trait(
216 tcx: TyCtxt<'_>,
217 opaque_ty_def_id: LocalDefId,
218 data: DefPathData,
219 disambiguator: &mut PerParentDisambiguatorState,
220) -> LocalDefId {
221 let (hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
222 | hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. }) =
223 tcx.local_opaque_ty_origin(opaque_ty_def_id)
224 else {
225 bug_impl(None, format_args!("expected opaque for {0:?}", opaque_ty_def_id),
Location::caller());bug!("expected opaque for {opaque_ty_def_id:?}");
226 };
227 let trait_def_id = tcx.local_parent(fn_def_id);
228 {
match (&tcx.def_kind(trait_def_id), &DefKind::Trait) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};assert_eq!(tcx.def_kind(trait_def_id), DefKind::Trait);
229
230 let span = tcx.def_span(opaque_ty_def_id);
231 let trait_assoc_ty = tcx.at(span).create_def(
233 trait_def_id,
234 None,
236 DefKind::AssocTy,
237 Some(data),
238 disambiguator,
239 );
240
241 let local_def_id = trait_assoc_ty.def_id();
242 let def_id = local_def_id.to_def_id();
243
244 trait_assoc_ty.feed_hir();
245
246 trait_assoc_ty.def_ident_span(Some(span));
248
249 trait_assoc_ty.associated_item(ty::AssocItem {
250 kind: ty::AssocKind::Type {
251 data: ty::AssocTypeData::Rpitit(ImplTraitInTraitData::Trait {
252 fn_def_id: fn_def_id.to_def_id(),
253 opaque_def_id: opaque_ty_def_id.to_def_id(),
254 }),
255 },
256 def_id,
257 container: ty::AssocContainer::Trait,
258 });
259
260 trait_assoc_ty.visibility(tcx.visibility(fn_def_id));
262
263 trait_assoc_ty.defaultness(tcx.defaultness(fn_def_id));
265
266 trait_assoc_ty.inferred_outlives_of(&[]);
268
269 local_def_id
270}
271
272fn associated_type_for_impl_trait_in_impl(
278 tcx: TyCtxt<'_>,
279 trait_assoc_def_id: DefId,
280 impl_fn: &hir::ImplItem<'_>,
281 disambiguator: &mut PerParentDisambiguatorState,
282) -> LocalDefId {
283 let impl_local_def_id = tcx.local_parent(impl_fn.owner_id.def_id);
284
285 let hir::ImplItemKind::Fn(fn_sig, _) = impl_fn.kind else { bug_impl(None, format_args!("expected decl"), Location::caller())bug!("expected decl") };
286 let span = match fn_sig.decl.output {
287 hir::FnRetTy::DefaultReturn(_) => tcx.def_span(impl_fn.owner_id),
288 hir::FnRetTy::Return(ty) => ty.span,
289 };
290
291 let disambiguated_data = tcx.def_key(trait_assoc_def_id).disambiguated_data;
293 let DefPathData::AnonAssocTy(name) = disambiguated_data.data else {
294 bug_impl(None, format_args!("expected anon associated type"),
Location::caller())bug!("expected anon associated type")
295 };
296 let data = DefPathData::AnonAssocTy(name);
297
298 let impl_assoc_ty = tcx.at(span).create_def(
299 impl_local_def_id,
300 None,
302 DefKind::AssocTy,
303 Some(data),
304 disambiguator,
305 );
306
307 let local_def_id = impl_assoc_ty.def_id();
308 let def_id = local_def_id.to_def_id();
309
310 impl_assoc_ty.feed_hir();
311
312 impl_assoc_ty.def_ident_span(Some(span));
314
315 impl_assoc_ty.associated_item(ty::AssocItem {
316 kind: ty::AssocKind::Type {
317 data: ty::AssocTypeData::Rpitit(ImplTraitInTraitData::Impl {
318 fn_def_id: impl_fn.owner_id.to_def_id(),
319 }),
320 },
321 def_id,
322 container: ty::AssocContainer::TraitImpl(Ok(trait_assoc_def_id)),
323 });
324
325 impl_assoc_ty.visibility(tcx.visibility(impl_fn.owner_id));
327
328 impl_assoc_ty.defaultness(tcx.defaultness(impl_fn.owner_id));
330
331 impl_assoc_ty.generics_of({
336 let trait_assoc_generics = tcx.generics_of(trait_assoc_def_id);
337 let trait_assoc_parent_count = trait_assoc_generics.parent_count;
338 let mut own_params = trait_assoc_generics.own_params.clone();
339
340 let parent_generics = tcx.generics_of(impl_local_def_id.to_def_id());
341 let parent_count = parent_generics.count();
342
343 for param in &mut own_params {
344 param.index = param.index + parent_count as u32 - trait_assoc_parent_count as u32;
345 }
346
347 let param_def_id_to_index =
348 own_params.iter().map(|param| (param.def_id, param.index)).collect();
349
350 ty::Generics {
351 parent: Some(impl_local_def_id.to_def_id()),
352 parent_count,
353 own_params,
354 param_def_id_to_index,
355 has_self: false,
356 has_late_bound_regions: trait_assoc_generics.has_late_bound_regions,
357 }
358 });
359
360 impl_assoc_ty.inferred_outlives_of(&[]);
362
363 local_def_id
364}