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