]> git.lizzy.rs Git - rust.git/blob - src/librustdoc/json/conversions.rs
Auto merge of #86231 - nagisa:nagisa/abi-allowlist, r=petrochenkov
[rust.git] / src / librustdoc / json / conversions.rs
1 //! These from impls are used to create the JSON types which get serialized. They're very close to
2 //! the `clean` types but with some fields removed or stringified to simplify the output and not
3 //! expose unstable compiler internals.
4
5 #![allow(rustc::default_hash_types)]
6
7 use std::convert::From;
8 use std::fmt;
9
10 use rustc_ast::ast;
11 use rustc_hir::{def::CtorKind, def_id::DefId};
12 use rustc_middle::ty::TyCtxt;
13 use rustc_span::def_id::CRATE_DEF_INDEX;
14 use rustc_span::Pos;
15
16 use rustdoc_json_types::*;
17
18 use crate::clean::utils::print_const_expr;
19 use crate::clean::{self, ItemId};
20 use crate::formats::item_type::ItemType;
21 use crate::json::JsonRenderer;
22 use std::collections::HashSet;
23
24 impl JsonRenderer<'_> {
25     pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
26         let deprecation = item.deprecation(self.tcx);
27         let links = self
28             .cache
29             .intra_doc_links
30             .get(&item.def_id)
31             .into_iter()
32             .flatten()
33             .filter_map(|clean::ItemLink { link, did, .. }| {
34                 did.map(|did| (link.clone(), from_item_id(did.into())))
35             })
36             .collect();
37         let docs = item.attrs.collapsed_doc_value();
38         let attrs = item
39             .attrs
40             .other_attrs
41             .iter()
42             .map(rustc_ast_pretty::pprust::attribute_to_string)
43             .collect();
44         let span = item.span(self.tcx);
45         let clean::Item { name, attrs: _, kind: _, visibility, def_id, cfg: _ } = item;
46         let inner = match *item.kind {
47             clean::StrippedItem(_) => return None,
48             _ => from_clean_item(item, self.tcx),
49         };
50         Some(Item {
51             id: from_item_id(def_id),
52             crate_id: def_id.krate().as_u32(),
53             name: name.map(|sym| sym.to_string()),
54             span: self.convert_span(span),
55             visibility: self.convert_visibility(visibility),
56             docs,
57             attrs,
58             deprecation: deprecation.map(from_deprecation),
59             inner,
60             links,
61         })
62     }
63
64     fn convert_span(&self, span: clean::Span) -> Option<Span> {
65         match span.filename(self.sess()) {
66             rustc_span::FileName::Real(name) => {
67                 if let Some(local_path) = name.into_local_path() {
68                     let hi = span.hi(self.sess());
69                     let lo = span.lo(self.sess());
70                     Some(Span {
71                         filename: local_path,
72                         begin: (lo.line, lo.col.to_usize()),
73                         end: (hi.line, hi.col.to_usize()),
74                     })
75                 } else {
76                     None
77                 }
78             }
79             _ => None,
80         }
81     }
82
83     fn convert_visibility(&self, v: clean::Visibility) -> Visibility {
84         use clean::Visibility::*;
85         match v {
86             Public => Visibility::Public,
87             Inherited => Visibility::Default,
88             Restricted(did) if did.index == CRATE_DEF_INDEX => Visibility::Crate,
89             Restricted(did) => Visibility::Restricted {
90                 parent: from_item_id(did.into()),
91                 path: self.tcx.def_path(did).to_string_no_crate_verbose(),
92             },
93         }
94     }
95 }
96
97 crate trait FromWithTcx<T> {
98     fn from_tcx(f: T, tcx: TyCtxt<'_>) -> Self;
99 }
100
101 crate trait IntoWithTcx<T> {
102     fn into_tcx(self, tcx: TyCtxt<'_>) -> T;
103 }
104
105 impl<T, U> IntoWithTcx<U> for T
106 where
107     U: FromWithTcx<T>,
108 {
109     fn into_tcx(self, tcx: TyCtxt<'_>) -> U {
110         U::from_tcx(self, tcx)
111     }
112 }
113
114 crate fn from_deprecation(deprecation: rustc_attr::Deprecation) -> Deprecation {
115     #[rustfmt::skip]
116     let rustc_attr::Deprecation { since, note, is_since_rustc_version: _, suggestion: _ } = deprecation;
117     Deprecation { since: since.map(|s| s.to_string()), note: note.map(|s| s.to_string()) }
118 }
119
120 impl FromWithTcx<clean::GenericArgs> for GenericArgs {
121     fn from_tcx(args: clean::GenericArgs, tcx: TyCtxt<'_>) -> Self {
122         use clean::GenericArgs::*;
123         match args {
124             AngleBracketed { args, bindings } => GenericArgs::AngleBracketed {
125                 args: args.into_iter().map(|a| a.into_tcx(tcx)).collect(),
126                 bindings: bindings.into_iter().map(|a| a.into_tcx(tcx)).collect(),
127             },
128             Parenthesized { inputs, output } => GenericArgs::Parenthesized {
129                 inputs: inputs.into_iter().map(|a| a.into_tcx(tcx)).collect(),
130                 output: output.map(|a| a.into_tcx(tcx)),
131             },
132         }
133     }
134 }
135
136 impl FromWithTcx<clean::GenericArg> for GenericArg {
137     fn from_tcx(arg: clean::GenericArg, tcx: TyCtxt<'_>) -> Self {
138         use clean::GenericArg::*;
139         match arg {
140             Lifetime(l) => GenericArg::Lifetime(l.0.to_string()),
141             Type(t) => GenericArg::Type(t.into_tcx(tcx)),
142             Const(c) => GenericArg::Const(c.into_tcx(tcx)),
143         }
144     }
145 }
146
147 impl FromWithTcx<clean::Constant> for Constant {
148     fn from_tcx(constant: clean::Constant, tcx: TyCtxt<'_>) -> Self {
149         let expr = constant.expr(tcx);
150         let value = constant.value(tcx);
151         let is_literal = constant.is_literal(tcx);
152         Constant { type_: constant.type_.into_tcx(tcx), expr, value, is_literal }
153     }
154 }
155
156 impl FromWithTcx<clean::TypeBinding> for TypeBinding {
157     fn from_tcx(binding: clean::TypeBinding, tcx: TyCtxt<'_>) -> Self {
158         TypeBinding { name: binding.name.to_string(), binding: binding.kind.into_tcx(tcx) }
159     }
160 }
161
162 impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind {
163     fn from_tcx(kind: clean::TypeBindingKind, tcx: TyCtxt<'_>) -> Self {
164         use clean::TypeBindingKind::*;
165         match kind {
166             Equality { ty } => TypeBindingKind::Equality(ty.into_tcx(tcx)),
167             Constraint { bounds } => {
168                 TypeBindingKind::Constraint(bounds.into_iter().map(|a| a.into_tcx(tcx)).collect())
169             }
170         }
171     }
172 }
173
174 crate fn from_item_id(did: ItemId) -> Id {
175     struct DisplayDefId(DefId);
176
177     impl fmt::Display for DisplayDefId {
178         fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
179             write!(f, "{}:{}", self.0.krate.as_u32(), u32::from(self.0.index))
180         }
181     }
182
183     match did {
184         ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did))),
185         ItemId::Blanket { for_, impl_id } => {
186             Id(format!("b:{}-{}", DisplayDefId(impl_id), DisplayDefId(for_)))
187         }
188         ItemId::Auto { for_, trait_ } => {
189             Id(format!("a:{}-{}", DisplayDefId(trait_), DisplayDefId(for_)))
190         }
191         ItemId::Primitive(ty, krate) => Id(format!("p:{}:{}", krate.as_u32(), ty.as_sym())),
192     }
193 }
194
195 fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
196     use clean::ItemKind::*;
197     let name = item.name;
198     let is_crate = item.is_crate();
199     match *item.kind {
200         ModuleItem(m) => ItemEnum::Module(Module { is_crate, items: ids(m.items) }),
201         ImportItem(i) => ItemEnum::Import(i.into_tcx(tcx)),
202         StructItem(s) => ItemEnum::Struct(s.into_tcx(tcx)),
203         UnionItem(u) => ItemEnum::Union(u.into_tcx(tcx)),
204         StructFieldItem(f) => ItemEnum::StructField(f.into_tcx(tcx)),
205         EnumItem(e) => ItemEnum::Enum(e.into_tcx(tcx)),
206         VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)),
207         FunctionItem(f) => ItemEnum::Function(f.into_tcx(tcx)),
208         ForeignFunctionItem(f) => ItemEnum::Function(f.into_tcx(tcx)),
209         TraitItem(t) => ItemEnum::Trait(t.into_tcx(tcx)),
210         TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)),
211         MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, tcx)),
212         TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, tcx)),
213         ImplItem(i) => ItemEnum::Impl(i.into_tcx(tcx)),
214         StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
215         ForeignStaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
216         ForeignTypeItem => ItemEnum::ForeignType,
217         TypedefItem(t, _) => ItemEnum::Typedef(t.into_tcx(tcx)),
218         OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)),
219         ConstantItem(c) => ItemEnum::Constant(c.into_tcx(tcx)),
220         MacroItem(m) => ItemEnum::Macro(m.source),
221         ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_tcx(tcx)),
222         AssocConstItem(t, s) => ItemEnum::AssocConst { type_: t.into_tcx(tcx), default: s },
223         AssocTypeItem(g, t) => ItemEnum::AssocType {
224             bounds: g.into_iter().map(|x| x.into_tcx(tcx)).collect(),
225             default: t.map(|x| x.into_tcx(tcx)),
226         },
227         // `convert_item` early returns `None` for striped items
228         StrippedItem(_) => unreachable!(),
229         PrimitiveItem(_) | KeywordItem(_) => {
230             panic!("{:?} is not supported for JSON output", item)
231         }
232         ExternCrateItem { ref src } => ItemEnum::ExternCrate {
233             name: name.as_ref().unwrap().to_string(),
234             rename: src.map(|x| x.to_string()),
235         },
236     }
237 }
238
239 impl FromWithTcx<clean::Struct> for Struct {
240     fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self {
241         let clean::Struct { struct_type, generics, fields, fields_stripped } = struct_;
242         Struct {
243             struct_type: from_ctor_kind(struct_type),
244             generics: generics.into_tcx(tcx),
245             fields_stripped,
246             fields: ids(fields),
247             impls: Vec::new(), // Added in JsonRenderer::item
248         }
249     }
250 }
251
252 impl FromWithTcx<clean::Union> for Union {
253     fn from_tcx(struct_: clean::Union, tcx: TyCtxt<'_>) -> Self {
254         let clean::Union { generics, fields, fields_stripped } = struct_;
255         Union {
256             generics: generics.into_tcx(tcx),
257             fields_stripped,
258             fields: ids(fields),
259             impls: Vec::new(), // Added in JsonRenderer::item
260         }
261     }
262 }
263
264 crate fn from_ctor_kind(struct_type: CtorKind) -> StructType {
265     match struct_type {
266         CtorKind::Fictive => StructType::Plain,
267         CtorKind::Fn => StructType::Tuple,
268         CtorKind::Const => StructType::Unit,
269     }
270 }
271
272 crate fn from_fn_header(header: &rustc_hir::FnHeader) -> HashSet<Qualifiers> {
273     let mut v = HashSet::new();
274
275     if let rustc_hir::Unsafety::Unsafe = header.unsafety {
276         v.insert(Qualifiers::Unsafe);
277     }
278
279     if let rustc_hir::IsAsync::Async = header.asyncness {
280         v.insert(Qualifiers::Async);
281     }
282
283     if let rustc_hir::Constness::Const = header.constness {
284         v.insert(Qualifiers::Const);
285     }
286
287     v
288 }
289
290 impl FromWithTcx<clean::Function> for Function {
291     fn from_tcx(function: clean::Function, tcx: TyCtxt<'_>) -> Self {
292         let clean::Function { decl, generics, header } = function;
293         Function {
294             decl: decl.into_tcx(tcx),
295             generics: generics.into_tcx(tcx),
296             header: from_fn_header(&header),
297             abi: header.abi.to_string(),
298         }
299     }
300 }
301
302 impl FromWithTcx<clean::Generics> for Generics {
303     fn from_tcx(generics: clean::Generics, tcx: TyCtxt<'_>) -> Self {
304         Generics {
305             params: generics.params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
306             where_predicates: generics
307                 .where_predicates
308                 .into_iter()
309                 .map(|x| x.into_tcx(tcx))
310                 .collect(),
311         }
312     }
313 }
314
315 impl FromWithTcx<clean::GenericParamDef> for GenericParamDef {
316     fn from_tcx(generic_param: clean::GenericParamDef, tcx: TyCtxt<'_>) -> Self {
317         GenericParamDef {
318             name: generic_param.name.to_string(),
319             kind: generic_param.kind.into_tcx(tcx),
320         }
321     }
322 }
323
324 impl FromWithTcx<clean::GenericParamDefKind> for GenericParamDefKind {
325     fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self {
326         use clean::GenericParamDefKind::*;
327         match kind {
328             Lifetime => GenericParamDefKind::Lifetime,
329             Type { did: _, bounds, default, synthetic: _ } => GenericParamDefKind::Type {
330                 bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
331                 default: default.map(|x| x.into_tcx(tcx)),
332             },
333             Const { did: _, ty, default } => {
334                 GenericParamDefKind::Const { ty: ty.into_tcx(tcx), default }
335             }
336         }
337     }
338 }
339
340 impl FromWithTcx<clean::WherePredicate> for WherePredicate {
341     fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self {
342         use clean::WherePredicate::*;
343         match predicate {
344             BoundPredicate { ty, bounds, .. } => WherePredicate::BoundPredicate {
345                 ty: ty.into_tcx(tcx),
346                 bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
347                 // FIXME: add `bound_params` to rustdoc-json-params?
348             },
349             RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate {
350                 lifetime: lifetime.0.to_string(),
351                 bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
352             },
353             EqPredicate { lhs, rhs } => {
354                 WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) }
355             }
356         }
357     }
358 }
359
360 impl FromWithTcx<clean::GenericBound> for GenericBound {
361     fn from_tcx(bound: clean::GenericBound, tcx: TyCtxt<'_>) -> Self {
362         use clean::GenericBound::*;
363         match bound {
364             TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => {
365                 GenericBound::TraitBound {
366                     trait_: trait_.into_tcx(tcx),
367                     generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
368                     modifier: from_trait_bound_modifier(modifier),
369                 }
370             }
371             Outlives(lifetime) => GenericBound::Outlives(lifetime.0.to_string()),
372         }
373     }
374 }
375
376 crate fn from_trait_bound_modifier(modifier: rustc_hir::TraitBoundModifier) -> TraitBoundModifier {
377     use rustc_hir::TraitBoundModifier::*;
378     match modifier {
379         None => TraitBoundModifier::None,
380         Maybe => TraitBoundModifier::Maybe,
381         MaybeConst => TraitBoundModifier::MaybeConst,
382     }
383 }
384
385 impl FromWithTcx<clean::Type> for Type {
386     fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
387         use clean::Type::*;
388         match ty {
389             ResolvedPath { path, did, is_generic: _ } => Type::ResolvedPath {
390                 name: path.whole_name(),
391                 id: from_item_id(did.into()),
392                 args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
393                 param_names: Vec::new(),
394             },
395             DynTrait(mut bounds, lt) => {
396                 let (path, id) = match bounds.remove(0).trait_ {
397                     ResolvedPath { path, did, .. } => (path, did),
398                     _ => unreachable!(),
399                 };
400
401                 Type::ResolvedPath {
402                     name: path.whole_name(),
403                     id: from_item_id(id.into()),
404                     args: path
405                         .segments
406                         .last()
407                         .map(|args| Box::new(args.clone().args.into_tcx(tcx))),
408                     param_names: bounds
409                         .into_iter()
410                         .map(|t| {
411                             clean::GenericBound::TraitBound(t, rustc_hir::TraitBoundModifier::None)
412                         })
413                         .chain(lt.into_iter().map(|lt| clean::GenericBound::Outlives(lt)))
414                         .map(|bound| bound.into_tcx(tcx))
415                         .collect(),
416                 }
417             }
418             Generic(s) => Type::Generic(s.to_string()),
419             Primitive(p) => Type::Primitive(p.as_sym().to_string()),
420             BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
421             Tuple(t) => Type::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()),
422             Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))),
423             Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s },
424             ImplTrait(g) => Type::ImplTrait(g.into_iter().map(|x| x.into_tcx(tcx)).collect()),
425             Never => Type::Never,
426             Infer => Type::Infer,
427             RawPointer(mutability, type_) => Type::RawPointer {
428                 mutable: mutability == ast::Mutability::Mut,
429                 type_: Box::new((*type_).into_tcx(tcx)),
430             },
431             BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef {
432                 lifetime: lifetime.map(|l| l.0.to_string()),
433                 mutable: mutability == ast::Mutability::Mut,
434                 type_: Box::new((*type_).into_tcx(tcx)),
435             },
436             QPath { name, self_type, trait_, .. } => Type::QualifiedPath {
437                 name: name.to_string(),
438                 self_type: Box::new((*self_type).into_tcx(tcx)),
439                 trait_: Box::new((*trait_).into_tcx(tcx)),
440             },
441         }
442     }
443 }
444
445 impl FromWithTcx<clean::BareFunctionDecl> for FunctionPointer {
446     fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self {
447         let clean::BareFunctionDecl { unsafety, generic_params, decl, abi } = bare_decl;
448         FunctionPointer {
449             header: if let rustc_hir::Unsafety::Unsafe = unsafety {
450                 let mut hs = HashSet::new();
451                 hs.insert(Qualifiers::Unsafe);
452                 hs
453             } else {
454                 HashSet::new()
455             },
456             generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
457             decl: decl.into_tcx(tcx),
458             abi: abi.to_string(),
459         }
460     }
461 }
462
463 impl FromWithTcx<clean::FnDecl> for FnDecl {
464     fn from_tcx(decl: clean::FnDecl, tcx: TyCtxt<'_>) -> Self {
465         let clean::FnDecl { inputs, output, c_variadic } = decl;
466         FnDecl {
467             inputs: inputs
468                 .values
469                 .into_iter()
470                 .map(|arg| (arg.name.to_string(), arg.type_.into_tcx(tcx)))
471                 .collect(),
472             output: match output {
473                 clean::FnRetTy::Return(t) => Some(t.into_tcx(tcx)),
474                 clean::FnRetTy::DefaultReturn => None,
475             },
476             c_variadic,
477         }
478     }
479 }
480
481 impl FromWithTcx<clean::Trait> for Trait {
482     fn from_tcx(trait_: clean::Trait, tcx: TyCtxt<'_>) -> Self {
483         let clean::Trait { unsafety, items, generics, bounds, is_auto } = trait_;
484         Trait {
485             is_auto,
486             is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
487             items: ids(items),
488             generics: generics.into_tcx(tcx),
489             bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
490             implementors: Vec::new(), // Added in JsonRenderer::item
491         }
492     }
493 }
494
495 impl FromWithTcx<clean::Impl> for Impl {
496     fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
497         let provided_trait_methods = impl_.provided_trait_methods(tcx);
498         let clean::Impl {
499             unsafety,
500             generics,
501             trait_,
502             for_,
503             items,
504             negative_polarity,
505             synthetic,
506             blanket_impl,
507             span: _span,
508         } = impl_;
509         Impl {
510             is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
511             generics: generics.into_tcx(tcx),
512             provided_trait_methods: provided_trait_methods
513                 .into_iter()
514                 .map(|x| x.to_string())
515                 .collect(),
516             trait_: trait_.map(|x| x.into_tcx(tcx)),
517             for_: for_.into_tcx(tcx),
518             items: ids(items),
519             negative: negative_polarity,
520             synthetic,
521             blanket_impl: blanket_impl.map(|x| (*x).into_tcx(tcx)),
522         }
523     }
524 }
525
526 crate fn from_function_method(
527     function: clean::Function,
528     has_body: bool,
529     tcx: TyCtxt<'_>,
530 ) -> Method {
531     let clean::Function { header, decl, generics } = function;
532     Method {
533         decl: decl.into_tcx(tcx),
534         generics: generics.into_tcx(tcx),
535         header: from_fn_header(&header),
536         abi: header.abi.to_string(),
537         has_body,
538     }
539 }
540
541 impl FromWithTcx<clean::Enum> for Enum {
542     fn from_tcx(enum_: clean::Enum, tcx: TyCtxt<'_>) -> Self {
543         let clean::Enum { variants, generics, variants_stripped } = enum_;
544         Enum {
545             generics: generics.into_tcx(tcx),
546             variants_stripped,
547             variants: ids(variants),
548             impls: Vec::new(), // Added in JsonRenderer::item
549         }
550     }
551 }
552
553 impl FromWithTcx<clean::VariantStruct> for Struct {
554     fn from_tcx(struct_: clean::VariantStruct, _tcx: TyCtxt<'_>) -> Self {
555         let clean::VariantStruct { struct_type, fields, fields_stripped } = struct_;
556         Struct {
557             struct_type: from_ctor_kind(struct_type),
558             generics: Default::default(),
559             fields_stripped,
560             fields: ids(fields),
561             impls: Vec::new(),
562         }
563     }
564 }
565
566 impl FromWithTcx<clean::Variant> for Variant {
567     fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
568         use clean::Variant::*;
569         match variant {
570             CLike => Variant::Plain,
571             Tuple(t) => Variant::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()),
572             Struct(s) => Variant::Struct(ids(s.fields)),
573         }
574     }
575 }
576
577 impl FromWithTcx<clean::Import> for Import {
578     fn from_tcx(import: clean::Import, _tcx: TyCtxt<'_>) -> Self {
579         use clean::ImportKind::*;
580         match import.kind {
581             Simple(s) => Import {
582                 source: import.source.path.whole_name(),
583                 name: s.to_string(),
584                 id: import.source.did.map(ItemId::from).map(from_item_id),
585                 glob: false,
586             },
587             Glob => Import {
588                 source: import.source.path.whole_name(),
589                 name: import.source.path.last_name().to_string(),
590                 id: import.source.did.map(ItemId::from).map(from_item_id),
591                 glob: true,
592             },
593         }
594     }
595 }
596
597 impl FromWithTcx<clean::ProcMacro> for ProcMacro {
598     fn from_tcx(mac: clean::ProcMacro, _tcx: TyCtxt<'_>) -> Self {
599         ProcMacro {
600             kind: from_macro_kind(mac.kind),
601             helpers: mac.helpers.iter().map(|x| x.to_string()).collect(),
602         }
603     }
604 }
605
606 crate fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind {
607     use rustc_span::hygiene::MacroKind::*;
608     match kind {
609         Bang => MacroKind::Bang,
610         Attr => MacroKind::Attr,
611         Derive => MacroKind::Derive,
612     }
613 }
614
615 impl FromWithTcx<clean::Typedef> for Typedef {
616     fn from_tcx(typedef: clean::Typedef, tcx: TyCtxt<'_>) -> Self {
617         let clean::Typedef { type_, generics, item_type: _ } = typedef;
618         Typedef { type_: type_.into_tcx(tcx), generics: generics.into_tcx(tcx) }
619     }
620 }
621
622 impl FromWithTcx<clean::OpaqueTy> for OpaqueTy {
623     fn from_tcx(opaque: clean::OpaqueTy, tcx: TyCtxt<'_>) -> Self {
624         OpaqueTy {
625             bounds: opaque.bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
626             generics: opaque.generics.into_tcx(tcx),
627         }
628     }
629 }
630
631 impl FromWithTcx<clean::Static> for Static {
632     fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self {
633         Static {
634             type_: stat.type_.into_tcx(tcx),
635             mutable: stat.mutability == ast::Mutability::Mut,
636             expr: stat.expr.map(|e| print_const_expr(tcx, e)).unwrap_or_default(),
637         }
638     }
639 }
640
641 impl FromWithTcx<clean::TraitAlias> for TraitAlias {
642     fn from_tcx(alias: clean::TraitAlias, tcx: TyCtxt<'_>) -> Self {
643         TraitAlias {
644             generics: alias.generics.into_tcx(tcx),
645             params: alias.bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
646         }
647     }
648 }
649
650 impl FromWithTcx<ItemType> for ItemKind {
651     fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self {
652         use ItemType::*;
653         match kind {
654             Module => ItemKind::Module,
655             ExternCrate => ItemKind::ExternCrate,
656             Import => ItemKind::Import,
657             Struct => ItemKind::Struct,
658             Union => ItemKind::Union,
659             Enum => ItemKind::Enum,
660             Function => ItemKind::Function,
661             Typedef => ItemKind::Typedef,
662             OpaqueTy => ItemKind::OpaqueTy,
663             Static => ItemKind::Static,
664             Constant => ItemKind::Constant,
665             Trait => ItemKind::Trait,
666             Impl => ItemKind::Impl,
667             TyMethod | Method => ItemKind::Method,
668             StructField => ItemKind::StructField,
669             Variant => ItemKind::Variant,
670             Macro => ItemKind::Macro,
671             Primitive => ItemKind::Primitive,
672             AssocConst => ItemKind::AssocConst,
673             AssocType => ItemKind::AssocType,
674             ForeignType => ItemKind::ForeignType,
675             Keyword => ItemKind::Keyword,
676             TraitAlias => ItemKind::TraitAlias,
677             ProcAttribute => ItemKind::ProcAttribute,
678             ProcDerive => ItemKind::ProcDerive,
679         }
680     }
681 }
682
683 fn ids(items: impl IntoIterator<Item = clean::Item>) -> Vec<Id> {
684     items.into_iter().filter(|x| !x.is_stripped()).map(|i| from_item_id(i.def_id)).collect()
685 }