1use std::iter::once;
4use std::sync::Arc;
5
6use rustc_data_structures::fx::FxHashSet;
7use rustc_data_structures::thin_vec::{ThinVec, thin_vec};
8use rustc_hir::def::{DefKind, MacroKinds, Res};
9use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LocalModDefId};
10use rustc_hir::{self as hir, Mutability, find_attr};
11use rustc_metadata::creader::{CStore, LoadedMacro};
12use rustc_middle::ty::fast_reject::SimplifiedType;
13use rustc_middle::ty::{self, TyCtxt};
14use rustc_span::def_id::LOCAL_CRATE;
15use rustc_span::hygiene::MacroKind;
16use rustc_span::symbol::{Symbol, sym};
17use tracing::{debug, trace};
18
19use super::{Item, extract_cfg_from_attrs};
20use crate::clean::{
21 self, Attributes, CfgInfo, ImplKind, ItemId, Type, clean_bound_vars, clean_generics,
22 clean_impl_item, clean_middle_assoc_item, clean_middle_field, clean_middle_ty,
23 clean_poly_fn_sig, clean_trait_ref_with_constraints, clean_ty, clean_ty_alias_inner_type,
24 clean_ty_generics, clean_variant_def, utils,
25};
26use crate::core::DocContext;
27use crate::formats::item_type::ItemType;
28
29pub(crate) fn try_inline(
42 cx: &mut DocContext<'_>,
43 res: Res,
44 name: Symbol,
45 attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
46 visited: &mut DefIdSet,
47) -> Option<Vec<clean::Item>> {
48 fn try_inline_inner(
49 cx: &mut DocContext<'_>,
50 kind: clean::ItemKind,
51 did: DefId,
52 name: Symbol,
53 import_def_id: Option<LocalDefId>,
54 ) -> clean::Item {
55 cx.inlined.insert(did.into());
56 let mut item = crate::clean::generate_item_with_correct_attrs(
57 cx,
58 kind,
59 did,
60 name,
61 import_def_id.as_slice(),
62 None,
63 );
64 item.inner.inline_stmt_id = import_def_id;
66 item
67 }
68
69 let did = res.opt_def_id()?;
70 if did.is_local() {
71 return None;
72 }
73 let mut ret = Vec::new();
74
75 debug!("attrs={attrs:?}");
76
77 let attrs_without_docs = attrs.map(|(attrs, def_id)| {
78 (attrs.iter().filter(|a| a.doc_str().is_none()).cloned().collect::<Vec<_>>(), def_id)
79 });
80 let attrs_without_docs =
81 attrs_without_docs.as_ref().map(|(attrs, def_id)| (&attrs[..], *def_id));
82
83 let import_def_id = attrs.and_then(|(_, def_id)| def_id);
84
85 let kind = match res {
86 Res::Def(DefKind::Trait, did) => {
87 record_extern_fqn(cx, did, ItemType::Trait);
88 cx.with_param_env(did, |cx| {
89 build_impls(cx, did, attrs_without_docs, &mut ret);
90 clean::TraitItem(Box::new(build_trait(cx, did)))
91 })
92 }
93 Res::Def(DefKind::TraitAlias, did) => {
94 record_extern_fqn(cx, did, ItemType::TraitAlias);
95 cx.with_param_env(did, |cx| clean::TraitAliasItem(build_trait_alias(cx, did)))
96 }
97 Res::Def(DefKind::Fn, did) => {
98 record_extern_fqn(cx, did, ItemType::Function);
99 cx.with_param_env(did, |cx| {
100 clean::enter_impl_trait(cx, |cx| clean::FunctionItem(build_function(cx, did)))
101 })
102 }
103 Res::Def(DefKind::Struct, did) => {
104 record_extern_fqn(cx, did, ItemType::Struct);
105 cx.with_param_env(did, |cx| {
106 build_impls(cx, did, attrs_without_docs, &mut ret);
107 clean::StructItem(build_struct(cx, did))
108 })
109 }
110 Res::Def(DefKind::Union, did) => {
111 record_extern_fqn(cx, did, ItemType::Union);
112 cx.with_param_env(did, |cx| {
113 build_impls(cx, did, attrs_without_docs, &mut ret);
114 clean::UnionItem(build_union(cx, did))
115 })
116 }
117 Res::Def(DefKind::TyAlias, did) => {
118 record_extern_fqn(cx, did, ItemType::TypeAlias);
119 cx.with_param_env(did, |cx| {
120 build_impls(cx, did, attrs_without_docs, &mut ret);
121 clean::TypeAliasItem(build_type_alias(cx, did, &mut ret))
122 })
123 }
124 Res::Def(DefKind::Enum, did) => {
125 record_extern_fqn(cx, did, ItemType::Enum);
126 cx.with_param_env(did, |cx| {
127 build_impls(cx, did, attrs_without_docs, &mut ret);
128 clean::EnumItem(build_enum(cx, did))
129 })
130 }
131 Res::Def(DefKind::ForeignTy, did) => {
132 record_extern_fqn(cx, did, ItemType::ForeignType);
133 cx.with_param_env(did, |cx| {
134 build_impls(cx, did, attrs_without_docs, &mut ret);
135 clean::ForeignTypeItem
136 })
137 }
138 Res::Def(DefKind::Variant, _) => return None,
140 Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) => return Some(Vec::new()),
143 Res::Def(DefKind::Mod, did) => {
144 record_extern_fqn(cx, did, ItemType::Module);
145 clean::ModuleItem(build_module(cx, did, visited))
146 }
147 Res::Def(DefKind::Static { .. }, did) => {
148 record_extern_fqn(cx, did, ItemType::Static);
149 cx.with_param_env(did, |cx| {
150 clean::StaticItem(build_static(cx, did, cx.tcx.is_mutable_static(did)))
151 })
152 }
153 Res::Def(DefKind::Const { .. }, did) => {
154 record_extern_fqn(cx, did, ItemType::Constant);
155 cx.with_param_env(did, |cx| {
156 let ct = build_const_item(cx, did);
157 clean::ConstantItem(Box::new(ct))
158 })
159 }
160 Res::Def(DefKind::Macro(kinds), did) => {
161 let mac = build_macro(cx.tcx, did, name, kinds);
162
163 let type_kind = match kinds {
164 MacroKinds::BANG => ItemType::Macro,
165 MacroKinds::ATTR => ItemType::ProcAttribute,
166 MacroKinds::DERIVE => ItemType::ProcDerive,
167 _ => ItemType::Macro,
169 };
170 record_extern_fqn(cx, did, type_kind);
171 ret.push(try_inline_inner(cx, mac, did, name, import_def_id));
172 return Some(ret);
173 }
174 _ => return None,
175 };
176
177 ret.push(try_inline_inner(cx, kind, did, name, import_def_id));
178 Some(ret)
179}
180
181pub(crate) fn try_inline_glob(
182 cx: &mut DocContext<'_>,
183 res: Res,
184 current_mod: LocalModDefId,
185 visited: &mut DefIdSet,
186 inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
187 import: &hir::Item<'_>,
188) -> Option<Vec<clean::Item>> {
189 let did = res.opt_def_id()?;
190 if did.is_local() {
191 return None;
192 }
193
194 match res {
195 Res::Def(DefKind::Mod, did) => {
196 let reexports = cx
199 .tcx
200 .module_children_local(current_mod.to_local_def_id())
201 .iter()
202 .filter(|child| !child.reexport_chain.is_empty())
203 .filter_map(|child| child.res.opt_def_id())
204 .filter(|&def_id| !cx.tcx.is_doc_hidden(def_id))
205 .collect();
206 let attrs = cx.tcx.hir_attrs(import.hir_id());
207 let mut items = build_module_items(
208 cx,
209 did,
210 visited,
211 inlined_names,
212 Some(&reexports),
213 Some((attrs, Some(import.owner_id.def_id))),
214 );
215 items.retain(|item| {
216 if let Some(name) = item.name {
217 inlined_names.insert((item.type_(), name))
220 } else {
221 true
222 }
223 });
224 Some(items)
225 }
226 _ => None,
228 }
229}
230
231pub(crate) fn load_attrs<'hir>(tcx: TyCtxt<'hir>, did: DefId) -> &'hir [hir::Attribute] {
232 #[allow(deprecated)]
234 tcx.get_all_attrs(did)
235}
236
237pub(crate) fn item_relative_path(tcx: TyCtxt<'_>, def_id: DefId) -> Vec<Symbol> {
238 tcx.def_path(def_id).data.into_iter().filter_map(|elem| elem.data.get_opt_name()).collect()
239}
240
241pub(crate) fn get_item_path(tcx: TyCtxt<'_>, def_id: DefId, kind: ItemType) -> Vec<Symbol> {
246 let crate_name = tcx.crate_name(def_id.krate);
247 let relative = item_relative_path(tcx, def_id);
248
249 if let ItemType::Macro = kind {
250 if matches!(
253 CStore::from_tcx(tcx).load_macro_untracked(tcx, def_id),
254 LoadedMacro::MacroDef { def, .. } if !def.macro_rules
255 ) {
256 once(crate_name).chain(relative).collect()
257 } else {
258 vec![crate_name, *relative.last().expect("relative was empty")]
259 }
260 } else {
261 once(crate_name).chain(relative).collect()
262 }
263}
264
265pub(crate) fn record_extern_fqn(cx: &mut DocContext<'_>, did: DefId, kind: ItemType) {
270 if did.is_local() {
271 if cx.cache.exact_paths.contains_key(&did) {
272 return;
273 }
274 } else if cx.cache.external_paths.contains_key(&did) {
275 return;
276 }
277
278 let item_path = get_item_path(cx.tcx, did, kind);
279
280 if did.is_local() {
281 cx.cache.exact_paths.insert(did, item_path);
282 } else {
283 cx.cache.external_paths.insert(did, (item_path, kind));
284 }
285}
286
287pub(crate) fn build_trait(cx: &mut DocContext<'_>, did: DefId) -> clean::Trait {
288 let trait_items = cx
289 .tcx
290 .associated_items(did)
291 .in_definition_order()
292 .filter(|item| !item.is_impl_trait_in_trait())
293 .map(|item| clean_middle_assoc_item(item, cx))
294 .collect();
295
296 let generics = clean_ty_generics(cx, did);
297 let (generics, mut supertrait_bounds) = separate_self_bounds(generics);
298
299 supertrait_bounds.retain(|b| {
300 !b.is_meta_sized_bound(cx.tcx)
303 });
304
305 clean::Trait { def_id: did, generics, items: trait_items, bounds: supertrait_bounds }
306}
307
308fn build_trait_alias(cx: &mut DocContext<'_>, did: DefId) -> clean::TraitAlias {
309 let generics = clean_ty_generics(cx, did);
310 let (generics, mut bounds) = separate_self_bounds(generics);
311
312 bounds.retain(|b| {
313 !b.is_meta_sized_bound(cx.tcx)
316 });
317
318 clean::TraitAlias { generics, bounds }
319}
320
321pub(super) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box<clean::Function> {
322 let sig = cx.tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip();
323 let mut generics = clean_ty_generics(cx, def_id);
325 let bound_vars = clean_bound_vars(sig.bound_vars(), cx.tcx);
326
327 let has_early_bound_params = !generics.params.is_empty();
337 let has_late_bound_params = !bound_vars.is_empty();
338 generics.params.extend(bound_vars);
339 if has_early_bound_params && has_late_bound_params {
340 generics.params.sort_by_key(|param| cx.tcx.def_ident_span(param.def_id).unwrap());
345 }
346
347 let decl = clean_poly_fn_sig(cx, Some(def_id), sig);
348
349 Box::new(clean::Function { decl, generics })
350}
351
352fn build_enum(cx: &mut DocContext<'_>, did: DefId) -> clean::Enum {
353 clean::Enum {
354 generics: clean_ty_generics(cx, did),
355 variants: cx.tcx.adt_def(did).variants().iter().map(|v| clean_variant_def(v, cx)).collect(),
356 }
357}
358
359fn build_struct(cx: &mut DocContext<'_>, did: DefId) -> clean::Struct {
360 let variant = cx.tcx.adt_def(did).non_enum_variant();
361
362 clean::Struct {
363 ctor_kind: variant.ctor_kind(),
364 generics: clean_ty_generics(cx, did),
365 fields: variant.fields.iter().map(|x| clean_middle_field(x, cx)).collect(),
366 }
367}
368
369fn build_union(cx: &mut DocContext<'_>, did: DefId) -> clean::Union {
370 let variant = cx.tcx.adt_def(did).non_enum_variant();
371
372 let generics = clean_ty_generics(cx, did);
373 let fields = variant.fields.iter().map(|x| clean_middle_field(x, cx)).collect();
374 clean::Union { generics, fields }
375}
376
377fn build_type_alias(
378 cx: &mut DocContext<'_>,
379 did: DefId,
380 ret: &mut Vec<Item>,
381) -> Box<clean::TypeAlias> {
382 let ty = cx.tcx.type_of(did).instantiate_identity().skip_norm_wip();
383 let type_ = clean_middle_ty(ty::Binder::dummy(ty), cx, Some(did), None);
384 let inner_type = clean_ty_alias_inner_type(ty, cx, ret);
385
386 Box::new(clean::TypeAlias {
387 type_,
388 generics: clean_ty_generics(cx, did),
389 inner_type,
390 item_type: None,
391 })
392}
393
394pub(crate) fn build_impls(
396 cx: &mut DocContext<'_>,
397 did: DefId,
398 attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
399 ret: &mut Vec<clean::Item>,
400) {
401 let tcx = cx.tcx;
402 let _prof_timer = tcx.sess.prof.generic_activity("build_inherent_impls");
403
404 for &did in tcx.inherent_impls(did).iter() {
406 cx.with_param_env(did, |cx| {
407 build_impl(cx, did, attrs, ret);
408 });
409 }
410
411 if find_attr!(tcx, did, RustcHasIncoherentInherentImpls) {
418 let type_ =
419 if tcx.is_trait(did) { SimplifiedType::Trait(did) } else { SimplifiedType::Adt(did) };
420 for &did in tcx.incoherent_impls(type_).iter() {
421 cx.with_param_env(did, |cx| {
422 build_impl(cx, did, attrs, ret);
423 });
424 }
425 }
426}
427
428pub(crate) fn merge_attrs(
429 tcx: TyCtxt<'_>,
430 old_attrs: &[hir::Attribute],
431 new_attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
432 cfg_info: &mut CfgInfo,
433) -> (clean::Attributes, Option<Arc<clean::cfg::Cfg>>) {
434 if let Some((inner, item_id)) = new_attrs {
439 let mut both = inner.to_vec();
440 both.extend_from_slice(old_attrs);
441 (
442 if let Some(item_id) = item_id {
443 Attributes::from_hir_with_additional(old_attrs, (inner, item_id.to_def_id()))
444 } else {
445 Attributes::from_hir(&both)
446 },
447 extract_cfg_from_attrs(both.iter(), tcx, cfg_info),
448 )
449 } else {
450 (Attributes::from_hir(old_attrs), extract_cfg_from_attrs(old_attrs.iter(), tcx, cfg_info))
451 }
452}
453
454pub(crate) fn build_impl(
456 cx: &mut DocContext<'_>,
457 did: DefId,
458 attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
459 ret: &mut Vec<clean::Item>,
460) {
461 if !cx.inlined.insert(did.into()) {
462 return;
463 }
464
465 let tcx = cx.tcx;
466 let _prof_timer = tcx.sess.prof.generic_activity("build_impl");
467
468 let associated_trait = tcx.impl_opt_trait_ref(did).map(ty::EarlyBinder::skip_binder);
469
470 let is_compiler_internal = |did| {
472 tcx.lookup_stability(did)
473 .is_some_and(|stab| stab.is_unstable() && stab.feature == sym::rustc_private)
474 };
475 let document_compiler_internal = is_compiler_internal(LOCAL_CRATE.as_def_id());
476 let is_directly_public = |cx: &mut DocContext<'_>, did| {
477 cx.cache.effective_visibilities.is_directly_public(tcx, did)
478 && (document_compiler_internal || !is_compiler_internal(did))
479 };
480
481 if !did.is_local()
484 && let Some(traitref) = associated_trait
485 && !is_directly_public(cx, traitref.def_id)
486 {
487 return;
488 }
489
490 let impl_item = match did.as_local() {
491 Some(did) => match &tcx.hir_expect_item(did).kind {
492 hir::ItemKind::Impl(impl_) => Some(impl_),
493 _ => panic!("`DefID` passed to `build_impl` is not an `impl"),
494 },
495 None => None,
496 };
497
498 let for_ = match &impl_item {
499 Some(impl_) => clean_ty(impl_.self_ty, cx),
500 None => clean_middle_ty(
501 ty::Binder::dummy(tcx.type_of(did).instantiate_identity().skip_norm_wip()),
502 cx,
503 Some(did),
504 None,
505 ),
506 };
507
508 if !did.is_local()
511 && let Some(did) = for_.def_id(&cx.cache)
512 && !is_directly_public(cx, did)
513 {
514 return;
515 }
516
517 let document_hidden = cx.document_hidden();
518 let (trait_items, generics) = match impl_item {
519 Some(impl_) => (
520 impl_
521 .items
522 .iter()
523 .map(|&item| tcx.hir_impl_item(item))
524 .filter(|item| {
525 if document_hidden {
532 return true;
533 }
534 if let Some(associated_trait) = associated_trait {
535 let assoc_tag = match item.kind {
536 hir::ImplItemKind::Const(..) => ty::AssocTag::Const,
537 hir::ImplItemKind::Fn(..) => ty::AssocTag::Fn,
538 hir::ImplItemKind::Type(..) => ty::AssocTag::Type,
539 };
540 let trait_item = tcx
541 .associated_items(associated_trait.def_id)
542 .find_by_ident_and_kind(
543 tcx,
544 item.ident,
545 assoc_tag,
546 associated_trait.def_id,
547 )
548 .unwrap(); !tcx.is_doc_hidden(trait_item.def_id)
550 } else {
551 true
552 }
553 })
554 .map(|item| clean_impl_item(item, cx))
555 .collect::<Vec<_>>(),
556 clean_generics(impl_.generics, cx),
557 ),
558 None => (
559 tcx.associated_items(did)
560 .in_definition_order()
561 .filter(|item| !item.is_impl_trait_in_trait())
562 .filter(|item| {
563 if let Some(associated_trait) = associated_trait {
567 let trait_item = tcx
568 .associated_items(associated_trait.def_id)
569 .find_by_ident_and_kind(
570 tcx,
571 item.ident(tcx),
572 item.tag(),
573 associated_trait.def_id,
574 )
575 .unwrap(); document_hidden || !tcx.is_doc_hidden(trait_item.def_id)
577 } else {
578 item.visibility(tcx).is_public()
579 }
580 })
581 .map(|item| clean_middle_assoc_item(item, cx))
582 .collect::<Vec<_>>(),
583 clean::enter_impl_trait(cx, |cx| clean_ty_generics(cx, did)),
584 ),
585 };
586 let polarity = if associated_trait.is_some() {
587 tcx.impl_polarity(did)
588 } else {
589 ty::ImplPolarity::Positive
590 };
591 let trait_ = associated_trait
592 .map(|t| clean_trait_ref_with_constraints(cx, ty::Binder::dummy(t), ThinVec::new()));
593 if trait_.as_ref().map(|t| t.def_id()) == tcx.lang_items().deref_trait()
594 && polarity != ty::ImplPolarity::Negative
595 {
596 super::build_deref_target_impls(cx, &trait_items, ret);
597 }
598
599 if !document_hidden {
600 let mut stack: Vec<&Type> = vec![&for_];
602
603 if let Some(did) = trait_.as_ref().map(|t| t.def_id())
604 && tcx.is_doc_hidden(did)
605 {
606 return;
607 }
608
609 if let Some(generics) = trait_.as_ref().and_then(|t| t.generics()) {
610 stack.extend(generics);
611 }
612
613 while let Some(ty) = stack.pop() {
614 if let Some(did) = ty.def_id(&cx.cache)
615 && tcx.is_doc_hidden(did)
616 {
617 return;
618 }
619 if let Some(generics) = ty.generics() {
620 stack.extend(generics);
621 }
622 }
623 }
624
625 if let Some(did) = trait_.as_ref().map(|t| t.def_id()) {
626 cx.with_param_env(did, |cx| {
627 record_extern_trait(cx, did);
628 });
629 }
630
631 let (merged_attrs, cfg) =
636 merge_attrs(cx.tcx, load_attrs(cx.tcx, did), attrs, &mut CfgInfo::default());
637 trace!("merged_attrs={merged_attrs:?}");
638
639 trace!(
640 "build_impl: impl {:?} for {:?}",
641 trait_.as_ref().map(|t| t.def_id()),
642 for_.def_id(&cx.cache)
643 );
644 ret.push(clean::Item::from_def_id_and_attrs_and_parts(
645 did,
646 None,
647 clean::ImplItem(Box::new(clean::Impl {
648 safety: hir::Safety::Safe,
649 generics,
650 trait_,
651 for_,
652 items: trait_items,
653 polarity,
654 kind: if utils::has_doc_flag(tcx, did, |d| d.fake_variadic.is_some()) {
655 ImplKind::FakeVariadic
656 } else {
657 ImplKind::Normal
658 },
659 is_deprecated: tcx
660 .lookup_deprecation(did)
661 .is_some_and(|deprecation| deprecation.is_in_effect()),
662 })),
663 merged_attrs,
664 cfg,
665 ));
666}
667
668fn build_module(cx: &mut DocContext<'_>, did: DefId, visited: &mut DefIdSet) -> clean::Module {
669 let items = build_module_items(cx, did, visited, &mut FxHashSet::default(), None, None);
670
671 let span = clean::Span::new(cx.tcx.def_span(did));
672 clean::Module { items, span }
673}
674
675fn build_module_items(
676 cx: &mut DocContext<'_>,
677 did: DefId,
678 visited: &mut DefIdSet,
679 inlined_names: &mut FxHashSet<(ItemType, Symbol)>,
680 allowed_def_ids: Option<&DefIdSet>,
681 attrs: Option<(&[hir::Attribute], Option<LocalDefId>)>,
682) -> Vec<clean::Item> {
683 let mut items = Vec::new();
684
685 for item in cx.tcx.module_children(did).iter() {
689 if item.vis.is_public() {
690 let res = item.res.expect_non_local();
691 if let Some(def_id) = res.opt_def_id()
692 && let Some(allowed_def_ids) = allowed_def_ids
693 && !allowed_def_ids.contains(&def_id)
694 {
695 continue;
696 }
697 if let Some(def_id) = res.mod_def_id() {
698 if did == def_id
702 || inlined_names.contains(&(ItemType::Module, item.ident.name))
703 || !visited.insert(def_id)
704 {
705 continue;
706 }
707 }
708 if let Res::PrimTy(p) = res {
709 let prim_ty = clean::PrimitiveType::from(p);
711 items.push(clean::Item {
712 inner: Box::new(clean::ItemInner {
713 name: None,
714 item_id: ItemId::DefId(did),
717 attrs: Default::default(),
718 stability: None,
719 kind: clean::ImportItem(clean::Import::new_simple(
720 item.ident.name,
721 clean::ImportSource {
722 path: clean::Path {
723 res,
724 segments: thin_vec![clean::PathSegment {
725 name: prim_ty.as_sym(),
726 args: clean::GenericArgs::AngleBracketed {
727 args: Default::default(),
728 constraints: ThinVec::new(),
729 },
730 }],
731 },
732 did: None,
733 },
734 true,
735 )),
736 cfg: None,
737 inline_stmt_id: None,
738 }),
739 });
740 } else if let Some(i) = try_inline(cx, res, item.ident.name, attrs, visited) {
741 items.extend(i)
742 }
743 }
744 }
745
746 items
747}
748
749pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
750 if let Some(did) = did.as_local() {
751 let hir_id = tcx.local_def_id_to_hir_id(did);
752 rustc_hir_pretty::id_to_string(&tcx, hir_id)
753 } else {
754 tcx.rendered_const(did).clone()
755 }
756}
757
758fn build_const_item(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
759 let mut generics = clean_ty_generics(cx, def_id);
760 clean::simplify::move_bounds_to_generic_parameters(&mut generics);
761 let ty = clean_middle_ty(
762 ty::Binder::dummy(cx.tcx.type_of(def_id).instantiate_identity().skip_norm_wip()),
763 cx,
764 None,
765 None,
766 );
767 clean::Constant { generics, type_: ty, kind: clean::ConstantKind::Extern { def_id } }
768}
769
770fn build_static(cx: &mut DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
771 clean::Static {
772 type_: Box::new(clean_middle_ty(
773 ty::Binder::dummy(cx.tcx.type_of(did).instantiate_identity().skip_norm_wip()),
774 cx,
775 Some(did),
776 None,
777 )),
778 mutability: if mutable { Mutability::Mut } else { Mutability::Not },
779 expr: None,
780 }
781}
782
783fn build_macro(
784 tcx: TyCtxt<'_>,
785 def_id: DefId,
786 name: Symbol,
787 macro_kinds: MacroKinds,
788) -> clean::ItemKind {
789 match CStore::from_tcx(tcx).load_macro_untracked(tcx, def_id) {
790 LoadedMacro::MacroDef { def, .. } => match macro_kinds {
791 MacroKinds::DERIVE => clean::ProcMacroItem(clean::ProcMacro {
792 kind: MacroKind::Derive,
793 helpers: Vec::new(),
794 }),
795 MacroKinds::ATTR => clean::ProcMacroItem(clean::ProcMacro {
796 kind: MacroKind::Attr,
797 helpers: Vec::new(),
798 }),
799 _ => clean::MacroItem(
800 clean::Macro {
801 source: utils::display_macro_source(tcx, name, &def),
802 macro_rules: def.macro_rules,
803 },
804 macro_kinds,
805 ),
806 },
807 LoadedMacro::ProcMacro(ext) => {
808 let kind = match ext.macro_kinds() {
810 MacroKinds::BANG => MacroKind::Bang,
811 MacroKinds::ATTR => MacroKind::Attr,
812 MacroKinds::DERIVE => MacroKind::Derive,
813 _ => unreachable!(),
814 };
815 clean::ProcMacroItem(clean::ProcMacro { kind, helpers: ext.helper_attrs })
816 }
817 }
818}
819
820fn separate_self_bounds(mut g: clean::Generics) -> (clean::Generics, Vec<clean::GenericBound>) {
821 let mut ty_bounds = Vec::new();
822 g.where_predicates.retain(|pred| match *pred {
823 clean::WherePredicate::BoundPredicate { ty: clean::SelfTy, ref bounds, .. } => {
824 ty_bounds.extend(bounds.iter().cloned());
825 false
826 }
827 _ => true,
828 });
829 (g, ty_bounds)
830}
831
832pub(crate) fn record_extern_trait(cx: &mut DocContext<'_>, did: DefId) {
833 if did.is_local()
834 || cx.external_traits.contains_key(&did)
835 || cx.active_extern_traits.contains(&did)
836 {
837 return;
838 }
839
840 cx.active_extern_traits.insert(did);
841
842 debug!("record_extern_trait: {did:?}");
843 let trait_ = build_trait(cx, did);
844
845 cx.external_traits.insert(did, trait_);
846 cx.active_extern_traits.remove(&did);
847}