1use std::iter::once;
4use std::sync::Arc;
5
6use rustc_attr_ir::{AttributeKind, DocInline, find_attr};
7use rustc_data_structures::fx::FxHashSet;
8use rustc_data_structures::thin_vec::{ThinVec, thin_vec};
9use rustc_hir::def::{DefKind, MacroKinds, Res};
10use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LocalModId};
11use rustc_hir::{self as hir, HirId, Mutability};
12use rustc_metadata::creader::{CStore, LoadedMacro};
13use rustc_middle::ty::fast_reject::SimplifiedType;
14use rustc_middle::ty::{self, TyCtxt};
15use rustc_span::def_id::LOCAL_CRATE;
16use rustc_span::hygiene::MacroKind;
17use rustc_span::symbol::{Symbol, sym};
18use tracing::{debug, instrument, trace};
19
20use super::{Item, extract_cfg_from_attrs};
21use crate::clean::{
22 self, Attributes, CfgInfo, ImplKind, ItemId, ItemKind, Type, clean_bound_vars, clean_generics,
23 clean_impl_item, clean_middle_assoc_item, clean_middle_field, clean_middle_ty,
24 clean_poly_fn_sig, clean_trait_ref_with_constraints, clean_ty, clean_ty_alias_inner_type,
25 clean_ty_generics, clean_variant_def, utils,
26};
27use crate::core::DocContext;
28use crate::formats::item_type::ItemType;
29
30pub(crate) fn try_inline(
43 cx: &mut DocContext<'_>,
44 res: Res,
45 name: Symbol,
46 attrs: Option<(&[rustc_attr_ir::Attribute], Option<LocalDefId>)>,
47 visited: &mut DefIdSet,
48) -> Option<Vec<clean::Item>> {
49 fn try_inline_inner(
50 cx: &mut DocContext<'_>,
51 kind: ItemKind,
52 did: DefId,
53 name: Symbol,
54 import_def_id: Option<LocalDefId>,
55 ) -> clean::Item {
56 cx.inlined.insert(did.into());
57 let mut item = crate::clean::generate_item_with_correct_attrs(
58 cx,
59 kind,
60 did,
61 name,
62 import_def_id.as_slice(),
63 None,
64 );
65 item.inner.inline_stmt_id = import_def_id;
67 item
68 }
69
70 let did = res.opt_def_id()?;
71 if did.is_local() {
72 return None;
73 }
74 let mut ret = Vec::new();
75
76 debug!("attrs={attrs:?}");
77
78 let attrs_without_docs = attrs.map(|(attrs, def_id)| {
79 (
80 attrs
81 .iter()
82 .filter(|a| {
83 !matches!(a, rustc_attr_ir::Attribute::Parsed(AttributeKind::DocComment { .. }))
84 })
85 .cloned()
86 .collect::<Vec<_>>(),
87 def_id,
88 )
89 });
90 let attrs_without_docs =
91 attrs_without_docs.as_ref().map(|(attrs, def_id)| (&attrs[..], *def_id));
92
93 let import_def_id = attrs.and_then(|(_, def_id)| def_id);
94
95 let kind = match res {
96 Res::Def(DefKind::Trait, did) => {
97 record_extern_fqn(cx, did, ItemType::Trait);
98 cx.with_param_env(did, |cx| {
99 build_impls(cx, did, attrs_without_docs, &mut ret);
100 ItemKind::Trait(Box::new(build_trait(cx, did)))
101 })
102 }
103 Res::Def(DefKind::TraitAlias, did) => {
104 record_extern_fqn(cx, did, ItemType::TraitAlias);
105 cx.with_param_env(did, |cx| ItemKind::TraitAlias(build_trait_alias(cx, did)))
106 }
107 Res::Def(DefKind::Fn, did) => {
108 record_extern_fqn(cx, did, ItemType::Function);
109 cx.with_param_env(did, |cx| {
110 clean::enter_impl_trait(cx, |cx| {
111 let (generics, decl) = build_function(cx, did);
112 ItemKind::Function(Box::new(clean::Function { generics, decl }))
113 })
114 })
115 }
116 Res::Def(DefKind::Struct, did) => {
117 record_extern_fqn(cx, did, ItemType::Struct);
118 cx.with_param_env(did, |cx| {
119 build_impls(cx, did, attrs_without_docs, &mut ret);
120 ItemKind::Struct(build_struct(cx, did))
121 })
122 }
123 Res::Def(DefKind::Union, did) => {
124 record_extern_fqn(cx, did, ItemType::Union);
125 cx.with_param_env(did, |cx| {
126 build_impls(cx, did, attrs_without_docs, &mut ret);
127 ItemKind::Union(build_union(cx, did))
128 })
129 }
130 Res::Def(DefKind::TyAlias, did) => {
131 record_extern_fqn(cx, did, ItemType::TypeAlias);
132 cx.with_param_env(did, |cx| {
133 build_impls(cx, did, attrs_without_docs, &mut ret);
134 ItemKind::TypeAlias(build_type_alias(cx, did, &mut ret))
135 })
136 }
137 Res::Def(DefKind::Enum, did) => {
138 record_extern_fqn(cx, did, ItemType::Enum);
139 cx.with_param_env(did, |cx| {
140 build_impls(cx, did, attrs_without_docs, &mut ret);
141 ItemKind::Enum(build_enum(cx, did))
142 })
143 }
144 Res::Def(DefKind::ForeignTy, did) => {
145 record_extern_fqn(cx, did, ItemType::ForeignType);
146 cx.with_param_env(did, |cx| {
147 build_impls(cx, did, attrs_without_docs, &mut ret);
148 ItemKind::ForeignType
149 })
150 }
151 Res::Def(DefKind::Variant, _) => return None,
153 Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) => return Some(Vec::new()),
156 Res::Def(DefKind::Mod, did) => {
157 record_extern_fqn(cx, did, ItemType::Module);
158 ItemKind::Module(build_module(cx, did, name, visited))
159 }
160 Res::Def(DefKind::Static { .. }, did) => {
161 record_extern_fqn(cx, did, ItemType::Static);
162 cx.with_param_env(did, |cx| {
163 ItemKind::Static(build_static(cx, did, cx.tcx.is_mutable_static(did)))
164 })
165 }
166 Res::Def(DefKind::Const, did) => {
167 record_extern_fqn(cx, did, ItemType::Constant);
168 cx.with_param_env(did, |cx| {
169 let ct = build_const_item(cx, did);
170 ItemKind::Constant(Box::new(ct))
171 })
172 }
173 Res::Def(DefKind::Macro(kinds), did) => {
174 let mac = build_macro(cx.tcx, did, name, kinds);
175
176 let type_kind = match kinds {
177 MacroKinds::BANG => ItemType::Macro,
178 MacroKinds::ATTR => ItemType::ProcAttribute,
179 MacroKinds::DERIVE => ItemType::ProcDerive,
180 _ => ItemType::Macro,
182 };
183 record_extern_fqn(cx, did, type_kind);
184 ret.push(try_inline_inner(cx, mac, did, name, import_def_id));
185 return Some(ret);
186 }
187 _ => return None,
188 };
189
190 ret.push(try_inline_inner(cx, kind, did, name, import_def_id));
191 Some(ret)
192}
193
194pub(crate) fn try_inline_glob(
195 cx: &mut DocContext<'_>,
196 res: Res,
197 current_mod: LocalModId,
198 visited: &mut DefIdSet,
199 inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
200 import_id: LocalDefId,
201 import_hir_id: HirId,
202) -> Option<Vec<clean::Item>> {
203 let did = res.opt_def_id()?;
204 if did.is_local() {
205 return None;
206 }
207
208 match res {
209 Res::Def(DefKind::Mod, did) => {
210 let reexports = cx
213 .tcx
214 .module_children_local(current_mod.to_local_def_id())
215 .iter()
216 .filter(|child| !child.reexport_chain.is_empty())
217 .filter_map(|child| child.res.opt_def_id())
218 .filter(|&def_id| !cx.tcx.is_doc_hidden(def_id))
219 .collect();
220 let attrs = cx.tcx.hir_attrs(import_hir_id);
221 let mut items = build_module_items(
222 cx,
223 did,
224 cx.tcx.item_name(did),
225 visited,
226 inlined_names,
227 Some(&reexports),
228 Some((attrs, Some(import_id))),
229 );
230 items.retain(|item| {
231 if let Some(name) = item.name {
232 inlined_names.insert((item.type_(), name))
235 } else {
236 true
237 }
238 });
239 Some(items)
240 }
241 _ => None,
243 }
244}
245
246pub(crate) fn load_attrs<'hir>(tcx: TyCtxt<'hir>, did: DefId) -> &'hir [rustc_attr_ir::Attribute] {
247 #[allow(deprecated)]
249 tcx.get_all_attrs(did)
250}
251
252pub(crate) fn item_relative_path(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<Symbol> {
253 tcx.def_path(def_id).data.into_iter().filter_map(|elem| elem.data.get_opt_name()).collect()
254}
255
256pub(crate) fn get_item_path(tcx: TyCtxt<'_>, def_id: DefId, kind: ItemType) -> Vec<Symbol> {
261 let crate_name = tcx.crate_name(def_id.krate);
262 let relative = item_relative_path(tcx, def_id);
263
264 if let ItemType::Macro = kind {
265 let is_macro_2_0_or_builtin = if let Some(local_def_id) = def_id.as_local() {
268 let (_, macro_def, _) = tcx.hir_expect_item(local_def_id).expect_macro();
269 !macro_def.macro_rules
270 } else {
271 matches!(
272 CStore::from_tcx(tcx).load_macro_untracked(tcx, def_id),
273 LoadedMacro::MacroDef { def, .. } if !def.macro_rules
274 )
275 };
276 if !is_macro_2_0_or_builtin {
277 return vec![crate_name, *relative.last().expect("relative was empty")];
278 }
279 }
280
281 once(crate_name).chain(relative).collect()
282}
283
284pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemType) {
289 if did.is_local() {
290 if cx.cache.exact_paths.contains_key(&did) {
291 return;
292 }
293 } else if cx.cache.external_paths.contains_key(&did) {
294 return;
295 }
296
297 let item_path = get_item_path(cx.tcx, did, kind);
298
299 if did.is_local() {
300 cx.cache.exact_paths.insert(did, item_path);
301 } else {
302 cx.cache.external_paths.insert(did, (item_path, kind));
303 }
304}
305
306pub(crate) fn build_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait {
307 let trait_items = cx
308 .tcx
309 .associated_items(did)
310 .in_definition_order()
311 .filter(|item| !item.is_impl_trait_in_trait())
312 .map(|item| clean_middle_assoc_item(item, cx))
313 .collect();
314
315 let generics = clean_ty_generics(cx, did);
316 let (generics, mut supertrait_bounds) = separate_self_bounds(generics);
317
318 supertrait_bounds.retain(|b| {
319 !b.is_meta_sized_bound(cx.tcx)
322 });
323
324 clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds }
325}
326
327fn build_trait_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::TraitAlias {
328 let generics = clean_ty_generics(cx, did);
329 let (generics, mut bounds) = separate_self_bounds(generics);
330
331 bounds.retain(|b| {
332 !b.is_meta_sized_bound(cx.tcx)
335 });
336
337 clean::TraitAlias { generics, bounds }
338}
339
340pub(super) fn build_function(
341 cx: &mut DocContext<'_>,
342 def_id: DefId,
343) -> (clean::Generics, clean::FnDecl) {
344 let sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip();
345 let mut generics = clean_ty_generics(cx, def_id);
347 let bound_vars = clean_bound_vars(sig.bound_vars(), cx.tcx);
348
349 let has_early_bound_params = !generics.params.is_empty();
359 let has_late_bound_params = !bound_vars.is_empty();
360 generics.params.extend(bound_vars);
361 if has_early_bound_params && has_late_bound_params {
362 generics.params.sort_by_key(|param| cx.tcx.def_ident_span(param.def_id).unwrap().lo_hi());
367 }
368
369 let decl = clean_poly_fn_sig(cx, Some(def_id), sig);
370
371 (generics, decl)
372}
373
374fn build_enum(cx: &mut DocContext<'_>, did: DefId) -> clean::Enum {
375 clean::Enum {
376 generics: clean_ty_generics(cx, did),
377 variants: cx.tcx.adt_def(did).variants().iter().map(|v| clean_variant_def(v, cx)).collect(),
378 }
379}
380
381fn build_struct(cx: &mut DocContext<'_>, did: DefId) -> clean::Struct {
382 let variant = cx.tcx.adt_def(did).non_enum_variant();
383
384 clean::Struct {
385 ctor_kind: variant.ctor_kind(),
386 generics: clean_ty_generics(cx, did),
387 fields: variant.fields.iter().map(|x| clean_middle_field(x, cx)).collect(),
388 }
389}
390
391fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
392 let variant = cx.tcx.adt_def(did).non_enum_variant();
393
394 let generics = clean_ty_generics(cx, did);
395 let fields = variant.fields.iter().map(|x| clean_middle_field(x, cx)).collect();
396 clean::Union { generics, fields }
397}
398
399fn build_type_alias(
400 cx: &mut DocContext<'_>,
401 did: DefId,
402 ret: &mut Vec<Item>,
403) -> Box<clean::TypeAlias> {
404 let ty = cx.tcx.type_of(did).instantiate_identity().skip_norm_wip();
405 let type_ = clean_middle_ty(ty::Binder::dummy(ty), cx, Some(did), None);
406 let inner_type = clean_ty_alias_inner_type(ty, cx, ret);
407
408 Box::new(clean::TypeAlias { type_, generics: clean_ty_generics(cx, did), inner_type })
409}
410
411pub(crate) fn build_impls(
413 cx: &mut DocContext<'_>,
414 did: DefId,
415 attrs: Option<(&[rustc_attr_ir::Attribute], Option<LocalDefId>)>,
416 ret: &mut Vec<clean::Item>,
417) {
418 let tcx = cx.tcx;
419 let _prof_timer = tcx.sess.prof.generic_activity("build_inherent_impls");
420
421 for &did in tcx.inherent_impls(did).iter() {
423 cx.with_param_env(did, |cx| {
424 build_impl(cx, did, attrs, ret);
425 });
426 }
427
428 if find_attr!(tcx, did, RustcHasIncoherentInherentImpls) {
435 let type_ =
436 if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) };
437 for &did in tcx.incoherent_impls(type_).iter() {
438 cx.with_param_env(did, |cx| {
439 build_impl(cx, did, attrs, ret);
440 });
441 }
442 }
443}
444
445pub(crate) fn merge_attrs(
446 tcx: TyCtxt<'_>,
447 old_attrs: &[rustc_attr_ir::Attribute],
448 new_attrs: Option<(&[rustc_attr_ir::Attribute], Option<LocalDefId>)>,
449 cfg_info: &mut CfgInfo,
450) -> (clean::Attributes, Option<Arc<clean::cfg::Cfg>>) {
451 if let Some((inner, item_id)) = new_attrs {
456 let mut both = inner.to_vec();
457 both.extend_from_slice(old_attrs);
458 (
459 if let Some(item_id) = item_id {
460 Attributes::from_hir_with_additional(old_attrs, (inner, item_id.to_def_id()))
461 } else {
462 Attributes::from_hir(&both)
463 },
464 extract_cfg_from_attrs(both.iter(), tcx, cfg_info),
465 )
466 } else {
467 (Attributes::from_hir(old_attrs), extract_cfg_from_attrs(old_attrs.iter(), tcx, cfg_info))
468 }
469}
470
471#[instrument(level = "debug", skip(cx, ret))]
473pub(crate) fn build_impl(
474 cx: &mut DocContext<'_>,
475 did: DefId,
476 attrs: Option<(&[rustc_attr_ir::Attribute], Option<LocalDefId>)>,
477 ret: &mut Vec<clean::Item>,
478) {
479 if !cx.inlined.insert(did.into()) {
480 return;
481 }
482
483 let tcx = cx.tcx;
484 let _prof_timer = tcx.sess.prof.generic_activity("build_impl");
485
486 let associated_trait = tcx.impl_opt_trait_ref(did).map(ty::EarlyBinder::skip_binder);
487
488 let is_compiler_internal = |did| {
490 tcx.lookup_stability(did)
491 .is_some_and(|stab| stab.is_unstable() && stab.feature == sym::rustc_private)
492 };
493 let document_compiler_internal = is_compiler_internal(LOCAL_CRATE.as_def_id());
494 let is_directly_public = |cx: &mut DocContext<'_>, did| {
495 cx.cache.effective_visibilities.is_directly_public(tcx, did)
496 && (document_compiler_internal || !is_compiler_internal(did))
497 };
498
499 if !did.is_local()
502 && let Some(traitref) = associated_trait
503 && !is_directly_public(cx, traitref.def_id)
504 {
505 return;
506 }
507
508 let impl_item = match did.as_local() {
509 Some(did) => match &tcx.hir_expect_item(did).kind {
510 hir::ItemKind::Impl(impl_) => Some(impl_),
511 _ => panic!("`DefID` passed to `build_impl` is not an `impl"),
512 },
513 None => None,
514 };
515
516 let for_ = match &impl_item {
517 Some(impl_) => clean_ty(impl_.self_ty, cx),
518 None => clean_middle_ty(
519 ty::Binder::dummy(tcx.type_of(did).instantiate_identity().skip_norm_wip()),
520 cx,
521 Some(did),
522 None,
523 ),
524 };
525
526 if !did.is_local()
529 && let Some(did) = for_.def_id(&cx.cache)
530 && !is_directly_public(cx, did)
531 {
532 return;
533 }
534
535 let document_hidden = cx.document_hidden();
536 let (trait_items, generics) = match impl_item {
537 Some(impl_) => (
538 impl_
539 .items
540 .iter()
541 .map(|&item| tcx.hir_impl_item(item))
542 .filter(|item| {
543 if document_hidden {
550 return true;
551 }
552 if let Some(associated_trait) = associated_trait {
553 let assoc_tag = match item.kind {
554 hir::ImplItemKind::Const(..) => ty::AssocTag::Const,
555 hir::ImplItemKind::Fn(..) => ty::AssocTag::Fn,
556 hir::ImplItemKind::Type(..) => ty::AssocTag::Type,
557 };
558 let trait_item = tcx
559 .associated_items(associated_trait.def_id)
560 .find_by_ident_and_kind(
561 tcx,
562 item.ident,
563 assoc_tag,
564 associated_trait.def_id,
565 )
566 .unwrap(); !tcx.is_doc_hidden(trait_item.def_id)
568 } else {
569 true
570 }
571 })
572 .map(|item| clean_impl_item(item, cx))
573 .collect::<Vec<_>>(),
574 clean_generics(impl_.generics, cx),
575 ),
576 None => (
577 tcx.associated_items(did)
578 .in_definition_order()
579 .filter(|item| !item.is_impl_trait_in_trait())
580 .filter(|item| {
581 if let Some(associated_trait) = associated_trait {
585 let trait_item = tcx
586 .associated_items(associated_trait.def_id)
587 .find_by_ident_and_kind(
588 tcx,
589 item.ident(tcx),
590 item.tag(),
591 associated_trait.def_id,
592 )
593 .unwrap(); document_hidden || !tcx.is_doc_hidden(trait_item.def_id)
595 } else {
596 item.visibility(tcx).is_public()
597 }
598 })
599 .map(|item| clean_middle_assoc_item(item, cx))
600 .collect::<Vec<_>>(),
601 clean::enter_impl_trait(cx, |cx| clean_ty_generics(cx, did)),
602 ),
603 };
604 let polarity = if associated_trait.is_some() {
605 tcx.impl_polarity(did)
606 } else {
607 ty::ImplPolarity::Positive
608 };
609 let trait_ = associated_trait
610 .map(|t| clean_trait_ref_with_constraints(cx, ty::Binder::dummy(t), ThinVec::new()));
611 if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait()
612 && polarity != ty::ImplPolarity::Negative
613 {
614 super::build_deref_target_impls(cx, &trait_items, ret);
615 }
616
617 if !document_hidden {
618 let mut stack: Vec<&Type> = vec![&for_];
620
621 if let Some(did) = trait_.as_ref().map(|t| t.def_id())
622 && tcx.is_doc_hidden(did)
623 {
624 return;
625 }
626
627 if let Some(generics) = trait_.as_ref().and_then(|t| t.generics()) {
628 stack.extend(generics);
629 }
630
631 while let Some(ty) = stack.pop() {
632 if let Some(did) = ty.def_id(&cx.cache)
633 && tcx.is_doc_hidden(did)
634 {
635 return;
636 }
637 if let Some(generics) = ty.generics() {
638 stack.extend(generics);
639 }
640 }
641 }
642
643 if let Some(did) = trait_.as_ref().map(|t| t.def_id()) {
644 cx.with_param_env(did, |cx| {
645 record_extern_trait(cx, did);
646 });
647 }
648
649 let (merged_attrs, cfg) =
654 merge_attrs(cx.tcx, load_attrs(cx.tcx, did), attrs, &mut CfgInfo::default());
655 trace!("merged_attrs={merged_attrs:?}");
656
657 trace!(
658 "build_impl: impl {:?} for {:?}",
659 trait_.as_ref().map(|t| t.def_id()),
660 for_.def_id(&cx.cache)
661 );
662 ret.push(clean::Item::from_def_id_and_attrs_and_parts(
663 did,
664 None,
665 ItemKind::Impl(Box::new(clean::Impl {
666 safety: hir::Safety::Safe,
667 generics,
668 trait_,
669 for_,
670 items: trait_items,
671 polarity,
672 kind: if utils::has_doc_flag(tcx, did, |d| d.fake_variadic.is_some()) {
673 ImplKind::FakeVariadic
674 } else {
675 ImplKind::Normal
676 },
677 is_deprecated: tcx
678 .lookup_deprecation(did)
679 .is_some_and(|deprecation| deprecation.is_in_effect()),
680 })),
681 merged_attrs,
682 cfg,
683 ));
684}
685
686fn build_module(
687 cx: &mut DocContext<'_>,
688 did: DefId,
689 name: Symbol,
690 visited: &mut DefIdSet,
691) -> clean::Module {
692 let items = build_module_items(cx, did, name, visited, &mut FxHashSet::default(), None, None);
693
694 let span = clean::Span::new(cx.tcx.def_span(did));
695 clean::Module { items, span }
696}
697
698fn should_ignore_res(res: Res) -> bool {
701 !matches!(res, Res::Def(def_kind, _) if !should_ignore_def_kind(def_kind))
702}
703
704fn should_ignore_def_kind(kind: DefKind) -> bool {
705 !matches!(
706 kind,
707 DefKind::Trait
708 | DefKind::TraitAlias
709 | DefKind::Fn
710 | DefKind::Struct
711 | DefKind::Union
712 | DefKind::TyAlias
713 | DefKind::Enum
714 | DefKind::ForeignTy
715 | DefKind::Variant
716 | DefKind::Mod
717 | DefKind::Static { .. }
718 | DefKind::Const
719 | DefKind::Macro(_)
720 | DefKind::Use
721 )
722}
723
724fn build_module_items(
725 cx: &mut DocContext<'_>,
726 module_def_id: DefId,
727 module_name: Symbol,
728 visited: &mut DefIdSet,
729 inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
730 allowed_def_ids: Option<&DefIdSet>,
731 attrs: Option<(&[rustc_attr_ir::Attribute], Option<LocalDefId>)>,
732) -> Vec<clean::Item> {
733 let mut items = Vec::new();
734
735 for item in cx.tcx.module_children(module_def_id).iter() {
739 if !item.vis.is_public() {
740 continue;
741 }
742 let res = item.res.expect_non_local();
743 if let Some(def_id) = res.opt_def_id()
744 && let Some(allowed_def_ids) = allowed_def_ids
745 && !allowed_def_ids.contains(&def_id)
746 {
747 continue;
748 }
749 if let Some(def_id) = res.mod_def_id() {
750 if module_def_id == def_id
754 || inlined_names.contains(&(ItemType::Module, item.ident.name))
755 || !visited.insert(def_id)
756 {
757 continue;
758 }
759 }
760 if let Res::PrimTy(p) = res {
761 let prim_ty = clean::PrimitiveType::from(p);
763 items.push(clean::Item {
764 inner: Box::new(clean::ItemInner {
765 name: None,
766 item_id: ItemId::DefId(module_def_id),
769 attrs: Default::default(),
770 stability: None,
771 kind: ItemKind::Import(clean::Import::new_simple(
772 item.ident.name,
773 clean::ImportSource {
774 path: clean::Path {
775 res,
776 segments: thin_vec![clean::PathSegment {
777 name: prim_ty.as_sym(),
778 args: clean::GenericArgs::AngleBracketed {
779 args: Default::default(),
780 constraints: ThinVec::new(),
781 },
782 }],
783 },
784 did: None,
785 },
786 true,
787 )),
788 cfg: None,
789 inline_stmt_id: None,
790 }),
791 });
792 } else if let Some(def_id) = res.opt_def_id()
793 && let Some(reexport) = item.reexport_chain.first()
794 && let Some(reexport_def_id) = reexport.id()
795 && !should_ignore_def_kind(cx.tcx.def_kind(reexport_def_id))
796 && find_attr!(
797 load_attrs(cx.tcx, reexport_def_id),
798 Doc(d)
799 if d.inline.is_some_and(|(inline, _)| inline == DocInline::NoInline)
800 )
801 {
802 if should_ignore_res(res) || matches!(res, Res::Def(DefKind::Use, _)) {
804 continue;
805 }
806 let item = Item::from_def_id_and_parts(
808 module_def_id,
809 None,
810 ItemKind::Import(clean::Import::new_simple(
811 item.ident.name,
812 clean::ImportSource {
813 path: clean::Path {
814 res,
815 segments: thin_vec![
816 clean::PathSegment {
817 name: module_name,
818 args: clean::GenericArgs::AngleBracketed {
819 args: Default::default(),
820 constraints: ThinVec::new(),
821 },
822 },
823 clean::PathSegment {
824 name: cx.tcx.item_name(def_id),
825 args: clean::GenericArgs::AngleBracketed {
826 args: Default::default(),
827 constraints: ThinVec::new(),
828 },
829 },
830 ],
831 },
832 did: None,
833 },
834 true,
835 )),
836 cx.tcx,
837 );
838 items.push(item);
839 } else if let Some(i) = try_inline(cx, res, item.ident.name, attrs, visited) {
840 items.extend(i)
841 }
842 }
843
844 items
845}
846
847pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
848 if let Some(did) = did.as_local() {
849 let hir_id = tcx.local_def_id_to_hir_id(did);
850 rustc_hir_pretty::id_to_string(&tcx, hir_id)
851 } else {
852 tcx.rendered_const(did).clone()
853 }
854}
855
856fn build_const_item(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
857 let mut generics = clean_ty_generics(cx, def_id);
858 clean::simplify::move_bounds_to_generic_parameters(&mut generics);
859 let type_ = clean_middle_ty(
860 ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity().skip_norm_wip()),
861 cx,
862 None,
863 None,
864 );
865 clean::Constant { generics, type_, body: clean::ConstantExpr::Extern { def_id } }
866}
867
868fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
869 clean::Static {
870 type_: Box::new(clean_middle_ty(
871 ty::Binder::dummy(cx.tcx.type_of(did).instantiate_identity().skip_norm_wip()),
872 cx,
873 Some(did),
874 None,
875 )),
876 mutability: if mutable { Mutability::Mut } else { Mutability::Not },
877 expr: None,
878 }
879}
880
881fn build_macro(tcx: TyCtxt<'_>, def_id: DefId, name: Symbol, macro_kinds: MacroKinds) -> ItemKind {
882 match CStore::from_tcx(tcx).load_macro_untracked(tcx, def_id) {
883 LoadedMacro::MacroDef { def, .. } => match macro_kinds {
884 MacroKinds::DERIVE => ItemKind::ProcMacro(clean::ProcMacro {
885 kind: MacroKind::Derive,
886 helpers: Vec::new(),
887 }),
888 MacroKinds::ATTR => {
889 ItemKind::ProcMacro(clean::ProcMacro { kind: MacroKind::Attr, helpers: Vec::new() })
890 }
891 _ => ItemKind::DeclMacro(
892 clean::DeclMacro {
893 source: utils::display_macro_source(tcx, name, &def),
894 macro_rules: def.macro_rules,
895 },
896 macro_kinds,
897 ),
898 },
899 LoadedMacro::ProcMacro(ext) => {
900 let kind = match ext.macro_kinds() {
902 MacroKinds::BANG => MacroKind::Bang,
903 MacroKinds::ATTR => MacroKind::Attr,
904 MacroKinds::DERIVE => MacroKind::Derive,
905 _ => unreachable!(),
906 };
907 ItemKind::ProcMacro(clean::ProcMacro { kind, helpers: ext.helper_attrs })
908 }
909 }
910}
911
912fn separate_self_bounds(mut g: clean::Generics) -> (clean::Generics, Vec<clean::GenericBound>) {
913 let mut ty_bounds = Vec::new();
914 g.where_predicates.retain(|pred| match *pred {
915 clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref bounds, .. } => {
916 ty_bounds.extend(bounds.iter().cloned());
917 false
918 }
919 _ => true,
920 });
921 (g, ty_bounds)
922}
923
924pub(crate) fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) {
925 if did.is_local()
926 || cx.external_traits.contains_key(&did)
927 || cx.active_extern_traits.contains(&did)
928 {
929 return;
930 }
931
932 cx.active_extern_traits.insert(did);
933
934 debug!("record_extern_trait: {did:?}");
935 let trait_ = build_trait(cx, did);
936
937 cx.external_traits.insert(did, trait_);
938 cx.active_extern_traits.remove(&did);
939}