]> git.proxmox.com Git - rustc.git/blob - src/librustdoc/json/conversions.rs
New upstream version 1.63.0+dfsg1
[rustc.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::{self, TyCtxt};
13 use rustc_span::{Pos, Symbol};
14 use rustc_target::spec::abi::Abi as RustcAbi;
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
23 impl JsonRenderer<'_> {
24 pub(super) fn convert_item(&self, item: clean::Item) -> Option<Item> {
25 let deprecation = item.deprecation(self.tcx);
26 let links = self
27 .cache
28 .intra_doc_links
29 .get(&item.item_id)
30 .into_iter()
31 .flatten()
32 .map(|clean::ItemLink { link, did, .. }| {
33 (link.clone(), from_item_id((*did).into(), self.tcx))
34 })
35 .collect();
36 let docs = item.attrs.collapsed_doc_value();
37 let attrs = item
38 .attrs
39 .other_attrs
40 .iter()
41 .map(rustc_ast_pretty::pprust::attribute_to_string)
42 .collect();
43 let span = item.span(self.tcx);
44 let clean::Item { name, attrs: _, kind: _, visibility, item_id, cfg: _ } = item;
45 let inner = match *item.kind {
46 clean::StrippedItem(_) | clean::KeywordItem(_) => return None,
47 _ => from_clean_item(item, self.tcx),
48 };
49 Some(Item {
50 id: from_item_id_with_name(item_id, self.tcx, name),
51 crate_id: item_id.krate().as_u32(),
52 name: name.map(|sym| sym.to_string()),
53 span: self.convert_span(span),
54 visibility: self.convert_visibility(visibility),
55 docs,
56 attrs,
57 deprecation: deprecation.map(from_deprecation),
58 inner,
59 links,
60 })
61 }
62
63 fn convert_span(&self, span: clean::Span) -> Option<Span> {
64 match span.filename(self.sess()) {
65 rustc_span::FileName::Real(name) => {
66 if let Some(local_path) = name.into_local_path() {
67 let hi = span.hi(self.sess());
68 let lo = span.lo(self.sess());
69 Some(Span {
70 filename: local_path,
71 begin: (lo.line, lo.col.to_usize()),
72 end: (hi.line, hi.col.to_usize()),
73 })
74 } else {
75 None
76 }
77 }
78 _ => None,
79 }
80 }
81
82 fn convert_visibility(&self, v: clean::Visibility) -> Visibility {
83 use clean::Visibility::*;
84 match v {
85 Public => Visibility::Public,
86 Inherited => Visibility::Default,
87 Restricted(did) if did.is_crate_root() => Visibility::Crate,
88 Restricted(did) => Visibility::Restricted {
89 parent: from_item_id(did.into(), self.tcx),
90 path: self.tcx.def_path(did).to_string_no_crate_verbose(),
91 },
92 }
93 }
94 }
95
96 pub(crate) trait FromWithTcx<T> {
97 fn from_tcx(f: T, tcx: TyCtxt<'_>) -> Self;
98 }
99
100 pub(crate) trait IntoWithTcx<T> {
101 fn into_tcx(self, tcx: TyCtxt<'_>) -> T;
102 }
103
104 impl<T, U> IntoWithTcx<U> for T
105 where
106 U: FromWithTcx<T>,
107 {
108 fn into_tcx(self, tcx: TyCtxt<'_>) -> U {
109 U::from_tcx(self, tcx)
110 }
111 }
112
113 pub(crate) fn from_deprecation(deprecation: rustc_attr::Deprecation) -> Deprecation {
114 #[rustfmt::skip]
115 let rustc_attr::Deprecation { since, note, is_since_rustc_version: _, suggestion: _ } = deprecation;
116 Deprecation { since: since.map(|s| s.to_string()), note: note.map(|s| s.to_string()) }
117 }
118
119 impl FromWithTcx<clean::GenericArgs> for GenericArgs {
120 fn from_tcx(args: clean::GenericArgs, tcx: TyCtxt<'_>) -> Self {
121 use clean::GenericArgs::*;
122 match args {
123 AngleBracketed { args, bindings } => GenericArgs::AngleBracketed {
124 args: args.into_vec().into_iter().map(|a| a.into_tcx(tcx)).collect(),
125 bindings: bindings.into_iter().map(|a| a.into_tcx(tcx)).collect(),
126 },
127 Parenthesized { inputs, output } => GenericArgs::Parenthesized {
128 inputs: inputs.into_vec().into_iter().map(|a| a.into_tcx(tcx)).collect(),
129 output: output.map(|a| (*a).into_tcx(tcx)),
130 },
131 }
132 }
133 }
134
135 impl FromWithTcx<clean::GenericArg> for GenericArg {
136 fn from_tcx(arg: clean::GenericArg, tcx: TyCtxt<'_>) -> Self {
137 use clean::GenericArg::*;
138 match arg {
139 Lifetime(l) => GenericArg::Lifetime(l.0.to_string()),
140 Type(t) => GenericArg::Type(t.into_tcx(tcx)),
141 Const(box c) => GenericArg::Const(c.into_tcx(tcx)),
142 Infer => GenericArg::Infer,
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 {
159 name: binding.assoc.name.to_string(),
160 args: binding.assoc.args.into_tcx(tcx),
161 binding: binding.kind.into_tcx(tcx),
162 }
163 }
164 }
165
166 impl FromWithTcx<clean::TypeBindingKind> for TypeBindingKind {
167 fn from_tcx(kind: clean::TypeBindingKind, tcx: TyCtxt<'_>) -> Self {
168 use clean::TypeBindingKind::*;
169 match kind {
170 Equality { term } => TypeBindingKind::Equality(term.into_tcx(tcx)),
171 Constraint { bounds } => {
172 TypeBindingKind::Constraint(bounds.into_iter().map(|a| a.into_tcx(tcx)).collect())
173 }
174 }
175 }
176 }
177
178 /// It generates an ID as follows:
179 ///
180 /// `CRATE_ID:ITEM_ID[:NAME_ID]` (if there is no name, NAME_ID is not generated).
181 pub(crate) fn from_item_id(item_id: ItemId, tcx: TyCtxt<'_>) -> Id {
182 from_item_id_with_name(item_id, tcx, None)
183 }
184
185 // FIXME: this function (and appending the name at the end of the ID) should be removed when
186 // reexports are not inlined anymore for json format. It should be done in #93518.
187 pub(crate) fn from_item_id_with_name(item_id: ItemId, tcx: TyCtxt<'_>, name: Option<Symbol>) -> Id {
188 struct DisplayDefId<'a>(DefId, TyCtxt<'a>, Option<Symbol>);
189
190 impl<'a> fmt::Display for DisplayDefId<'a> {
191 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
192 let name = match self.2 {
193 Some(name) => format!(":{}", name.as_u32()),
194 None => self
195 .1
196 .opt_item_name(self.0)
197 .map(|n| format!(":{}", n.as_u32()))
198 .unwrap_or_default(),
199 };
200 write!(f, "{}:{}{}", self.0.krate.as_u32(), u32::from(self.0.index), name)
201 }
202 }
203
204 match item_id {
205 ItemId::DefId(did) => Id(format!("{}", DisplayDefId(did, tcx, name))),
206 ItemId::Blanket { for_, impl_id } => {
207 Id(format!("b:{}-{}", DisplayDefId(impl_id, tcx, None), DisplayDefId(for_, tcx, name)))
208 }
209 ItemId::Auto { for_, trait_ } => {
210 Id(format!("a:{}-{}", DisplayDefId(trait_, tcx, None), DisplayDefId(for_, tcx, name)))
211 }
212 ItemId::Primitive(ty, krate) => Id(format!("p:{}:{}", krate.as_u32(), ty.as_sym())),
213 }
214 }
215
216 fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
217 use clean::ItemKind::*;
218 let name = item.name;
219 let is_crate = item.is_crate();
220 let header = item.fn_header(tcx);
221
222 match *item.kind {
223 ModuleItem(m) => ItemEnum::Module(Module { is_crate, items: ids(m.items, tcx) }),
224 ImportItem(i) => ItemEnum::Import(i.into_tcx(tcx)),
225 StructItem(s) => ItemEnum::Struct(s.into_tcx(tcx)),
226 UnionItem(u) => ItemEnum::Union(u.into_tcx(tcx)),
227 StructFieldItem(f) => ItemEnum::StructField(f.into_tcx(tcx)),
228 EnumItem(e) => ItemEnum::Enum(e.into_tcx(tcx)),
229 VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)),
230 FunctionItem(f) => ItemEnum::Function(from_function(f, header.unwrap(), tcx)),
231 ForeignFunctionItem(f) => ItemEnum::Function(from_function(f, header.unwrap(), tcx)),
232 TraitItem(t) => ItemEnum::Trait(t.into_tcx(tcx)),
233 TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)),
234 MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, header.unwrap(), tcx)),
235 TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, header.unwrap(), tcx)),
236 ImplItem(i) => ItemEnum::Impl(i.into_tcx(tcx)),
237 StaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
238 ForeignStaticItem(s) => ItemEnum::Static(s.into_tcx(tcx)),
239 ForeignTypeItem => ItemEnum::ForeignType,
240 TypedefItem(t) => ItemEnum::Typedef(t.into_tcx(tcx)),
241 OpaqueTyItem(t) => ItemEnum::OpaqueTy(t.into_tcx(tcx)),
242 ConstantItem(c) => ItemEnum::Constant(c.into_tcx(tcx)),
243 MacroItem(m) => ItemEnum::Macro(m.source),
244 ProcMacroItem(m) => ItemEnum::ProcMacro(m.into_tcx(tcx)),
245 PrimitiveItem(p) => ItemEnum::PrimitiveType(p.as_sym().to_string()),
246 TyAssocConstItem(ty) => ItemEnum::AssocConst { type_: ty.into_tcx(tcx), default: None },
247 AssocConstItem(ty, default) => {
248 ItemEnum::AssocConst { type_: ty.into_tcx(tcx), default: Some(default.expr(tcx)) }
249 }
250 TyAssocTypeItem(g, b) => ItemEnum::AssocType {
251 generics: (*g).into_tcx(tcx),
252 bounds: b.into_iter().map(|x| x.into_tcx(tcx)).collect(),
253 default: None,
254 },
255 // FIXME: do not map to Typedef but to a custom variant
256 AssocTypeItem(t, _) => ItemEnum::Typedef(t.into_tcx(tcx)),
257 // `convert_item` early returns `None` for striped items and keywords.
258 StrippedItem(_) | KeywordItem(_) => unreachable!(),
259 ExternCrateItem { ref src } => ItemEnum::ExternCrate {
260 name: name.as_ref().unwrap().to_string(),
261 rename: src.map(|x| x.to_string()),
262 },
263 }
264 }
265
266 impl FromWithTcx<clean::Struct> for Struct {
267 fn from_tcx(struct_: clean::Struct, tcx: TyCtxt<'_>) -> Self {
268 let fields_stripped = struct_.has_stripped_entries();
269 let clean::Struct { struct_type, generics, fields } = struct_;
270 Struct {
271 struct_type: from_ctor_kind(struct_type),
272 generics: generics.into_tcx(tcx),
273 fields_stripped,
274 fields: ids(fields, tcx),
275 impls: Vec::new(), // Added in JsonRenderer::item
276 }
277 }
278 }
279
280 impl FromWithTcx<clean::Union> for Union {
281 fn from_tcx(union_: clean::Union, tcx: TyCtxt<'_>) -> Self {
282 let fields_stripped = union_.has_stripped_entries();
283 let clean::Union { generics, fields } = union_;
284 Union {
285 generics: generics.into_tcx(tcx),
286 fields_stripped,
287 fields: ids(fields, tcx),
288 impls: Vec::new(), // Added in JsonRenderer::item
289 }
290 }
291 }
292
293 pub(crate) fn from_ctor_kind(struct_type: CtorKind) -> StructType {
294 match struct_type {
295 CtorKind::Fictive => StructType::Plain,
296 CtorKind::Fn => StructType::Tuple,
297 CtorKind::Const => StructType::Unit,
298 }
299 }
300
301 pub(crate) fn from_fn_header(header: &rustc_hir::FnHeader) -> Header {
302 Header {
303 async_: header.is_async(),
304 const_: header.is_const(),
305 unsafe_: header.is_unsafe(),
306 abi: convert_abi(header.abi),
307 }
308 }
309
310 fn convert_abi(a: RustcAbi) -> Abi {
311 match a {
312 RustcAbi::Rust => Abi::Rust,
313 RustcAbi::C { unwind } => Abi::C { unwind },
314 RustcAbi::Cdecl { unwind } => Abi::Cdecl { unwind },
315 RustcAbi::Stdcall { unwind } => Abi::Stdcall { unwind },
316 RustcAbi::Fastcall { unwind } => Abi::Fastcall { unwind },
317 RustcAbi::Aapcs { unwind } => Abi::Aapcs { unwind },
318 RustcAbi::Win64 { unwind } => Abi::Win64 { unwind },
319 RustcAbi::SysV64 { unwind } => Abi::SysV64 { unwind },
320 RustcAbi::System { unwind } => Abi::System { unwind },
321 _ => Abi::Other(a.to_string()),
322 }
323 }
324
325 impl FromWithTcx<clean::Generics> for Generics {
326 fn from_tcx(generics: clean::Generics, tcx: TyCtxt<'_>) -> Self {
327 Generics {
328 params: generics.params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
329 where_predicates: generics
330 .where_predicates
331 .into_iter()
332 .map(|x| x.into_tcx(tcx))
333 .collect(),
334 }
335 }
336 }
337
338 impl FromWithTcx<clean::GenericParamDef> for GenericParamDef {
339 fn from_tcx(generic_param: clean::GenericParamDef, tcx: TyCtxt<'_>) -> Self {
340 GenericParamDef {
341 name: generic_param.name.to_string(),
342 kind: generic_param.kind.into_tcx(tcx),
343 }
344 }
345 }
346
347 impl FromWithTcx<clean::GenericParamDefKind> for GenericParamDefKind {
348 fn from_tcx(kind: clean::GenericParamDefKind, tcx: TyCtxt<'_>) -> Self {
349 use clean::GenericParamDefKind::*;
350 match kind {
351 Lifetime { outlives } => GenericParamDefKind::Lifetime {
352 outlives: outlives.into_iter().map(|lt| lt.0.to_string()).collect(),
353 },
354 Type { did: _, bounds, default, synthetic } => GenericParamDefKind::Type {
355 bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
356 default: default.map(|x| (*x).into_tcx(tcx)),
357 synthetic,
358 },
359 Const { did: _, ty, default } => GenericParamDefKind::Const {
360 type_: (*ty).into_tcx(tcx),
361 default: default.map(|x| *x),
362 },
363 }
364 }
365 }
366
367 impl FromWithTcx<clean::WherePredicate> for WherePredicate {
368 fn from_tcx(predicate: clean::WherePredicate, tcx: TyCtxt<'_>) -> Self {
369 use clean::WherePredicate::*;
370 match predicate {
371 BoundPredicate { ty, bounds, bound_params } => WherePredicate::BoundPredicate {
372 type_: ty.into_tcx(tcx),
373 bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
374 generic_params: bound_params
375 .into_iter()
376 .map(|x| GenericParamDef {
377 name: x.0.to_string(),
378 kind: GenericParamDefKind::Lifetime { outlives: vec![] },
379 })
380 .collect(),
381 },
382 RegionPredicate { lifetime, bounds } => WherePredicate::RegionPredicate {
383 lifetime: lifetime.0.to_string(),
384 bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
385 },
386 EqPredicate { lhs, rhs } => {
387 WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) }
388 }
389 }
390 }
391 }
392
393 impl FromWithTcx<clean::GenericBound> for GenericBound {
394 fn from_tcx(bound: clean::GenericBound, tcx: TyCtxt<'_>) -> Self {
395 use clean::GenericBound::*;
396 match bound {
397 TraitBound(clean::PolyTrait { trait_, generic_params }, modifier) => {
398 // FIXME: should `trait_` be a clean::Path equivalent in JSON?
399 let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
400 GenericBound::TraitBound {
401 trait_,
402 generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
403 modifier: from_trait_bound_modifier(modifier),
404 }
405 }
406 Outlives(lifetime) => GenericBound::Outlives(lifetime.0.to_string()),
407 }
408 }
409 }
410
411 pub(crate) fn from_trait_bound_modifier(
412 modifier: rustc_hir::TraitBoundModifier,
413 ) -> TraitBoundModifier {
414 use rustc_hir::TraitBoundModifier::*;
415 match modifier {
416 None => TraitBoundModifier::None,
417 Maybe => TraitBoundModifier::Maybe,
418 MaybeConst => TraitBoundModifier::MaybeConst,
419 }
420 }
421
422 impl FromWithTcx<clean::Type> for Type {
423 fn from_tcx(ty: clean::Type, tcx: TyCtxt<'_>) -> Self {
424 use clean::Type::{
425 Array, BareFunction, BorrowedRef, DynTrait, Generic, ImplTrait, Infer, Primitive,
426 QPath, RawPointer, Slice, Tuple,
427 };
428
429 match ty {
430 clean::Type::Path { path } => Type::ResolvedPath {
431 name: path.whole_name(),
432 id: from_item_id(path.def_id().into(), tcx),
433 args: path.segments.last().map(|args| Box::new(args.clone().args.into_tcx(tcx))),
434 param_names: Vec::new(),
435 },
436 DynTrait(mut bounds, lt) => {
437 let first_trait = bounds.remove(0).trait_;
438
439 Type::ResolvedPath {
440 name: first_trait.whole_name(),
441 id: from_item_id(first_trait.def_id().into(), tcx),
442 args: first_trait
443 .segments
444 .last()
445 .map(|args| Box::new(args.clone().args.into_tcx(tcx))),
446 param_names: bounds
447 .into_iter()
448 .map(|t| {
449 clean::GenericBound::TraitBound(t, rustc_hir::TraitBoundModifier::None)
450 })
451 .chain(lt.map(clean::GenericBound::Outlives))
452 .map(|bound| bound.into_tcx(tcx))
453 .collect(),
454 }
455 }
456 Generic(s) => Type::Generic(s.to_string()),
457 Primitive(p) => Type::Primitive(p.as_sym().to_string()),
458 BareFunction(f) => Type::FunctionPointer(Box::new((*f).into_tcx(tcx))),
459 Tuple(t) => Type::Tuple(t.into_iter().map(|x| x.into_tcx(tcx)).collect()),
460 Slice(t) => Type::Slice(Box::new((*t).into_tcx(tcx))),
461 Array(t, s) => Type::Array { type_: Box::new((*t).into_tcx(tcx)), len: s },
462 ImplTrait(g) => Type::ImplTrait(g.into_iter().map(|x| x.into_tcx(tcx)).collect()),
463 Infer => Type::Infer,
464 RawPointer(mutability, type_) => Type::RawPointer {
465 mutable: mutability == ast::Mutability::Mut,
466 type_: Box::new((*type_).into_tcx(tcx)),
467 },
468 BorrowedRef { lifetime, mutability, type_ } => Type::BorrowedRef {
469 lifetime: lifetime.map(|l| l.0.to_string()),
470 mutable: mutability == ast::Mutability::Mut,
471 type_: Box::new((*type_).into_tcx(tcx)),
472 },
473 QPath { assoc, self_type, trait_, .. } => {
474 // FIXME: should `trait_` be a clean::Path equivalent in JSON?
475 let trait_ = clean::Type::Path { path: trait_ }.into_tcx(tcx);
476 Type::QualifiedPath {
477 name: assoc.name.to_string(),
478 args: Box::new(assoc.args.clone().into_tcx(tcx)),
479 self_type: Box::new((*self_type).into_tcx(tcx)),
480 trait_: Box::new(trait_),
481 }
482 }
483 }
484 }
485 }
486
487 impl FromWithTcx<clean::Term> for Term {
488 fn from_tcx(term: clean::Term, tcx: TyCtxt<'_>) -> Term {
489 match term {
490 clean::Term::Type(ty) => Term::Type(FromWithTcx::from_tcx(ty, tcx)),
491 clean::Term::Constant(c) => Term::Constant(FromWithTcx::from_tcx(c, tcx)),
492 }
493 }
494 }
495
496 impl FromWithTcx<clean::BareFunctionDecl> for FunctionPointer {
497 fn from_tcx(bare_decl: clean::BareFunctionDecl, tcx: TyCtxt<'_>) -> Self {
498 let clean::BareFunctionDecl { unsafety, generic_params, decl, abi } = bare_decl;
499 FunctionPointer {
500 header: Header {
501 unsafe_: matches!(unsafety, rustc_hir::Unsafety::Unsafe),
502 const_: false,
503 async_: false,
504 abi: convert_abi(abi),
505 },
506 generic_params: generic_params.into_iter().map(|x| x.into_tcx(tcx)).collect(),
507 decl: decl.into_tcx(tcx),
508 }
509 }
510 }
511
512 impl FromWithTcx<clean::FnDecl> for FnDecl {
513 fn from_tcx(decl: clean::FnDecl, tcx: TyCtxt<'_>) -> Self {
514 let clean::FnDecl { inputs, output, c_variadic } = decl;
515 FnDecl {
516 inputs: inputs
517 .values
518 .into_iter()
519 .map(|arg| (arg.name.to_string(), arg.type_.into_tcx(tcx)))
520 .collect(),
521 output: match output {
522 clean::FnRetTy::Return(t) => Some(t.into_tcx(tcx)),
523 clean::FnRetTy::DefaultReturn => None,
524 },
525 c_variadic,
526 }
527 }
528 }
529
530 impl FromWithTcx<clean::Trait> for Trait {
531 fn from_tcx(trait_: clean::Trait, tcx: TyCtxt<'_>) -> Self {
532 let clean::Trait { unsafety, items, generics, bounds, is_auto } = trait_;
533 Trait {
534 is_auto,
535 is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
536 items: ids(items, tcx),
537 generics: generics.into_tcx(tcx),
538 bounds: bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
539 implementations: Vec::new(), // Added in JsonRenderer::item
540 }
541 }
542 }
543
544 impl FromWithTcx<clean::Impl> for Impl {
545 fn from_tcx(impl_: clean::Impl, tcx: TyCtxt<'_>) -> Self {
546 let provided_trait_methods = impl_.provided_trait_methods(tcx);
547 let clean::Impl { unsafety, generics, trait_, for_, items, polarity, kind } = impl_;
548 // FIXME: should `trait_` be a clean::Path equivalent in JSON?
549 let trait_ = trait_.map(|path| clean::Type::Path { path }.into_tcx(tcx));
550 // FIXME: use something like ImplKind in JSON?
551 let (synthetic, blanket_impl) = match kind {
552 clean::ImplKind::Normal | clean::ImplKind::TupleVaradic => (false, None),
553 clean::ImplKind::Auto => (true, None),
554 clean::ImplKind::Blanket(ty) => (false, Some(*ty)),
555 };
556 let negative_polarity = match polarity {
557 ty::ImplPolarity::Positive | ty::ImplPolarity::Reservation => false,
558 ty::ImplPolarity::Negative => true,
559 };
560 Impl {
561 is_unsafe: unsafety == rustc_hir::Unsafety::Unsafe,
562 generics: generics.into_tcx(tcx),
563 provided_trait_methods: provided_trait_methods
564 .into_iter()
565 .map(|x| x.to_string())
566 .collect(),
567 trait_,
568 for_: for_.into_tcx(tcx),
569 items: ids(items, tcx),
570 negative: negative_polarity,
571 synthetic,
572 blanket_impl: blanket_impl.map(|x| x.into_tcx(tcx)),
573 }
574 }
575 }
576
577 pub(crate) fn from_function(
578 function: clean::Function,
579 header: rustc_hir::FnHeader,
580 tcx: TyCtxt<'_>,
581 ) -> Function {
582 let clean::Function { decl, generics } = function;
583 Function {
584 decl: decl.into_tcx(tcx),
585 generics: generics.into_tcx(tcx),
586 header: from_fn_header(&header),
587 }
588 }
589
590 pub(crate) fn from_function_method(
591 function: clean::Function,
592 has_body: bool,
593 header: rustc_hir::FnHeader,
594 tcx: TyCtxt<'_>,
595 ) -> Method {
596 let clean::Function { decl, generics } = function;
597 Method {
598 decl: decl.into_tcx(tcx),
599 generics: generics.into_tcx(tcx),
600 header: from_fn_header(&header),
601 has_body,
602 }
603 }
604
605 impl FromWithTcx<clean::Enum> for Enum {
606 fn from_tcx(enum_: clean::Enum, tcx: TyCtxt<'_>) -> Self {
607 let variants_stripped = enum_.has_stripped_entries();
608 let clean::Enum { variants, generics } = enum_;
609 Enum {
610 generics: generics.into_tcx(tcx),
611 variants_stripped,
612 variants: ids(variants, tcx),
613 impls: Vec::new(), // Added in JsonRenderer::item
614 }
615 }
616 }
617
618 impl FromWithTcx<clean::VariantStruct> for Struct {
619 fn from_tcx(struct_: clean::VariantStruct, tcx: TyCtxt<'_>) -> Self {
620 let fields_stripped = struct_.has_stripped_entries();
621 let clean::VariantStruct { struct_type, fields } = struct_;
622 Struct {
623 struct_type: from_ctor_kind(struct_type),
624 generics: Default::default(),
625 fields_stripped,
626 fields: ids(fields, tcx),
627 impls: Vec::new(),
628 }
629 }
630 }
631
632 impl FromWithTcx<clean::Variant> for Variant {
633 fn from_tcx(variant: clean::Variant, tcx: TyCtxt<'_>) -> Self {
634 use clean::Variant::*;
635 match variant {
636 CLike => Variant::Plain,
637 Tuple(fields) => Variant::Tuple(
638 fields
639 .into_iter()
640 .map(|f| {
641 if let clean::StructFieldItem(ty) = *f.kind {
642 ty.into_tcx(tcx)
643 } else {
644 unreachable!()
645 }
646 })
647 .collect(),
648 ),
649 Struct(s) => Variant::Struct(ids(s.fields, tcx)),
650 }
651 }
652 }
653
654 impl FromWithTcx<clean::Import> for Import {
655 fn from_tcx(import: clean::Import, tcx: TyCtxt<'_>) -> Self {
656 use clean::ImportKind::*;
657 match import.kind {
658 Simple(s) => Import {
659 source: import.source.path.whole_name(),
660 name: s.to_string(),
661 id: import.source.did.map(ItemId::from).map(|i| from_item_id(i, tcx)),
662 glob: false,
663 },
664 Glob => Import {
665 source: import.source.path.whole_name(),
666 name: import.source.path.last().to_string(),
667 id: import.source.did.map(ItemId::from).map(|i| from_item_id(i, tcx)),
668 glob: true,
669 },
670 }
671 }
672 }
673
674 impl FromWithTcx<clean::ProcMacro> for ProcMacro {
675 fn from_tcx(mac: clean::ProcMacro, _tcx: TyCtxt<'_>) -> Self {
676 ProcMacro {
677 kind: from_macro_kind(mac.kind),
678 helpers: mac.helpers.iter().map(|x| x.to_string()).collect(),
679 }
680 }
681 }
682
683 pub(crate) fn from_macro_kind(kind: rustc_span::hygiene::MacroKind) -> MacroKind {
684 use rustc_span::hygiene::MacroKind::*;
685 match kind {
686 Bang => MacroKind::Bang,
687 Attr => MacroKind::Attr,
688 Derive => MacroKind::Derive,
689 }
690 }
691
692 impl FromWithTcx<clean::Typedef> for Typedef {
693 fn from_tcx(typedef: clean::Typedef, tcx: TyCtxt<'_>) -> Self {
694 let clean::Typedef { type_, generics, item_type: _ } = typedef;
695 Typedef { type_: type_.into_tcx(tcx), generics: generics.into_tcx(tcx) }
696 }
697 }
698
699 impl FromWithTcx<clean::OpaqueTy> for OpaqueTy {
700 fn from_tcx(opaque: clean::OpaqueTy, tcx: TyCtxt<'_>) -> Self {
701 OpaqueTy {
702 bounds: opaque.bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
703 generics: opaque.generics.into_tcx(tcx),
704 }
705 }
706 }
707
708 impl FromWithTcx<clean::Static> for Static {
709 fn from_tcx(stat: clean::Static, tcx: TyCtxt<'_>) -> Self {
710 Static {
711 type_: stat.type_.into_tcx(tcx),
712 mutable: stat.mutability == ast::Mutability::Mut,
713 expr: stat.expr.map(|e| print_const_expr(tcx, e)).unwrap_or_default(),
714 }
715 }
716 }
717
718 impl FromWithTcx<clean::TraitAlias> for TraitAlias {
719 fn from_tcx(alias: clean::TraitAlias, tcx: TyCtxt<'_>) -> Self {
720 TraitAlias {
721 generics: alias.generics.into_tcx(tcx),
722 params: alias.bounds.into_iter().map(|x| x.into_tcx(tcx)).collect(),
723 }
724 }
725 }
726
727 impl FromWithTcx<ItemType> for ItemKind {
728 fn from_tcx(kind: ItemType, _tcx: TyCtxt<'_>) -> Self {
729 use ItemType::*;
730 match kind {
731 Module => ItemKind::Module,
732 ExternCrate => ItemKind::ExternCrate,
733 Import => ItemKind::Import,
734 Struct => ItemKind::Struct,
735 Union => ItemKind::Union,
736 Enum => ItemKind::Enum,
737 Function => ItemKind::Function,
738 Typedef => ItemKind::Typedef,
739 OpaqueTy => ItemKind::OpaqueTy,
740 Static => ItemKind::Static,
741 Constant => ItemKind::Constant,
742 Trait => ItemKind::Trait,
743 Impl => ItemKind::Impl,
744 TyMethod | Method => ItemKind::Method,
745 StructField => ItemKind::StructField,
746 Variant => ItemKind::Variant,
747 Macro => ItemKind::Macro,
748 Primitive => ItemKind::Primitive,
749 AssocConst => ItemKind::AssocConst,
750 AssocType => ItemKind::AssocType,
751 ForeignType => ItemKind::ForeignType,
752 Keyword => ItemKind::Keyword,
753 TraitAlias => ItemKind::TraitAlias,
754 ProcAttribute => ItemKind::ProcAttribute,
755 ProcDerive => ItemKind::ProcDerive,
756 Generic => unreachable!(),
757 }
758 }
759 }
760
761 fn ids(items: impl IntoIterator<Item = clean::Item>, tcx: TyCtxt<'_>) -> Vec<Id> {
762 items
763 .into_iter()
764 .filter(|x| !x.is_stripped() && !x.is_keyword())
765 .map(|i| from_item_id_with_name(i.item_id, tcx, i.name))
766 .collect()
767 }