1 // Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! This module contains the "cleaned" pieces of the AST, and the functions
14 pub use self::Type
::*;
15 pub use self::PrimitiveType
::*;
16 pub use self::TypeKind
::*;
17 pub use self::VariantKind
::*;
18 pub use self::Mutability
::*;
19 pub use self::Import
::*;
20 pub use self::ItemEnum
::*;
21 pub use self::Attribute
::*;
22 pub use self::TyParamBound
::*;
23 pub use self::SelfTy
::*;
24 pub use self::FunctionRetTy
::*;
30 use syntax
::attr
::{AttributeMethods, AttrMetaMethods}
;
32 use syntax
::codemap
::{DUMMY_SP, Pos, Spanned}
;
33 use syntax
::parse
::token
::{self, InternedString, special_idents}
;
36 use rustc_trans
::back
::link
;
37 use rustc
::middle
::cstore
::{self, CrateStore}
;
38 use rustc
::hir
::def
::Def
;
39 use rustc
::hir
::def_id
::{DefId, DefIndex}
;
40 use rustc
::ty
::subst
::{self, ParamSpace, VecPerParamSpace}
;
42 use rustc
::middle
::stability
;
46 use std
::collections
::{HashMap, HashSet}
;
47 use std
::path
::PathBuf
;
50 use std
::env
::current_dir
;
55 use html
::item_type
::ItemType
;
60 // extract the stability index for a node from tcx, if possible
61 fn get_stability(cx
: &DocContext
, def_id
: DefId
) -> Option
<Stability
> {
62 cx
.tcx_opt().and_then(|tcx
| stability
::lookup_stability(tcx
, def_id
)).clean(cx
)
65 fn get_deprecation(cx
: &DocContext
, def_id
: DefId
) -> Option
<Deprecation
> {
66 cx
.tcx_opt().and_then(|tcx
| stability
::lookup_deprecation(tcx
, def_id
)).clean(cx
)
70 fn clean(&self, cx
: &DocContext
) -> T
;
73 impl<T
: Clean
<U
>, U
> Clean
<Vec
<U
>> for [T
] {
74 fn clean(&self, cx
: &DocContext
) -> Vec
<U
> {
75 self.iter().map(|x
| x
.clean(cx
)).collect()
79 impl<T
: Clean
<U
>, U
> Clean
<VecPerParamSpace
<U
>> for VecPerParamSpace
<T
> {
80 fn clean(&self, cx
: &DocContext
) -> VecPerParamSpace
<U
> {
81 self.map(|x
| x
.clean(cx
))
85 impl<T
: Clean
<U
>, U
> Clean
<U
> for P
<T
> {
86 fn clean(&self, cx
: &DocContext
) -> U
{
91 impl<T
: Clean
<U
>, U
> Clean
<U
> for Rc
<T
> {
92 fn clean(&self, cx
: &DocContext
) -> U
{
97 impl<T
: Clean
<U
>, U
> Clean
<Option
<U
>> for Option
<T
> {
98 fn clean(&self, cx
: &DocContext
) -> Option
<U
> {
99 self.as_ref().map(|v
| v
.clean(cx
))
103 impl<T
, U
> Clean
<U
> for ty
::Binder
<T
> where T
: Clean
<U
> {
104 fn clean(&self, cx
: &DocContext
) -> U
{
109 impl<T
: Clean
<U
>, U
> Clean
<Vec
<U
>> for P
<[T
]> {
110 fn clean(&self, cx
: &DocContext
) -> Vec
<U
> {
111 self.iter().map(|x
| x
.clean(cx
)).collect()
115 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
119 pub module
: Option
<Item
>,
120 pub externs
: Vec
<(ast
::CrateNum
, ExternalCrate
)>,
121 pub primitives
: Vec
<PrimitiveType
>,
122 pub external_traits
: HashMap
<DefId
, Trait
>,
125 struct CrateNum(ast
::CrateNum
);
127 impl<'a
, 'tcx
> Clean
<Crate
> for visit_ast
::RustdocVisitor
<'a
, 'tcx
> {
128 fn clean(&self, cx
: &DocContext
) -> Crate
{
129 use rustc
::session
::config
::Input
;
131 if let Some(t
) = cx
.tcx_opt() {
132 cx
.deref_trait_did
.set(t
.lang_items
.deref_trait());
135 let mut externs
= Vec
::new();
136 for cnum
in cx
.sess().cstore
.crates() {
137 externs
.push((cnum
, CrateNum(cnum
).clean(cx
)));
139 externs
.sort_by(|&(a
, _
), &(b
, _
)| a
.cmp(&b
));
141 // Figure out the name of this crate
142 let input
= &cx
.input
;
143 let name
= link
::find_crate_name(None
, &self.attrs
, input
);
145 // Clean the crate, translating the entire libsyntax AST to one that is
146 // understood by rustdoc.
147 let mut module
= self.module
.clean(cx
);
149 // Collect all inner modules which are tagged as implementations of
152 // Note that this loop only searches the top-level items of the crate,
153 // and this is intentional. If we were to search the entire crate for an
154 // item tagged with `#[doc(primitive)]` then we would also have to
155 // search the entirety of external modules for items tagged
156 // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
157 // all that metadata unconditionally).
159 // In order to keep the metadata load under control, the
160 // `#[doc(primitive)]` feature is explicitly designed to only allow the
161 // primitive tags to show up as the top level items in a crate.
163 // Also note that this does not attempt to deal with modules tagged
164 // duplicately for the same primitive. This is handled later on when
165 // rendering by delegating everything to a hash map.
166 let mut primitives
= Vec
::new();
168 let m
= match module
.inner
{
169 ModuleItem(ref mut m
) => m
,
172 let mut tmp
= Vec
::new();
173 for child
in &mut m
.items
{
177 let prim
= match PrimitiveType
::find(&child
.attrs
) {
181 primitives
.push(prim
);
183 source
: Span
::empty(),
184 name
: Some(prim
.to_url_str().to_string()),
185 attrs
: child
.attrs
.clone(),
186 visibility
: Some(hir
::Public
),
189 def_id
: DefId
::local(prim
.to_def_index()),
190 inner
: PrimitiveItem(prim
),
196 let src
= match cx
.input
{
197 Input
::File(ref path
) => {
198 if path
.is_absolute() {
201 current_dir().unwrap().join(path
)
204 Input
::Str { ref name, .. }
=> PathBuf
::from(name
.clone()),
208 name
: name
.to_string(),
210 module
: Some(module
),
212 primitives
: primitives
,
213 external_traits
: cx
.external_traits
.borrow_mut().take()
214 .unwrap_or(HashMap
::new()),
219 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
220 pub struct ExternalCrate
{
222 pub attrs
: Vec
<Attribute
>,
223 pub primitives
: Vec
<PrimitiveType
>,
226 impl Clean
<ExternalCrate
> for CrateNum
{
227 fn clean(&self, cx
: &DocContext
) -> ExternalCrate
{
228 let mut primitives
= Vec
::new();
229 cx
.tcx_opt().map(|tcx
| {
230 for item
in tcx
.sess
.cstore
.crate_top_level_items(self.0) {
231 let did
= match item
.def
{
232 cstore
::DlDef(Def
::Mod(did
)) => did
,
235 let attrs
= inline
::load_attrs(cx
, tcx
, did
);
236 PrimitiveType
::find(&attrs
).map(|prim
| primitives
.push(prim
));
240 name
: (&cx
.sess().cstore
.crate_name(self.0)[..]).to_owned(),
241 attrs
: cx
.sess().cstore
.crate_attrs(self.0).clean(cx
),
242 primitives
: primitives
,
247 /// Anything with a source location and set of attributes and, optionally, a
248 /// name. That is, anything that can be documented. This doesn't correspond
249 /// directly to the AST's concept of an item; it's a strict superset.
250 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
254 /// Not everything has a name. E.g., impls
255 pub name
: Option
<String
>,
256 pub attrs
: Vec
<Attribute
>,
258 pub visibility
: Option
<Visibility
>,
260 pub stability
: Option
<Stability
>,
261 pub deprecation
: Option
<Deprecation
>,
265 /// Finds the `doc` attribute as a NameValue and returns the corresponding
267 pub fn doc_value
<'a
>(&'a
self) -> Option
<&'a
str> {
268 self.attrs
.value("doc")
270 pub fn is_crate(&self) -> bool
{
272 StrippedItem(box ModuleItem(Module { is_crate: true, ..}
)) |
273 ModuleItem(Module { is_crate: true, ..}
) => true,
277 pub fn is_mod(&self) -> bool
{
278 ItemType
::from_item(self) == ItemType
::Module
280 pub fn is_trait(&self) -> bool
{
281 ItemType
::from_item(self) == ItemType
::Trait
283 pub fn is_struct(&self) -> bool
{
284 ItemType
::from_item(self) == ItemType
::Struct
286 pub fn is_enum(&self) -> bool
{
287 ItemType
::from_item(self) == ItemType
::Module
289 pub fn is_fn(&self) -> bool
{
290 ItemType
::from_item(self) == ItemType
::Function
292 pub fn is_associated_type(&self) -> bool
{
293 ItemType
::from_item(self) == ItemType
::AssociatedType
295 pub fn is_associated_const(&self) -> bool
{
296 ItemType
::from_item(self) == ItemType
::AssociatedConst
298 pub fn is_method(&self) -> bool
{
299 ItemType
::from_item(self) == ItemType
::Method
301 pub fn is_ty_method(&self) -> bool
{
302 ItemType
::from_item(self) == ItemType
::TyMethod
304 pub fn is_stripped(&self) -> bool
{
305 match self.inner { StrippedItem(..) => true, _ => false }
307 pub fn has_stripped_fields(&self) -> Option
<bool
> {
309 StructItem(ref _struct
) => Some(_struct
.fields_stripped
),
310 VariantItem(Variant { kind: StructVariant(ref vstruct)}
) => {
311 Some(vstruct
.fields_stripped
)
317 pub fn stability_class(&self) -> String
{
318 self.stability
.as_ref().map(|ref s
| {
319 let mut base
= match s
.level
{
320 stability
::Unstable
=> "unstable".to_string(),
321 stability
::Stable
=> String
::new(),
323 if !s
.deprecated_since
.is_empty() {
324 base
.push_str(" deprecated");
327 }).unwrap_or(String
::new())
330 pub fn stable_since(&self) -> Option
<&str> {
331 self.stability
.as_ref().map(|s
| &s
.since
[..])
335 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
337 ExternCrateItem(String
, Option
<String
>),
341 FunctionItem(Function
),
343 TypedefItem(Typedef
, bool
/* is associated type */),
345 ConstantItem(Constant
),
348 /// A method signature only. Used for required methods in traits (ie,
349 /// non-default-methods).
350 TyMethodItem(TyMethod
),
351 /// A method with a body.
353 StructFieldItem(Type
),
354 VariantItem(Variant
),
355 /// `fn`s from an extern block
356 ForeignFunctionItem(Function
),
357 /// `static`s from an extern block
358 ForeignStaticItem(Static
),
360 PrimitiveItem(PrimitiveType
),
361 AssociatedConstItem(Type
, Option
<String
>),
362 AssociatedTypeItem(Vec
<TyParamBound
>, Option
<Type
>),
363 DefaultImplItem(DefaultImpl
),
364 /// An item that has been stripped by a rustdoc pass
365 StrippedItem(Box
<ItemEnum
>),
368 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
370 pub items
: Vec
<Item
>,
374 impl Clean
<Item
> for doctree
::Module
{
375 fn clean(&self, cx
: &DocContext
) -> Item
{
376 let name
= if self.name
.is_some() {
377 self.name
.unwrap().clean(cx
)
382 let mut items
: Vec
<Item
> = vec
![];
383 items
.extend(self.extern_crates
.iter().map(|x
| x
.clean(cx
)));
384 items
.extend(self.imports
.iter().flat_map(|x
| x
.clean(cx
)));
385 items
.extend(self.structs
.iter().map(|x
| x
.clean(cx
)));
386 items
.extend(self.enums
.iter().map(|x
| x
.clean(cx
)));
387 items
.extend(self.fns
.iter().map(|x
| x
.clean(cx
)));
388 items
.extend(self.foreigns
.iter().flat_map(|x
| x
.clean(cx
)));
389 items
.extend(self.mods
.iter().map(|x
| x
.clean(cx
)));
390 items
.extend(self.typedefs
.iter().map(|x
| x
.clean(cx
)));
391 items
.extend(self.statics
.iter().map(|x
| x
.clean(cx
)));
392 items
.extend(self.constants
.iter().map(|x
| x
.clean(cx
)));
393 items
.extend(self.traits
.iter().map(|x
| x
.clean(cx
)));
394 items
.extend(self.impls
.iter().flat_map(|x
| x
.clean(cx
)));
395 items
.extend(self.macros
.iter().map(|x
| x
.clean(cx
)));
396 items
.extend(self.def_traits
.iter().map(|x
| x
.clean(cx
)));
398 // determine if we should display the inner contents or
399 // the outer `mod` item for the source code.
401 let cm
= cx
.sess().codemap();
402 let outer
= cm
.lookup_char_pos(self.where_outer
.lo
);
403 let inner
= cm
.lookup_char_pos(self.where_inner
.lo
);
404 if outer
.file
.start_pos
== inner
.file
.start_pos
{
408 // mod foo; (and a separate FileMap for the contents)
415 attrs
: self.attrs
.clean(cx
),
416 source
: whence
.clean(cx
),
417 visibility
: self.vis
.clean(cx
),
418 stability
: self.stab
.clean(cx
),
419 deprecation
: self.depr
.clean(cx
),
420 def_id
: cx
.map
.local_def_id(self.id
),
421 inner
: ModuleItem(Module
{
422 is_crate
: self.is_crate
,
429 pub trait Attributes
{
430 fn has_word(&self, &str) -> bool
;
431 fn value
<'a
>(&'a
self, &str) -> Option
<&'a
str>;
432 fn list
<'a
>(&'a
self, &str) -> &'a
[Attribute
];
435 impl Attributes
for [Attribute
] {
436 /// Returns whether the attribute list contains a specific `Word`
437 fn has_word(&self, word
: &str) -> bool
{
439 if let Word(ref w
) = *attr
{
448 /// Finds an attribute as NameValue and returns the corresponding value found.
449 fn value
<'a
>(&'a
self, name
: &str) -> Option
<&'a
str> {
451 if let NameValue(ref x
, ref v
) = *attr
{
460 /// Finds an attribute as List and returns the list of attributes nested inside.
461 fn list
<'a
>(&'a
self, name
: &str) -> &'a
[Attribute
] {
463 if let List(ref x
, ref list
) = *attr
{
473 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
476 List(String
, Vec
<Attribute
>),
477 NameValue(String
, String
)
480 impl Clean
<Attribute
> for ast
::MetaItem
{
481 fn clean(&self, cx
: &DocContext
) -> Attribute
{
483 ast
::MetaItemKind
::Word(ref s
) => Word(s
.to_string()),
484 ast
::MetaItemKind
::List(ref s
, ref l
) => {
485 List(s
.to_string(), l
.clean(cx
))
487 ast
::MetaItemKind
::NameValue(ref s
, ref v
) => {
488 NameValue(s
.to_string(), lit_to_string(v
))
494 impl Clean
<Attribute
> for ast
::Attribute
{
495 fn clean(&self, cx
: &DocContext
) -> Attribute
{
496 self.with_desugared_doc(|a
| a
.node
.value
.clean(cx
))
500 // This is a rough approximation that gets us what we want.
501 impl attr
::AttrMetaMethods
for Attribute
{
502 fn name(&self) -> InternedString
{
504 Word(ref n
) | List(ref n
, _
) | NameValue(ref n
, _
) => {
505 token
::intern_and_get_ident(n
)
510 fn value_str(&self) -> Option
<InternedString
> {
512 NameValue(_
, ref v
) => {
513 Some(token
::intern_and_get_ident(v
))
518 fn meta_item_list
<'a
>(&'a
self) -> Option
<&'a
[P
<ast
::MetaItem
>]> { None }
519 fn span(&self) -> codemap
::Span { unimplemented!() }
522 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
526 pub bounds
: Vec
<TyParamBound
>,
527 pub default: Option
<Type
>,
530 impl Clean
<TyParam
> for hir
::TyParam
{
531 fn clean(&self, cx
: &DocContext
) -> TyParam
{
533 name
: self.name
.clean(cx
),
534 did
: cx
.map
.local_def_id(self.id
),
535 bounds
: self.bounds
.clean(cx
),
536 default: self.default.clean(cx
),
541 impl<'tcx
> Clean
<TyParam
> for ty
::TypeParameterDef
<'tcx
> {
542 fn clean(&self, cx
: &DocContext
) -> TyParam
{
543 cx
.external_typarams
.borrow_mut().as_mut().unwrap()
544 .insert(self.def_id
, self.name
.clean(cx
));
546 name
: self.name
.clean(cx
),
548 bounds
: vec
![], // these are filled in from the where-clauses
549 default: self.default.clean(cx
),
554 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
555 pub enum TyParamBound
{
556 RegionBound(Lifetime
),
557 TraitBound(PolyTrait
, hir
::TraitBoundModifier
)
561 fn maybe_sized(cx
: &DocContext
) -> TyParamBound
{
562 use rustc
::hir
::TraitBoundModifier
as TBM
;
563 let mut sized_bound
= ty
::BoundSized
.clean(cx
);
564 if let TyParamBound
::TraitBound(_
, ref mut tbm
) = sized_bound
{
570 fn is_sized_bound(&self, cx
: &DocContext
) -> bool
{
571 use rustc
::hir
::TraitBoundModifier
as TBM
;
572 if let Some(tcx
) = cx
.tcx_opt() {
573 if let TyParamBound
::TraitBound(PolyTrait { ref trait_, .. }
, TBM
::None
) = *self {
574 if trait_
.def_id() == tcx
.lang_items
.sized_trait() {
583 impl Clean
<TyParamBound
> for hir
::TyParamBound
{
584 fn clean(&self, cx
: &DocContext
) -> TyParamBound
{
586 hir
::RegionTyParamBound(lt
) => RegionBound(lt
.clean(cx
)),
587 hir
::TraitTyParamBound(ref t
, modifier
) => TraitBound(t
.clean(cx
), modifier
),
592 impl<'tcx
> Clean
<(Vec
<TyParamBound
>, Vec
<TypeBinding
>)> for ty
::ExistentialBounds
<'tcx
> {
593 fn clean(&self, cx
: &DocContext
) -> (Vec
<TyParamBound
>, Vec
<TypeBinding
>) {
594 let mut tp_bounds
= vec
![];
595 self.region_bound
.clean(cx
).map(|b
| tp_bounds
.push(RegionBound(b
)));
596 for bb
in &self.builtin_bounds
{
597 tp_bounds
.push(bb
.clean(cx
));
600 let mut bindings
= vec
![];
601 for &ty
::Binder(ref pb
) in &self.projection_bounds
{
602 bindings
.push(TypeBinding
{
603 name
: pb
.projection_ty
.item_name
.clean(cx
),
608 (tp_bounds
, bindings
)
612 fn external_path_params(cx
: &DocContext
, trait_did
: Option
<DefId
>,
613 bindings
: Vec
<TypeBinding
>, substs
: &subst
::Substs
) -> PathParameters
{
614 let lifetimes
= substs
.regions
.get_slice(subst
::TypeSpace
)
616 .filter_map(|v
| v
.clean(cx
))
618 let types
= substs
.types
.get_slice(subst
::TypeSpace
).to_vec();
620 match (trait_did
, cx
.tcx_opt()) {
621 // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
622 (Some(did
), Some(ref tcx
)) if tcx
.lang_items
.fn_trait_kind(did
).is_some() => {
623 assert_eq
!(types
.len(), 1);
624 let inputs
= match types
[0].sty
{
625 ty
::TyTuple(ref tys
) => tys
.iter().map(|t
| t
.clean(cx
)).collect(),
627 return PathParameters
::AngleBracketed
{
628 lifetimes
: lifetimes
,
629 types
: types
.clean(cx
),
635 // FIXME(#20299) return type comes from a projection now
636 // match types[1].sty {
637 // ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
638 // _ => Some(types[1].clean(cx))
640 PathParameters
::Parenthesized
{
646 PathParameters
::AngleBracketed
{
647 lifetimes
: lifetimes
,
648 types
: types
.clean(cx
),
655 // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
656 // from Fn<(A, B,), C> to Fn(A, B) -> C
657 fn external_path(cx
: &DocContext
, name
: &str, trait_did
: Option
<DefId
>,
658 bindings
: Vec
<TypeBinding
>, substs
: &subst
::Substs
) -> Path
{
661 segments
: vec
![PathSegment
{
662 name
: name
.to_string(),
663 params
: external_path_params(cx
, trait_did
, bindings
, substs
)
668 impl Clean
<TyParamBound
> for ty
::BuiltinBound
{
669 fn clean(&self, cx
: &DocContext
) -> TyParamBound
{
670 let tcx
= match cx
.tcx_opt() {
672 None
=> return RegionBound(Lifetime
::statik())
674 let empty
= subst
::Substs
::empty();
675 let (did
, path
) = match *self {
677 (tcx
.lang_items
.send_trait().unwrap(),
678 external_path(cx
, "Send", None
, vec
![], &empty
)),
680 (tcx
.lang_items
.sized_trait().unwrap(),
681 external_path(cx
, "Sized", None
, vec
![], &empty
)),
683 (tcx
.lang_items
.copy_trait().unwrap(),
684 external_path(cx
, "Copy", None
, vec
![], &empty
)),
686 (tcx
.lang_items
.sync_trait().unwrap(),
687 external_path(cx
, "Sync", None
, vec
![], &empty
)),
689 inline
::record_extern_fqn(cx
, did
, TypeTrait
);
690 TraitBound(PolyTrait
{
691 trait_
: ResolvedPath
{
698 }, hir
::TraitBoundModifier
::None
)
702 impl<'tcx
> Clean
<TyParamBound
> for ty
::TraitRef
<'tcx
> {
703 fn clean(&self, cx
: &DocContext
) -> TyParamBound
{
704 let tcx
= match cx
.tcx_opt() {
706 None
=> return RegionBound(Lifetime
::statik())
708 inline
::record_extern_fqn(cx
, self.def_id
, TypeTrait
);
709 let path
= external_path(cx
, &tcx
.item_name(self.def_id
).as_str(),
710 Some(self.def_id
), vec
![], self.substs
);
712 debug
!("ty::TraitRef\n substs.types(TypeSpace): {:?}\n",
713 self.substs
.types
.get_slice(ParamSpace
::TypeSpace
));
715 // collect any late bound regions
716 let mut late_bounds
= vec
![];
717 for &ty_s
in self.substs
.types
.get_slice(ParamSpace
::TypeSpace
) {
718 if let ty
::TyTuple(ref ts
) = ty_s
.sty
{
720 if let ty
::TyRef(ref reg
, _
) = ty_s
.sty
{
721 if let &ty
::Region
::ReLateBound(_
, _
) = *reg
{
722 debug
!(" hit an ReLateBound {:?}", reg
);
723 if let Some(lt
) = reg
.clean(cx
) {
724 late_bounds
.push(lt
);
734 trait_
: ResolvedPath
{
740 lifetimes
: late_bounds
,
742 hir
::TraitBoundModifier
::None
747 impl<'tcx
> Clean
<Option
<Vec
<TyParamBound
>>> for subst
::Substs
<'tcx
> {
748 fn clean(&self, cx
: &DocContext
) -> Option
<Vec
<TyParamBound
>> {
749 let mut v
= Vec
::new();
750 v
.extend(self.regions
.iter().filter_map(|r
| r
.clean(cx
)).map(RegionBound
));
751 v
.extend(self.types
.iter().map(|t
| TraitBound(PolyTrait
{
754 }, hir
::TraitBoundModifier
::None
)));
755 if !v
.is_empty() {Some(v)}
else {None}
759 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
760 pub struct Lifetime(String
);
763 pub fn get_ref
<'a
>(&'a
self) -> &'a
str {
764 let Lifetime(ref s
) = *self;
769 pub fn statik() -> Lifetime
{
770 Lifetime("'static".to_string())
774 impl Clean
<Lifetime
> for hir
::Lifetime
{
775 fn clean(&self, _
: &DocContext
) -> Lifetime
{
776 Lifetime(self.name
.to_string())
780 impl Clean
<Lifetime
> for hir
::LifetimeDef
{
781 fn clean(&self, _
: &DocContext
) -> Lifetime
{
782 Lifetime(self.lifetime
.name
.to_string())
786 impl Clean
<Lifetime
> for ty
::RegionParameterDef
{
787 fn clean(&self, _
: &DocContext
) -> Lifetime
{
788 Lifetime(self.name
.to_string())
792 impl Clean
<Option
<Lifetime
>> for ty
::Region
{
793 fn clean(&self, cx
: &DocContext
) -> Option
<Lifetime
> {
795 ty
::ReStatic
=> Some(Lifetime
::statik()),
796 ty
::ReLateBound(_
, ty
::BrNamed(_
, name
)) => Some(Lifetime(name
.to_string())),
797 ty
::ReEarlyBound(ref data
) => Some(Lifetime(data
.name
.clean(cx
))),
799 ty
::ReLateBound(..) |
803 ty
::ReSkolemized(..) |
809 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
810 pub enum WherePredicate
{
811 BoundPredicate { ty: Type, bounds: Vec<TyParamBound> }
,
812 RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>}
,
813 EqPredicate { lhs: Type, rhs: Type }
816 impl Clean
<WherePredicate
> for hir
::WherePredicate
{
817 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
819 hir
::WherePredicate
::BoundPredicate(ref wbp
) => {
820 WherePredicate
::BoundPredicate
{
821 ty
: wbp
.bounded_ty
.clean(cx
),
822 bounds
: wbp
.bounds
.clean(cx
)
826 hir
::WherePredicate
::RegionPredicate(ref wrp
) => {
827 WherePredicate
::RegionPredicate
{
828 lifetime
: wrp
.lifetime
.clean(cx
),
829 bounds
: wrp
.bounds
.clean(cx
)
833 hir
::WherePredicate
::EqPredicate(_
) => {
834 unimplemented
!() // FIXME(#20041)
840 impl<'a
> Clean
<WherePredicate
> for ty
::Predicate
<'a
> {
841 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
842 use rustc
::ty
::Predicate
;
845 Predicate
::Trait(ref pred
) => pred
.clean(cx
),
846 Predicate
::Equate(ref pred
) => pred
.clean(cx
),
847 Predicate
::RegionOutlives(ref pred
) => pred
.clean(cx
),
848 Predicate
::TypeOutlives(ref pred
) => pred
.clean(cx
),
849 Predicate
::Projection(ref pred
) => pred
.clean(cx
),
850 Predicate
::WellFormed(_
) => panic
!("not user writable"),
851 Predicate
::ObjectSafe(_
) => panic
!("not user writable"),
856 impl<'a
> Clean
<WherePredicate
> for ty
::TraitPredicate
<'a
> {
857 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
858 WherePredicate
::BoundPredicate
{
859 ty
: self.trait_ref
.substs
.self_ty().clean(cx
).unwrap(),
860 bounds
: vec
![self.trait_ref
.clean(cx
)]
865 impl<'tcx
> Clean
<WherePredicate
> for ty
::EquatePredicate
<'tcx
> {
866 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
867 let ty
::EquatePredicate(ref lhs
, ref rhs
) = *self;
868 WherePredicate
::EqPredicate
{
875 impl Clean
<WherePredicate
> for ty
::OutlivesPredicate
<ty
::Region
, ty
::Region
> {
876 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
877 let ty
::OutlivesPredicate(ref a
, ref b
) = *self;
878 WherePredicate
::RegionPredicate
{
879 lifetime
: a
.clean(cx
).unwrap(),
880 bounds
: vec
![b
.clean(cx
).unwrap()]
885 impl<'tcx
> Clean
<WherePredicate
> for ty
::OutlivesPredicate
<ty
::Ty
<'tcx
>, ty
::Region
> {
886 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
887 let ty
::OutlivesPredicate(ref ty
, ref lt
) = *self;
889 WherePredicate
::BoundPredicate
{
891 bounds
: vec
![TyParamBound
::RegionBound(lt
.clean(cx
).unwrap())]
896 impl<'tcx
> Clean
<WherePredicate
> for ty
::ProjectionPredicate
<'tcx
> {
897 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
898 WherePredicate
::EqPredicate
{
899 lhs
: self.projection_ty
.clean(cx
),
900 rhs
: self.ty
.clean(cx
)
905 impl<'tcx
> Clean
<Type
> for ty
::ProjectionTy
<'tcx
> {
906 fn clean(&self, cx
: &DocContext
) -> Type
{
907 let trait_
= match self.trait_ref
.clean(cx
) {
908 TyParamBound
::TraitBound(t
, _
) => t
.trait_
,
909 TyParamBound
::RegionBound(_
) => {
910 panic
!("cleaning a trait got a region")
914 name
: self.item_name
.clean(cx
),
915 self_type
: box self.trait_ref
.self_ty().clean(cx
),
921 // maybe use a Generic enum and use Vec<Generic>?
922 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
923 pub struct Generics
{
924 pub lifetimes
: Vec
<Lifetime
>,
925 pub type_params
: Vec
<TyParam
>,
926 pub where_predicates
: Vec
<WherePredicate
>
929 impl Clean
<Generics
> for hir
::Generics
{
930 fn clean(&self, cx
: &DocContext
) -> Generics
{
932 lifetimes
: self.lifetimes
.clean(cx
),
933 type_params
: self.ty_params
.clean(cx
),
934 where_predicates
: self.where_clause
.predicates
.clean(cx
)
939 impl<'a
, 'tcx
> Clean
<Generics
> for (&'a ty
::Generics
<'tcx
>,
940 &'a ty
::GenericPredicates
<'tcx
>,
942 fn clean(&self, cx
: &DocContext
) -> Generics
{
943 use self::WherePredicate
as WP
;
945 let (gens
, preds
, space
) = *self;
947 // Bounds in the type_params and lifetimes fields are repeated in the
948 // predicates field (see rustc_typeck::collect::ty_generics), so remove
950 let stripped_typarams
= gens
.types
.get_slice(space
).iter().map(|tp
| {
952 }).collect
::<Vec
<_
>>();
953 let stripped_lifetimes
= gens
.regions
.get_slice(space
).iter().map(|rp
| {
954 let mut srp
= rp
.clone();
955 srp
.bounds
= Vec
::new();
957 }).collect
::<Vec
<_
>>();
959 let mut where_predicates
= preds
.predicates
.get_slice(space
)
962 // Type parameters and have a Sized bound by default unless removed with
963 // ?Sized. Scan through the predicates and mark any type parameter with
964 // a Sized bound, removing the bounds as we find them.
966 // Note that associated types also have a sized bound by default, but we
967 // don't actually know the set of associated types right here so that's
968 // handled in cleaning associated types
969 let mut sized_params
= HashSet
::new();
970 where_predicates
.retain(|pred
| {
972 WP
::BoundPredicate { ty: Generic(ref g), ref bounds }
=> {
973 if bounds
.iter().any(|b
| b
.is_sized_bound(cx
)) {
974 sized_params
.insert(g
.clone());
984 // Run through the type parameters again and insert a ?Sized
985 // unbound for any we didn't find to be Sized.
986 for tp
in &stripped_typarams
{
987 if !sized_params
.contains(&tp
.name
) {
988 where_predicates
.push(WP
::BoundPredicate
{
989 ty
: Type
::Generic(tp
.name
.clone()),
990 bounds
: vec
![TyParamBound
::maybe_sized(cx
)],
995 // It would be nice to collect all of the bounds on a type and recombine
996 // them if possible, to avoid e.g. `where T: Foo, T: Bar, T: Sized, T: 'a`
997 // and instead see `where T: Foo + Bar + Sized + 'a`
1000 type_params
: simplify
::ty_params(stripped_typarams
),
1001 lifetimes
: stripped_lifetimes
,
1002 where_predicates
: simplify
::where_clauses(cx
, where_predicates
),
1007 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1009 pub generics
: Generics
,
1011 pub unsafety
: hir
::Unsafety
,
1012 pub constness
: hir
::Constness
,
1017 impl Clean
<Method
> for hir
::MethodSig
{
1018 fn clean(&self, cx
: &DocContext
) -> Method
{
1019 let all_inputs
= &self.decl
.inputs
;
1020 let inputs
= match self.explicit_self
.node
{
1021 hir
::SelfStatic
=> &**all_inputs
,
1022 _
=> &all_inputs
[1..]
1026 values
: inputs
.clean(cx
),
1028 output
: self.decl
.output
.clean(cx
),
1033 generics
: self.generics
.clean(cx
),
1034 self_
: self.explicit_self
.node
.clean(cx
),
1035 unsafety
: self.unsafety
,
1036 constness
: self.constness
,
1043 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1044 pub struct TyMethod
{
1045 pub unsafety
: hir
::Unsafety
,
1047 pub generics
: Generics
,
1052 impl Clean
<TyMethod
> for hir
::MethodSig
{
1053 fn clean(&self, cx
: &DocContext
) -> TyMethod
{
1054 let inputs
= match self.explicit_self
.node
{
1055 hir
::SelfStatic
=> &*self.decl
.inputs
,
1056 _
=> &self.decl
.inputs
[1..]
1060 values
: inputs
.clean(cx
),
1062 output
: self.decl
.output
.clean(cx
),
1067 unsafety
: self.unsafety
.clone(),
1069 self_
: self.explicit_self
.node
.clean(cx
),
1070 generics
: self.generics
.clean(cx
),
1076 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1080 SelfBorrowed(Option
<Lifetime
>, Mutability
),
1084 impl Clean
<SelfTy
> for hir
::ExplicitSelf_
{
1085 fn clean(&self, cx
: &DocContext
) -> SelfTy
{
1087 hir
::SelfStatic
=> SelfStatic
,
1088 hir
::SelfValue(_
) => SelfValue
,
1089 hir
::SelfRegion(ref lt
, ref mt
, _
) => {
1090 SelfBorrowed(lt
.clean(cx
), mt
.clean(cx
))
1092 hir
::SelfExplicit(ref typ
, _
) => SelfExplicit(typ
.clean(cx
)),
1097 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1098 pub struct Function
{
1100 pub generics
: Generics
,
1101 pub unsafety
: hir
::Unsafety
,
1102 pub constness
: hir
::Constness
,
1106 impl Clean
<Item
> for doctree
::Function
{
1107 fn clean(&self, cx
: &DocContext
) -> Item
{
1109 name
: Some(self.name
.clean(cx
)),
1110 attrs
: self.attrs
.clean(cx
),
1111 source
: self.whence
.clean(cx
),
1112 visibility
: self.vis
.clean(cx
),
1113 stability
: self.stab
.clean(cx
),
1114 deprecation
: self.depr
.clean(cx
),
1115 def_id
: cx
.map
.local_def_id(self.id
),
1116 inner
: FunctionItem(Function
{
1117 decl
: self.decl
.clean(cx
),
1118 generics
: self.generics
.clean(cx
),
1119 unsafety
: self.unsafety
,
1120 constness
: self.constness
,
1127 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1129 pub inputs
: Arguments
,
1130 pub output
: FunctionRetTy
,
1132 pub attrs
: Vec
<Attribute
>,
1135 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1136 pub struct Arguments
{
1137 pub values
: Vec
<Argument
>,
1140 impl Clean
<FnDecl
> for hir
::FnDecl
{
1141 fn clean(&self, cx
: &DocContext
) -> FnDecl
{
1144 values
: self.inputs
.clean(cx
),
1146 output
: self.output
.clean(cx
),
1147 variadic
: self.variadic
,
1153 impl<'tcx
> Clean
<Type
> for ty
::FnOutput
<'tcx
> {
1154 fn clean(&self, cx
: &DocContext
) -> Type
{
1156 ty
::FnConverging(ty
) => ty
.clean(cx
),
1157 ty
::FnDiverging
=> Bottom
1162 impl<'a
, 'tcx
> Clean
<FnDecl
> for (DefId
, &'a ty
::PolyFnSig
<'tcx
>) {
1163 fn clean(&self, cx
: &DocContext
) -> FnDecl
{
1164 let (did
, sig
) = *self;
1165 let mut names
= if cx
.map
.as_local_node_id(did
).is_some() {
1168 cx
.tcx().sess
.cstore
.method_arg_names(did
).into_iter()
1170 if let Some("self") = names
.peek().map(|s
| &s
[..]) {
1171 let _
= names
.next();
1174 output
: Return(sig
.0.output
.clean(cx
)),
1176 variadic
: sig
.0.variadic
,
1178 values
: sig
.0.inputs
.iter().map(|t
| {
1182 name
: names
.next().unwrap_or("".to_string()),
1190 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1191 pub struct Argument
{
1194 pub id
: ast
::NodeId
,
1197 impl Clean
<Argument
> for hir
::Arg
{
1198 fn clean(&self, cx
: &DocContext
) -> Argument
{
1200 name
: name_from_pat(&*self.pat
),
1201 type_
: (self.ty
.clean(cx
)),
1207 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1208 pub enum FunctionRetTy
{
1214 impl Clean
<FunctionRetTy
> for hir
::FunctionRetTy
{
1215 fn clean(&self, cx
: &DocContext
) -> FunctionRetTy
{
1217 hir
::Return(ref typ
) => Return(typ
.clean(cx
)),
1218 hir
::DefaultReturn(..) => DefaultReturn
,
1219 hir
::NoReturn(..) => NoReturn
1224 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1226 pub unsafety
: hir
::Unsafety
,
1227 pub items
: Vec
<Item
>,
1228 pub generics
: Generics
,
1229 pub bounds
: Vec
<TyParamBound
>,
1232 impl Clean
<Item
> for doctree
::Trait
{
1233 fn clean(&self, cx
: &DocContext
) -> Item
{
1235 name
: Some(self.name
.clean(cx
)),
1236 attrs
: self.attrs
.clean(cx
),
1237 source
: self.whence
.clean(cx
),
1238 def_id
: cx
.map
.local_def_id(self.id
),
1239 visibility
: self.vis
.clean(cx
),
1240 stability
: self.stab
.clean(cx
),
1241 deprecation
: self.depr
.clean(cx
),
1242 inner
: TraitItem(Trait
{
1243 unsafety
: self.unsafety
,
1244 items
: self.items
.clean(cx
),
1245 generics
: self.generics
.clean(cx
),
1246 bounds
: self.bounds
.clean(cx
),
1252 impl Clean
<Type
> for hir
::TraitRef
{
1253 fn clean(&self, cx
: &DocContext
) -> Type
{
1254 resolve_type(cx
, self.path
.clean(cx
), self.ref_id
)
1258 impl Clean
<PolyTrait
> for hir
::PolyTraitRef
{
1259 fn clean(&self, cx
: &DocContext
) -> PolyTrait
{
1261 trait_
: self.trait_ref
.clean(cx
),
1262 lifetimes
: self.bound_lifetimes
.clean(cx
)
1267 impl Clean
<Item
> for hir
::TraitItem
{
1268 fn clean(&self, cx
: &DocContext
) -> Item
{
1269 let inner
= match self.node
{
1270 hir
::ConstTraitItem(ref ty
, ref default) => {
1271 AssociatedConstItem(ty
.clean(cx
),
1272 default.as_ref().map(|expr
|
1273 expr
.span
.to_src(cx
)))
1275 hir
::MethodTraitItem(ref sig
, Some(_
)) => {
1276 MethodItem(sig
.clean(cx
))
1278 hir
::MethodTraitItem(ref sig
, None
) => {
1279 TyMethodItem(sig
.clean(cx
))
1281 hir
::TypeTraitItem(ref bounds
, ref default) => {
1282 AssociatedTypeItem(bounds
.clean(cx
), default.clean(cx
))
1286 name
: Some(self.name
.clean(cx
)),
1287 attrs
: self.attrs
.clean(cx
),
1288 source
: self.span
.clean(cx
),
1289 def_id
: cx
.map
.local_def_id(self.id
),
1291 stability
: get_stability(cx
, cx
.map
.local_def_id(self.id
)),
1292 deprecation
: get_deprecation(cx
, cx
.map
.local_def_id(self.id
)),
1298 impl Clean
<Item
> for hir
::ImplItem
{
1299 fn clean(&self, cx
: &DocContext
) -> Item
{
1300 let inner
= match self.node
{
1301 hir
::ImplItemKind
::Const(ref ty
, ref expr
) => {
1302 AssociatedConstItem(ty
.clean(cx
),
1303 Some(expr
.span
.to_src(cx
)))
1305 hir
::ImplItemKind
::Method(ref sig
, _
) => {
1306 MethodItem(sig
.clean(cx
))
1308 hir
::ImplItemKind
::Type(ref ty
) => TypedefItem(Typedef
{
1309 type_
: ty
.clean(cx
),
1310 generics
: Generics
{
1311 lifetimes
: Vec
::new(),
1312 type_params
: Vec
::new(),
1313 where_predicates
: Vec
::new()
1318 name
: Some(self.name
.clean(cx
)),
1319 source
: self.span
.clean(cx
),
1320 attrs
: self.attrs
.clean(cx
),
1321 def_id
: cx
.map
.local_def_id(self.id
),
1322 visibility
: self.vis
.clean(cx
),
1323 stability
: get_stability(cx
, cx
.map
.local_def_id(self.id
)),
1324 deprecation
: get_deprecation(cx
, cx
.map
.local_def_id(self.id
)),
1330 impl<'tcx
> Clean
<Item
> for ty
::Method
<'tcx
> {
1331 fn clean(&self, cx
: &DocContext
) -> Item
{
1332 let (self_
, sig
) = match self.explicit_self
{
1333 ty
::ExplicitSelfCategory
::Static
=> (hir
::SelfStatic
.clean(cx
),
1334 self.fty
.sig
.clone()),
1336 let sig
= ty
::Binder(ty
::FnSig
{
1337 inputs
: self.fty
.sig
.0.inputs
[1..].to_vec(),
1338 ..self.fty
.sig
.0.clone()
1341 ty
::ExplicitSelfCategory
::ByValue
=> SelfValue
,
1342 ty
::ExplicitSelfCategory
::ByReference(..) => {
1343 match self.fty
.sig
.0.inputs
[0].sty
{
1344 ty
::TyRef(r
, mt
) => {
1345 SelfBorrowed(r
.clean(cx
), mt
.mutbl
.clean(cx
))
1347 _
=> unreachable
!(),
1350 ty
::ExplicitSelfCategory
::ByBox
=> {
1351 SelfExplicit(self.fty
.sig
.0.inputs
[0].clean(cx
))
1353 ty
::ExplicitSelfCategory
::Static
=> unreachable
!(),
1359 let generics
= (&self.generics
, &self.predicates
,
1360 subst
::FnSpace
).clean(cx
);
1361 let decl
= (self.def_id
, &sig
).clean(cx
);
1362 let provided
= match self.container
{
1363 ty
::ImplContainer(..) => false,
1364 ty
::TraitContainer(did
) => {
1365 cx
.tcx().provided_trait_methods(did
).iter().any(|m
| {
1366 m
.def_id
== self.def_id
1370 let inner
= if provided
{
1372 unsafety
: self.fty
.unsafety
,
1378 // trait methods canot (currently, at least) be const
1379 constness
: hir
::Constness
::NotConst
,
1382 TyMethodItem(TyMethod
{
1383 unsafety
: self.fty
.unsafety
,
1392 name
: Some(self.name
.clean(cx
)),
1393 visibility
: Some(hir
::Inherited
),
1394 stability
: get_stability(cx
, self.def_id
),
1395 deprecation
: get_deprecation(cx
, self.def_id
),
1396 def_id
: self.def_id
,
1397 attrs
: inline
::load_attrs(cx
, cx
.tcx(), self.def_id
),
1398 source
: Span
::empty(),
1404 impl<'tcx
> Clean
<Item
> for ty
::ImplOrTraitItem
<'tcx
> {
1405 fn clean(&self, cx
: &DocContext
) -> Item
{
1407 ty
::ConstTraitItem(ref cti
) => cti
.clean(cx
),
1408 ty
::MethodTraitItem(ref mti
) => mti
.clean(cx
),
1409 ty
::TypeTraitItem(ref tti
) => tti
.clean(cx
),
1414 /// A trait reference, which may have higher ranked lifetimes.
1415 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1416 pub struct PolyTrait
{
1418 pub lifetimes
: Vec
<Lifetime
>
1421 /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
1422 /// type out of the AST/TyCtxt given one of these, if more information is needed. Most importantly
1423 /// it does not preserve mutability or boxes.
1424 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1426 /// structs/enums/traits (most that'd be an hir::TyPath)
1429 typarams
: Option
<Vec
<TyParamBound
>>,
1431 /// true if is a `T::Name` path for associated types
1434 /// For parameterized types, so the consumer of the JSON don't go
1435 /// looking for types which don't exist anywhere.
1437 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1438 /// arrays, slices, and tuples.
1439 Primitive(PrimitiveType
),
1441 BareFunction(Box
<BareFunctionDecl
>),
1444 FixedVector(Box
<Type
>, String
),
1448 RawPointer(Mutability
, Box
<Type
>),
1450 lifetime
: Option
<Lifetime
>,
1451 mutability
: Mutability
,
1455 // <Type as Trait>::Name
1458 self_type
: Box
<Type
>,
1466 PolyTraitRef(Vec
<TyParamBound
>),
1469 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
1470 pub enum PrimitiveType
{
1471 Isize
, I8
, I16
, I32
, I64
,
1472 Usize
, U8
, U16
, U32
, U64
,
1480 PrimitiveRawPointer
,
1483 #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
1496 pub trait GetDefId
{
1497 fn def_id(&self) -> Option
<DefId
>;
1500 impl<T
: GetDefId
> GetDefId
for Option
<T
> {
1501 fn def_id(&self) -> Option
<DefId
> {
1502 self.as_ref().and_then(|d
| d
.def_id())
1507 pub fn primitive_type(&self) -> Option
<PrimitiveType
> {
1509 Primitive(p
) | BorrowedRef { type_: box Primitive(p), ..}
=> Some(p
),
1510 Vector(..) | BorrowedRef{ type_: box Vector(..), .. }
=> Some(Slice
),
1511 FixedVector(..) | BorrowedRef { type_: box FixedVector(..), .. }
=> {
1514 Tuple(..) => Some(PrimitiveTuple
),
1515 RawPointer(..) => Some(PrimitiveRawPointer
),
1521 impl GetDefId
for Type
{
1522 fn def_id(&self) -> Option
<DefId
> {
1524 ResolvedPath { did, .. }
=> Some(did
),
1530 impl PrimitiveType
{
1531 fn from_str(s
: &str) -> Option
<PrimitiveType
> {
1533 "isize" => Some(Isize
),
1538 "usize" => Some(Usize
),
1543 "bool" => Some(Bool
),
1544 "char" => Some(Char
),
1548 "array" => Some(Array
),
1549 "slice" => Some(Slice
),
1550 "tuple" => Some(PrimitiveTuple
),
1551 "pointer" => Some(PrimitiveRawPointer
),
1556 fn find(attrs
: &[Attribute
]) -> Option
<PrimitiveType
> {
1557 for attr
in attrs
.list("doc") {
1558 if let NameValue(ref k
, ref v
) = *attr
{
1559 if "primitive" == *k
{
1560 if let ret@
Some(..) = PrimitiveType
::from_str(v
) {
1569 pub fn to_string(&self) -> &'
static str {
1588 PrimitiveTuple
=> "tuple",
1589 PrimitiveRawPointer
=> "pointer",
1593 pub fn to_url_str(&self) -> &'
static str {
1597 /// Creates a rustdoc-specific node id for primitive types.
1599 /// These node ids are generally never used by the AST itself.
1600 pub fn to_def_index(&self) -> DefIndex
{
1601 let x
= u32::MAX
- 1 - (*self as u32);
1602 DefIndex
::new(x
as usize)
1606 impl Clean
<Type
> for hir
::Ty
{
1607 fn clean(&self, cx
: &DocContext
) -> Type
{
1610 TyPtr(ref m
) => RawPointer(m
.mutbl
.clean(cx
), box m
.ty
.clean(cx
)),
1611 TyRptr(ref l
, ref m
) =>
1612 BorrowedRef
{lifetime
: l
.clean(cx
), mutability
: m
.mutbl
.clean(cx
),
1613 type_
: box m
.ty
.clean(cx
)},
1614 TyVec(ref ty
) => Vector(box ty
.clean(cx
)),
1615 TyFixedLengthVec(ref ty
, ref e
) => FixedVector(box ty
.clean(cx
),
1617 TyTup(ref tys
) => Tuple(tys
.clean(cx
)),
1618 TyPath(None
, ref p
) => {
1619 resolve_type(cx
, p
.clean(cx
), self.id
)
1621 TyPath(Some(ref qself
), ref p
) => {
1622 let mut segments
: Vec
<_
> = p
.segments
.clone().into();
1624 let trait_path
= hir
::Path
{
1627 segments
: segments
.into(),
1630 name
: p
.segments
.last().unwrap().identifier
.name
.clean(cx
),
1631 self_type
: box qself
.ty
.clean(cx
),
1632 trait_
: box resolve_type(cx
, trait_path
.clean(cx
), self.id
)
1635 TyObjectSum(ref lhs
, ref bounds
) => {
1636 let lhs_ty
= lhs
.clean(cx
);
1638 ResolvedPath { path, typarams: None, did, is_generic }
=> {
1641 typarams
: Some(bounds
.clean(cx
)),
1643 is_generic
: is_generic
,
1647 lhs_ty
// shouldn't happen
1651 TyBareFn(ref barefn
) => BareFunction(box barefn
.clean(cx
)),
1652 TyPolyTraitRef(ref bounds
) => PolyTraitRef(bounds
.clean(cx
)),
1654 TyTypeof(..) => panic
!("Unimplemented type {:?}", self.node
),
1659 impl<'tcx
> Clean
<Type
> for ty
::Ty
<'tcx
> {
1660 fn clean(&self, cx
: &DocContext
) -> Type
{
1662 ty
::TyBool
=> Primitive(Bool
),
1663 ty
::TyChar
=> Primitive(Char
),
1664 ty
::TyInt(ast
::IntTy
::Is
) => Primitive(Isize
),
1665 ty
::TyInt(ast
::IntTy
::I8
) => Primitive(I8
),
1666 ty
::TyInt(ast
::IntTy
::I16
) => Primitive(I16
),
1667 ty
::TyInt(ast
::IntTy
::I32
) => Primitive(I32
),
1668 ty
::TyInt(ast
::IntTy
::I64
) => Primitive(I64
),
1669 ty
::TyUint(ast
::UintTy
::Us
) => Primitive(Usize
),
1670 ty
::TyUint(ast
::UintTy
::U8
) => Primitive(U8
),
1671 ty
::TyUint(ast
::UintTy
::U16
) => Primitive(U16
),
1672 ty
::TyUint(ast
::UintTy
::U32
) => Primitive(U32
),
1673 ty
::TyUint(ast
::UintTy
::U64
) => Primitive(U64
),
1674 ty
::TyFloat(ast
::FloatTy
::F32
) => Primitive(F32
),
1675 ty
::TyFloat(ast
::FloatTy
::F64
) => Primitive(F64
),
1676 ty
::TyStr
=> Primitive(Str
),
1678 let box_did
= cx
.tcx_opt().and_then(|tcx
| {
1679 tcx
.lang_items
.owned_box()
1681 lang_struct(cx
, box_did
, t
, "Box", Unique
)
1683 ty
::TySlice(ty
) => Vector(box ty
.clean(cx
)),
1684 ty
::TyArray(ty
, i
) => FixedVector(box ty
.clean(cx
),
1686 ty
::TyRawPtr(mt
) => RawPointer(mt
.mutbl
.clean(cx
), box mt
.ty
.clean(cx
)),
1687 ty
::TyRef(r
, mt
) => BorrowedRef
{
1688 lifetime
: r
.clean(cx
),
1689 mutability
: mt
.mutbl
.clean(cx
),
1690 type_
: box mt
.ty
.clean(cx
),
1692 ty
::TyFnDef(_
, _
, ref fty
) |
1693 ty
::TyFnPtr(ref fty
) => BareFunction(box BareFunctionDecl
{
1694 unsafety
: fty
.unsafety
,
1695 generics
: Generics
{
1696 lifetimes
: Vec
::new(),
1697 type_params
: Vec
::new(),
1698 where_predicates
: Vec
::new()
1700 decl
: (cx
.map
.local_def_id(0), &fty
.sig
).clean(cx
),
1701 abi
: fty
.abi
.to_string(),
1703 ty
::TyStruct(def
, substs
) |
1704 ty
::TyEnum(def
, substs
) => {
1706 let kind
= match self.sty
{
1707 ty
::TyStruct(..) => TypeStruct
,
1710 inline
::record_extern_fqn(cx
, did
, kind
);
1711 let path
= external_path(cx
, &cx
.tcx().item_name(did
).as_str(),
1712 None
, vec
![], substs
);
1720 ty
::TyTrait(box ty
::TraitTy { ref principal, ref bounds }
) => {
1721 let did
= principal
.def_id();
1722 inline
::record_extern_fqn(cx
, did
, TypeTrait
);
1723 let (typarams
, bindings
) = bounds
.clean(cx
);
1724 let path
= external_path(cx
, &cx
.tcx().item_name(did
).as_str(),
1725 Some(did
), bindings
, principal
.substs());
1728 typarams
: Some(typarams
),
1733 ty
::TyTuple(ref t
) => Tuple(t
.clean(cx
)),
1735 ty
::TyProjection(ref data
) => data
.clean(cx
),
1737 ty
::TyParam(ref p
) => Generic(p
.name
.to_string()),
1739 ty
::TyClosure(..) => Tuple(vec
![]), // FIXME(pcwalton)
1741 ty
::TyInfer(..) => panic
!("TyInfer"),
1742 ty
::TyError
=> panic
!("TyError"),
1747 impl Clean
<Item
> for hir
::StructField
{
1748 fn clean(&self, cx
: &DocContext
) -> Item
{
1750 name
: Some(self.name
).clean(cx
),
1751 attrs
: self.attrs
.clean(cx
),
1752 source
: self.span
.clean(cx
),
1753 visibility
: self.vis
.clean(cx
),
1754 stability
: get_stability(cx
, cx
.map
.local_def_id(self.id
)),
1755 deprecation
: get_deprecation(cx
, cx
.map
.local_def_id(self.id
)),
1756 def_id
: cx
.map
.local_def_id(self.id
),
1757 inner
: StructFieldItem(self.ty
.clean(cx
)),
1762 impl<'tcx
> Clean
<Item
> for ty
::FieldDefData
<'tcx
, '
static> {
1763 fn clean(&self, cx
: &DocContext
) -> Item
{
1764 // FIXME: possible O(n^2)-ness! Not my fault.
1765 let attr_map
= cx
.tcx().sess
.cstore
.crate_struct_field_attrs(self.did
.krate
);
1767 name
: Some(self.name
).clean(cx
),
1768 attrs
: attr_map
.get(&self.did
).unwrap_or(&Vec
::new()).clean(cx
),
1769 source
: Span
::empty(),
1770 visibility
: self.vis
.clean(cx
),
1771 stability
: get_stability(cx
, self.did
),
1772 deprecation
: get_deprecation(cx
, self.did
),
1774 inner
: StructFieldItem(self.unsubst_ty().clean(cx
)),
1779 pub type Visibility
= hir
::Visibility
;
1781 impl Clean
<Option
<Visibility
>> for hir
::Visibility
{
1782 fn clean(&self, _
: &DocContext
) -> Option
<Visibility
> {
1787 impl Clean
<Option
<Visibility
>> for ty
::Visibility
{
1788 fn clean(&self, _
: &DocContext
) -> Option
<Visibility
> {
1789 Some(if *self == ty
::Visibility
::Public { hir::Public }
else { hir::Inherited }
)
1793 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1795 pub struct_type
: doctree
::StructType
,
1796 pub generics
: Generics
,
1797 pub fields
: Vec
<Item
>,
1798 pub fields_stripped
: bool
,
1801 impl Clean
<Item
> for doctree
::Struct
{
1802 fn clean(&self, cx
: &DocContext
) -> Item
{
1804 name
: Some(self.name
.clean(cx
)),
1805 attrs
: self.attrs
.clean(cx
),
1806 source
: self.whence
.clean(cx
),
1807 def_id
: cx
.map
.local_def_id(self.id
),
1808 visibility
: self.vis
.clean(cx
),
1809 stability
: self.stab
.clean(cx
),
1810 deprecation
: self.depr
.clean(cx
),
1811 inner
: StructItem(Struct
{
1812 struct_type
: self.struct_type
,
1813 generics
: self.generics
.clean(cx
),
1814 fields
: self.fields
.clean(cx
),
1815 fields_stripped
: false,
1821 /// This is a more limited form of the standard Struct, different in that
1822 /// it lacks the things most items have (name, id, parameterization). Found
1823 /// only as a variant in an enum.
1824 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1825 pub struct VariantStruct
{
1826 pub struct_type
: doctree
::StructType
,
1827 pub fields
: Vec
<Item
>,
1828 pub fields_stripped
: bool
,
1831 impl Clean
<VariantStruct
> for ::rustc
::hir
::VariantData
{
1832 fn clean(&self, cx
: &DocContext
) -> VariantStruct
{
1834 struct_type
: doctree
::struct_type_from_def(self),
1835 fields
: self.fields().iter().map(|x
| x
.clean(cx
)).collect(),
1836 fields_stripped
: false,
1841 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1843 pub variants
: Vec
<Item
>,
1844 pub generics
: Generics
,
1845 pub variants_stripped
: bool
,
1848 impl Clean
<Item
> for doctree
::Enum
{
1849 fn clean(&self, cx
: &DocContext
) -> Item
{
1851 name
: Some(self.name
.clean(cx
)),
1852 attrs
: self.attrs
.clean(cx
),
1853 source
: self.whence
.clean(cx
),
1854 def_id
: cx
.map
.local_def_id(self.id
),
1855 visibility
: self.vis
.clean(cx
),
1856 stability
: self.stab
.clean(cx
),
1857 deprecation
: self.depr
.clean(cx
),
1858 inner
: EnumItem(Enum
{
1859 variants
: self.variants
.clean(cx
),
1860 generics
: self.generics
.clean(cx
),
1861 variants_stripped
: false,
1867 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1868 pub struct Variant
{
1869 pub kind
: VariantKind
,
1872 impl Clean
<Item
> for doctree
::Variant
{
1873 fn clean(&self, cx
: &DocContext
) -> Item
{
1875 name
: Some(self.name
.clean(cx
)),
1876 attrs
: self.attrs
.clean(cx
),
1877 source
: self.whence
.clean(cx
),
1879 stability
: self.stab
.clean(cx
),
1880 deprecation
: self.depr
.clean(cx
),
1881 def_id
: cx
.map
.local_def_id(self.def
.id()),
1882 inner
: VariantItem(Variant
{
1883 kind
: struct_def_to_variant_kind(&self.def
, cx
),
1889 impl<'tcx
> Clean
<Item
> for ty
::VariantDefData
<'tcx
, '
static> {
1890 fn clean(&self, cx
: &DocContext
) -> Item
{
1891 let kind
= match self.kind() {
1892 ty
::VariantKind
::Unit
=> CLikeVariant
,
1893 ty
::VariantKind
::Tuple
=> {
1895 self.fields
.iter().map(|f
| f
.unsubst_ty().clean(cx
)).collect()
1898 ty
::VariantKind
::Struct
=> {
1899 StructVariant(VariantStruct
{
1900 struct_type
: doctree
::Plain
,
1901 fields_stripped
: false,
1902 fields
: self.fields
.iter().map(|field
| {
1904 source
: Span
::empty(),
1905 name
: Some(field
.name
.clean(cx
)),
1906 attrs
: cx
.tcx().get_attrs(field
.did
).clean(cx
),
1907 visibility
: field
.vis
.clean(cx
),
1909 stability
: get_stability(cx
, field
.did
),
1910 deprecation
: get_deprecation(cx
, field
.did
),
1911 inner
: StructFieldItem(field
.unsubst_ty().clean(cx
))
1918 name
: Some(self.name
.clean(cx
)),
1919 attrs
: inline
::load_attrs(cx
, cx
.tcx(), self.did
),
1920 source
: Span
::empty(),
1921 visibility
: Some(hir
::Inherited
),
1923 inner
: VariantItem(Variant { kind: kind }
),
1924 stability
: get_stability(cx
, self.did
),
1925 deprecation
: get_deprecation(cx
, self.did
),
1930 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1931 pub enum VariantKind
{
1933 TupleVariant(Vec
<Type
>),
1934 StructVariant(VariantStruct
),
1937 fn struct_def_to_variant_kind(struct_def
: &hir
::VariantData
, cx
: &DocContext
) -> VariantKind
{
1938 if struct_def
.is_struct() {
1939 StructVariant(struct_def
.clean(cx
))
1940 } else if struct_def
.is_unit() {
1943 TupleVariant(struct_def
.fields().iter().map(|x
| x
.ty
.clean(cx
)).collect())
1947 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1949 pub filename
: String
,
1957 fn empty() -> Span
{
1959 filename
: "".to_string(),
1960 loline
: 0, locol
: 0,
1961 hiline
: 0, hicol
: 0,
1966 impl Clean
<Span
> for syntax
::codemap
::Span
{
1967 fn clean(&self, cx
: &DocContext
) -> Span
{
1968 if *self == DUMMY_SP
{
1969 return Span
::empty();
1972 let cm
= cx
.sess().codemap();
1973 let filename
= cm
.span_to_filename(*self);
1974 let lo
= cm
.lookup_char_pos(self.lo
);
1975 let hi
= cm
.lookup_char_pos(self.hi
);
1977 filename
: filename
.to_string(),
1979 locol
: lo
.col
.to_usize(),
1981 hicol
: hi
.col
.to_usize(),
1986 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1989 pub segments
: Vec
<PathSegment
>,
1993 pub fn singleton(name
: String
) -> Path
{
1996 segments
: vec
![PathSegment
{
1998 params
: PathParameters
::AngleBracketed
{
1999 lifetimes
: Vec
::new(),
2001 bindings
: Vec
::new()
2008 impl Clean
<Path
> for hir
::Path
{
2009 fn clean(&self, cx
: &DocContext
) -> Path
{
2011 global
: self.global
,
2012 segments
: self.segments
.clean(cx
),
2017 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2018 pub enum PathParameters
{
2020 lifetimes
: Vec
<Lifetime
>,
2022 bindings
: Vec
<TypeBinding
>
2026 output
: Option
<Type
>
2030 impl Clean
<PathParameters
> for hir
::PathParameters
{
2031 fn clean(&self, cx
: &DocContext
) -> PathParameters
{
2033 hir
::AngleBracketedParameters(ref data
) => {
2034 PathParameters
::AngleBracketed
{
2035 lifetimes
: data
.lifetimes
.clean(cx
),
2036 types
: data
.types
.clean(cx
),
2037 bindings
: data
.bindings
.clean(cx
)
2041 hir
::ParenthesizedParameters(ref data
) => {
2042 PathParameters
::Parenthesized
{
2043 inputs
: data
.inputs
.clean(cx
),
2044 output
: data
.output
.clean(cx
)
2051 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2052 pub struct PathSegment
{
2054 pub params
: PathParameters
2057 impl Clean
<PathSegment
> for hir
::PathSegment
{
2058 fn clean(&self, cx
: &DocContext
) -> PathSegment
{
2060 name
: self.identifier
.name
.clean(cx
),
2061 params
: self.parameters
.clean(cx
)
2066 fn path_to_string(p
: &hir
::Path
) -> String
{
2067 let mut s
= String
::new();
2068 let mut first
= true;
2069 for i
in p
.segments
.iter().map(|x
| x
.identifier
.name
.as_str()) {
2070 if !first
|| p
.global
{
2080 impl Clean
<String
> for ast
::Name
{
2081 fn clean(&self, _
: &DocContext
) -> String
{
2086 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2087 pub struct Typedef
{
2089 pub generics
: Generics
,
2092 impl Clean
<Item
> for doctree
::Typedef
{
2093 fn clean(&self, cx
: &DocContext
) -> Item
{
2095 name
: Some(self.name
.clean(cx
)),
2096 attrs
: self.attrs
.clean(cx
),
2097 source
: self.whence
.clean(cx
),
2098 def_id
: cx
.map
.local_def_id(self.id
.clone()),
2099 visibility
: self.vis
.clean(cx
),
2100 stability
: self.stab
.clean(cx
),
2101 deprecation
: self.depr
.clean(cx
),
2102 inner
: TypedefItem(Typedef
{
2103 type_
: self.ty
.clean(cx
),
2104 generics
: self.gen
.clean(cx
),
2110 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2111 pub struct BareFunctionDecl
{
2112 pub unsafety
: hir
::Unsafety
,
2113 pub generics
: Generics
,
2118 impl Clean
<BareFunctionDecl
> for hir
::BareFnTy
{
2119 fn clean(&self, cx
: &DocContext
) -> BareFunctionDecl
{
2121 unsafety
: self.unsafety
,
2122 generics
: Generics
{
2123 lifetimes
: self.lifetimes
.clean(cx
),
2124 type_params
: Vec
::new(),
2125 where_predicates
: Vec
::new()
2127 decl
: self.decl
.clean(cx
),
2128 abi
: self.abi
.to_string(),
2133 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2136 pub mutability
: Mutability
,
2137 /// It's useful to have the value of a static documented, but I have no
2138 /// desire to represent expressions (that'd basically be all of the AST,
2139 /// which is huge!). So, have a string.
2143 impl Clean
<Item
> for doctree
::Static
{
2144 fn clean(&self, cx
: &DocContext
) -> Item
{
2145 debug
!("cleaning static {}: {:?}", self.name
.clean(cx
), self);
2147 name
: Some(self.name
.clean(cx
)),
2148 attrs
: self.attrs
.clean(cx
),
2149 source
: self.whence
.clean(cx
),
2150 def_id
: cx
.map
.local_def_id(self.id
),
2151 visibility
: self.vis
.clean(cx
),
2152 stability
: self.stab
.clean(cx
),
2153 deprecation
: self.depr
.clean(cx
),
2154 inner
: StaticItem(Static
{
2155 type_
: self.type_
.clean(cx
),
2156 mutability
: self.mutability
.clean(cx
),
2157 expr
: self.expr
.span
.to_src(cx
),
2163 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2164 pub struct Constant
{
2169 impl Clean
<Item
> for doctree
::Constant
{
2170 fn clean(&self, cx
: &DocContext
) -> Item
{
2172 name
: Some(self.name
.clean(cx
)),
2173 attrs
: self.attrs
.clean(cx
),
2174 source
: self.whence
.clean(cx
),
2175 def_id
: cx
.map
.local_def_id(self.id
),
2176 visibility
: self.vis
.clean(cx
),
2177 stability
: self.stab
.clean(cx
),
2178 deprecation
: self.depr
.clean(cx
),
2179 inner
: ConstantItem(Constant
{
2180 type_
: self.type_
.clean(cx
),
2181 expr
: self.expr
.span
.to_src(cx
),
2187 #[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)]
2188 pub enum Mutability
{
2193 impl Clean
<Mutability
> for hir
::Mutability
{
2194 fn clean(&self, _
: &DocContext
) -> Mutability
{
2196 &hir
::MutMutable
=> Mutable
,
2197 &hir
::MutImmutable
=> Immutable
,
2202 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)]
2203 pub enum ImplPolarity
{
2208 impl Clean
<ImplPolarity
> for hir
::ImplPolarity
{
2209 fn clean(&self, _
: &DocContext
) -> ImplPolarity
{
2211 &hir
::ImplPolarity
::Positive
=> ImplPolarity
::Positive
,
2212 &hir
::ImplPolarity
::Negative
=> ImplPolarity
::Negative
,
2217 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2219 pub unsafety
: hir
::Unsafety
,
2220 pub generics
: Generics
,
2221 pub provided_trait_methods
: HashSet
<String
>,
2222 pub trait_
: Option
<Type
>,
2224 pub items
: Vec
<Item
>,
2226 pub polarity
: Option
<ImplPolarity
>,
2229 fn detect_derived
<M
: AttrMetaMethods
>(attrs
: &[M
]) -> bool
{
2230 attr
::contains_name(attrs
, "automatically_derived")
2233 impl Clean
<Vec
<Item
>> for doctree
::Impl
{
2234 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
2235 let mut ret
= Vec
::new();
2236 let trait_
= self.trait_
.clean(cx
);
2237 let items
= self.items
.clean(cx
);
2239 // If this impl block is an implementation of the Deref trait, then we
2240 // need to try inlining the target's inherent impl blocks as well.
2241 if trait_
.def_id() == cx
.deref_trait_did
.get() {
2242 build_deref_target_impls(cx
, &items
, &mut ret
);
2245 let provided
= trait_
.def_id().and_then(|did
| {
2246 cx
.tcx_opt().map(|tcx
| {
2247 tcx
.provided_trait_methods(did
)
2249 .map(|meth
| meth
.name
.to_string())
2252 }).unwrap_or(HashSet
::new());
2256 attrs
: self.attrs
.clean(cx
),
2257 source
: self.whence
.clean(cx
),
2258 def_id
: cx
.map
.local_def_id(self.id
),
2259 visibility
: self.vis
.clean(cx
),
2260 stability
: self.stab
.clean(cx
),
2261 deprecation
: self.depr
.clean(cx
),
2262 inner
: ImplItem(Impl
{
2263 unsafety
: self.unsafety
,
2264 generics
: self.generics
.clean(cx
),
2265 provided_trait_methods
: provided
,
2267 for_
: self.for_
.clean(cx
),
2269 derived
: detect_derived(&self.attrs
),
2270 polarity
: Some(self.polarity
.clean(cx
)),
2277 fn build_deref_target_impls(cx
: &DocContext
,
2279 ret
: &mut Vec
<Item
>) {
2280 let tcx
= match cx
.tcx_opt() {
2286 let target
= match item
.inner
{
2287 TypedefItem(ref t
, true) => &t
.type_
,
2290 let primitive
= match *target
{
2291 ResolvedPath { did, .. }
if did
.is_local() => continue,
2292 ResolvedPath { did, .. }
=> {
2293 ret
.extend(inline
::build_impls(cx
, tcx
, did
));
2296 _
=> match target
.primitive_type() {
2301 let did
= match primitive
{
2302 Isize
=> tcx
.lang_items
.isize_impl(),
2303 I8
=> tcx
.lang_items
.i8_impl(),
2304 I16
=> tcx
.lang_items
.i16_impl(),
2305 I32
=> tcx
.lang_items
.i32_impl(),
2306 I64
=> tcx
.lang_items
.i64_impl(),
2307 Usize
=> tcx
.lang_items
.usize_impl(),
2308 U8
=> tcx
.lang_items
.u8_impl(),
2309 U16
=> tcx
.lang_items
.u16_impl(),
2310 U32
=> tcx
.lang_items
.u32_impl(),
2311 U64
=> tcx
.lang_items
.u64_impl(),
2312 F32
=> tcx
.lang_items
.f32_impl(),
2313 F64
=> tcx
.lang_items
.f64_impl(),
2314 Char
=> tcx
.lang_items
.char_impl(),
2316 Str
=> tcx
.lang_items
.str_impl(),
2317 Slice
=> tcx
.lang_items
.slice_impl(),
2318 Array
=> tcx
.lang_items
.slice_impl(),
2319 PrimitiveTuple
=> None
,
2320 PrimitiveRawPointer
=> tcx
.lang_items
.const_ptr_impl(),
2322 if let Some(did
) = did
{
2323 if !did
.is_local() {
2324 inline
::build_impl(cx
, tcx
, did
, ret
);
2330 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2331 pub struct DefaultImpl
{
2332 pub unsafety
: hir
::Unsafety
,
2336 impl Clean
<Item
> for doctree
::DefaultImpl
{
2337 fn clean(&self, cx
: &DocContext
) -> Item
{
2340 attrs
: self.attrs
.clean(cx
),
2341 source
: self.whence
.clean(cx
),
2342 def_id
: cx
.map
.local_def_id(self.id
),
2343 visibility
: Some(hir
::Public
),
2346 inner
: DefaultImplItem(DefaultImpl
{
2347 unsafety
: self.unsafety
,
2348 trait_
: self.trait_
.clean(cx
),
2354 impl Clean
<Item
> for doctree
::ExternCrate
{
2355 fn clean(&self, cx
: &DocContext
) -> Item
{
2358 attrs
: self.attrs
.clean(cx
),
2359 source
: self.whence
.clean(cx
),
2360 def_id
: cx
.map
.local_def_id(0),
2361 visibility
: self.vis
.clean(cx
),
2364 inner
: ExternCrateItem(self.name
.clean(cx
), self.path
.clone())
2369 impl Clean
<Vec
<Item
>> for doctree
::Import
{
2370 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
2371 // We consider inlining the documentation of `pub use` statements, but we
2372 // forcefully don't inline if this is not public or if the
2373 // #[doc(no_inline)] attribute is present.
2374 let denied
= self.vis
!= hir
::Public
|| self.attrs
.iter().any(|a
| {
2375 &a
.name()[..] == "doc" && match a
.meta_item_list() {
2376 Some(l
) => attr
::contains_name(l
, "no_inline"),
2380 let (mut ret
, inner
) = match self.node
{
2381 hir
::ViewPathGlob(ref p
) => {
2382 (vec
![], GlobImport(resolve_use_source(cx
, p
.clean(cx
), self.id
)))
2384 hir
::ViewPathList(ref p
, ref list
) => {
2385 // Attempt to inline all reexported items, but be sure
2386 // to keep any non-inlineable reexports so they can be
2387 // listed in the documentation.
2388 let mut ret
= vec
![];
2389 let remaining
= if !denied
{
2390 let mut remaining
= vec
![];
2392 match inline
::try_inline(cx
, path
.node
.id(), path
.node
.rename()) {
2397 remaining
.push(path
.clean(cx
));
2405 if remaining
.is_empty() {
2408 (ret
, ImportList(resolve_use_source(cx
, p
.clean(cx
), self.id
),
2411 hir
::ViewPathSimple(name
, ref p
) => {
2413 if let Some(items
) = inline
::try_inline(cx
, self.id
, Some(name
)) {
2417 (vec
![], SimpleImport(name
.clean(cx
),
2418 resolve_use_source(cx
, p
.clean(cx
), self.id
)))
2423 attrs
: self.attrs
.clean(cx
),
2424 source
: self.whence
.clean(cx
),
2425 def_id
: cx
.map
.local_def_id(0),
2426 visibility
: self.vis
.clean(cx
),
2429 inner
: ImportItem(inner
)
2435 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2437 // use source as str;
2438 SimpleImport(String
, ImportSource
),
2440 GlobImport(ImportSource
),
2441 // use source::{a, b, c};
2442 ImportList(ImportSource
, Vec
<ViewListIdent
>),
2445 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2446 pub struct ImportSource
{
2448 pub did
: Option
<DefId
>,
2451 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2452 pub struct ViewListIdent
{
2454 pub rename
: Option
<String
>,
2455 pub source
: Option
<DefId
>,
2458 impl Clean
<ViewListIdent
> for hir
::PathListItem
{
2459 fn clean(&self, cx
: &DocContext
) -> ViewListIdent
{
2461 hir
::PathListIdent { id, name, rename }
=> ViewListIdent
{
2462 name
: name
.clean(cx
),
2463 rename
: rename
.map(|r
| r
.clean(cx
)),
2464 source
: resolve_def(cx
, id
)
2466 hir
::PathListMod { id, rename }
=> ViewListIdent
{
2467 name
: "self".to_string(),
2468 rename
: rename
.map(|r
| r
.clean(cx
)),
2469 source
: resolve_def(cx
, id
)
2475 impl Clean
<Vec
<Item
>> for hir
::ForeignMod
{
2476 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
2477 let mut items
= self.items
.clean(cx
);
2478 for item
in &mut items
{
2479 if let ForeignFunctionItem(ref mut f
) = item
.inner
{
2487 impl Clean
<Item
> for hir
::ForeignItem
{
2488 fn clean(&self, cx
: &DocContext
) -> Item
{
2489 let inner
= match self.node
{
2490 hir
::ForeignItemFn(ref decl
, ref generics
) => {
2491 ForeignFunctionItem(Function
{
2492 decl
: decl
.clean(cx
),
2493 generics
: generics
.clean(cx
),
2494 unsafety
: hir
::Unsafety
::Unsafe
,
2496 constness
: hir
::Constness
::NotConst
,
2499 hir
::ForeignItemStatic(ref ty
, mutbl
) => {
2500 ForeignStaticItem(Static
{
2501 type_
: ty
.clean(cx
),
2502 mutability
: if mutbl {Mutable}
else {Immutable}
,
2503 expr
: "".to_string(),
2508 name
: Some(self.name
.clean(cx
)),
2509 attrs
: self.attrs
.clean(cx
),
2510 source
: self.span
.clean(cx
),
2511 def_id
: cx
.map
.local_def_id(self.id
),
2512 visibility
: self.vis
.clean(cx
),
2513 stability
: get_stability(cx
, cx
.map
.local_def_id(self.id
)),
2514 deprecation
: get_deprecation(cx
, cx
.map
.local_def_id(self.id
)),
2523 fn to_src(&self, cx
: &DocContext
) -> String
;
2526 impl ToSource
for syntax
::codemap
::Span
{
2527 fn to_src(&self, cx
: &DocContext
) -> String
{
2528 debug
!("converting span {:?} to snippet", self.clean(cx
));
2529 let sn
= match cx
.sess().codemap().span_to_snippet(*self) {
2530 Ok(x
) => x
.to_string(),
2531 Err(_
) => "".to_string()
2533 debug
!("got snippet {}", sn
);
2538 fn lit_to_string(lit
: &ast
::Lit
) -> String
{
2540 ast
::LitKind
::Str(ref st
, _
) => st
.to_string(),
2541 ast
::LitKind
::ByteStr(ref data
) => format
!("{:?}", data
),
2542 ast
::LitKind
::Byte(b
) => {
2543 let mut res
= String
::from("b'");
2544 for c
in (b
as char).escape_default() {
2550 ast
::LitKind
::Char(c
) => format
!("'{}'", c
),
2551 ast
::LitKind
::Int(i
, _t
) => i
.to_string(),
2552 ast
::LitKind
::Float(ref f
, _t
) => f
.to_string(),
2553 ast
::LitKind
::FloatUnsuffixed(ref f
) => f
.to_string(),
2554 ast
::LitKind
::Bool(b
) => b
.to_string(),
2558 fn name_from_pat(p
: &hir
::Pat
) -> String
{
2560 debug
!("Trying to get a name from pattern: {:?}", p
);
2563 PatKind
::Wild
=> "_".to_string(),
2564 PatKind
::Ident(_
, ref p
, _
) => p
.node
.to_string(),
2565 PatKind
::TupleStruct(ref p
, _
) | PatKind
::Path(ref p
) => path_to_string(p
),
2566 PatKind
::QPath(..) => panic
!("tried to get argument name from PatKind::QPath, \
2567 which is not allowed in function arguments"),
2568 PatKind
::Struct(ref name
, ref fields
, etc
) => {
2569 format
!("{} {{ {}{} }}", path_to_string(name
),
2570 fields
.iter().map(|&Spanned { node: ref fp, .. }
|
2571 format
!("{}: {}", fp
.name
, name_from_pat(&*fp
.pat
)))
2572 .collect
::<Vec
<String
>>().join(", "),
2573 if etc { ", ..." }
else { "" }
2576 PatKind
::Tup(ref elts
) => format
!("({})", elts
.iter().map(|p
| name_from_pat(&**p
))
2577 .collect
::<Vec
<String
>>().join(", ")),
2578 PatKind
::Box(ref p
) => name_from_pat(&**p
),
2579 PatKind
::Ref(ref p
, _
) => name_from_pat(&**p
),
2580 PatKind
::Lit(..) => {
2581 warn
!("tried to get argument name from PatKind::Lit, \
2582 which is silly in function arguments");
2585 PatKind
::Range(..) => panic
!("tried to get argument name from PatKind::Range, \
2586 which is not allowed in function arguments"),
2587 PatKind
::Vec(ref begin
, ref mid
, ref end
) => {
2588 let begin
= begin
.iter().map(|p
| name_from_pat(&**p
));
2589 let mid
= mid
.as_ref().map(|p
| format
!("..{}", name_from_pat(&**p
))).into_iter();
2590 let end
= end
.iter().map(|p
| name_from_pat(&**p
));
2591 format
!("[{}]", begin
.chain(mid
).chain(end
).collect
::<Vec
<_
>>().join(", "))
2596 /// Given a Type, resolve it using the def_map
2597 fn resolve_type(cx
: &DocContext
,
2599 id
: ast
::NodeId
) -> Type
{
2600 debug
!("resolve_type({:?},{:?})", path
, id
);
2601 let tcx
= match cx
.tcx_opt() {
2603 // If we're extracting tests, this return value's accuracy is not
2604 // important, all we want is a string representation to help people
2605 // figure out what doctests are failing.
2607 let did
= DefId
::local(DefIndex
::from_u32(0));
2608 return ResolvedPath
{
2616 let def
= tcx
.def_map
.borrow().get(&id
).expect("unresolved id not in defmap").full_def();
2617 debug
!("resolve_type: def={:?}", def
);
2619 let is_generic
= match def
{
2620 Def
::PrimTy(p
) => match p
{
2621 hir
::TyStr
=> return Primitive(Str
),
2622 hir
::TyBool
=> return Primitive(Bool
),
2623 hir
::TyChar
=> return Primitive(Char
),
2624 hir
::TyInt(ast
::IntTy
::Is
) => return Primitive(Isize
),
2625 hir
::TyInt(ast
::IntTy
::I8
) => return Primitive(I8
),
2626 hir
::TyInt(ast
::IntTy
::I16
) => return Primitive(I16
),
2627 hir
::TyInt(ast
::IntTy
::I32
) => return Primitive(I32
),
2628 hir
::TyInt(ast
::IntTy
::I64
) => return Primitive(I64
),
2629 hir
::TyUint(ast
::UintTy
::Us
) => return Primitive(Usize
),
2630 hir
::TyUint(ast
::UintTy
::U8
) => return Primitive(U8
),
2631 hir
::TyUint(ast
::UintTy
::U16
) => return Primitive(U16
),
2632 hir
::TyUint(ast
::UintTy
::U32
) => return Primitive(U32
),
2633 hir
::TyUint(ast
::UintTy
::U64
) => return Primitive(U64
),
2634 hir
::TyFloat(ast
::FloatTy
::F32
) => return Primitive(F32
),
2635 hir
::TyFloat(ast
::FloatTy
::F64
) => return Primitive(F64
),
2637 Def
::SelfTy(..) if path
.segments
.len() == 1 => {
2638 return Generic(special_idents
::type_self
.name
.to_string());
2640 Def
::SelfTy(..) | Def
::TyParam(..) => true,
2643 let did
= register_def(&*cx
, def
);
2644 ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
2647 fn register_def(cx
: &DocContext
, def
: Def
) -> DefId
{
2648 debug
!("register_def({:?})", def
);
2650 let (did
, kind
) = match def
{
2651 Def
::Fn(i
) => (i
, TypeFunction
),
2652 Def
::TyAlias(i
) => (i
, TypeTypedef
),
2653 Def
::Enum(i
) => (i
, TypeEnum
),
2654 Def
::Trait(i
) => (i
, TypeTrait
),
2655 Def
::Struct(i
) => (i
, TypeStruct
),
2656 Def
::Mod(i
) => (i
, TypeModule
),
2657 Def
::Static(i
, _
) => (i
, TypeStatic
),
2658 Def
::Variant(i
, _
) => (i
, TypeEnum
),
2659 Def
::SelfTy(Some(def_id
), _
) => (def_id
, TypeTrait
),
2660 Def
::SelfTy(_
, Some((impl_id
, _
))) => return cx
.map
.local_def_id(impl_id
),
2661 _
=> return def
.def_id()
2663 if did
.is_local() { return did }
2664 let tcx
= match cx
.tcx_opt() {
2668 inline
::record_extern_fqn(cx
, did
, kind
);
2669 if let TypeTrait
= kind
{
2670 let t
= inline
::build_external_trait(cx
, tcx
, did
);
2671 cx
.external_traits
.borrow_mut().as_mut().unwrap().insert(did
, t
);
2676 fn resolve_use_source(cx
: &DocContext
, path
: Path
, id
: ast
::NodeId
) -> ImportSource
{
2679 did
: resolve_def(cx
, id
),
2683 fn resolve_def(cx
: &DocContext
, id
: ast
::NodeId
) -> Option
<DefId
> {
2684 cx
.tcx_opt().and_then(|tcx
| {
2685 tcx
.def_map
.borrow().get(&id
).map(|d
| register_def(cx
, d
.full_def()))
2689 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2692 pub imported_from
: Option
<String
>,
2695 impl Clean
<Item
> for doctree
::Macro
{
2696 fn clean(&self, cx
: &DocContext
) -> Item
{
2697 let name
= format
!("{}!", self.name
.clean(cx
));
2699 name
: Some(name
.clone()),
2700 attrs
: self.attrs
.clean(cx
),
2701 source
: self.whence
.clean(cx
),
2702 visibility
: hir
::Public
.clean(cx
),
2703 stability
: self.stab
.clean(cx
),
2704 deprecation
: self.depr
.clean(cx
),
2705 def_id
: cx
.map
.local_def_id(self.id
),
2706 inner
: MacroItem(Macro
{
2707 source
: format
!("macro_rules! {} {{\n{}}}",
2708 name
.trim_right_matches('
!'
), self.matchers
.iter().map(|span
|
2709 format
!(" {} => {{ ... }};\n", span
.to_src(cx
))).collect
::<String
>()),
2710 imported_from
: self.imported_from
.clean(cx
),
2716 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2717 pub struct Stability
{
2718 pub level
: stability
::StabilityLevel
,
2719 pub feature
: String
,
2721 pub deprecated_since
: String
,
2723 pub issue
: Option
<u32>
2726 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2727 pub struct Deprecation
{
2732 impl Clean
<Stability
> for attr
::Stability
{
2733 fn clean(&self, _
: &DocContext
) -> Stability
{
2735 level
: stability
::StabilityLevel
::from_attr_level(&self.level
),
2736 feature
: self.feature
.to_string(),
2737 since
: match self.level
{
2738 attr
::Stable {ref since}
=> since
.to_string(),
2739 _
=> "".to_string(),
2741 deprecated_since
: match self.rustc_depr
{
2742 Some(attr
::RustcDeprecation {ref since, ..}
) => since
.to_string(),
2746 match (&self.rustc_depr
, &self.level
) {
2747 (&Some(ref depr
), _
) => depr
.reason
.to_string(),
2748 (&None
, &attr
::Unstable {reason: Some(ref reason), ..}
) => reason
.to_string(),
2749 _
=> "".to_string(),
2752 issue
: match self.level
{
2753 attr
::Unstable {issue, ..}
=> Some(issue
),
2760 impl<'a
> Clean
<Stability
> for &'a attr
::Stability
{
2761 fn clean(&self, dc
: &DocContext
) -> Stability
{
2766 impl Clean
<Deprecation
> for attr
::Deprecation
{
2767 fn clean(&self, _
: &DocContext
) -> Deprecation
{
2769 since
: self.since
.as_ref().map_or("".to_string(), |s
| s
.to_string()),
2770 note
: self.note
.as_ref().map_or("".to_string(), |s
| s
.to_string()),
2775 impl<'tcx
> Clean
<Item
> for ty
::AssociatedConst
<'tcx
> {
2776 fn clean(&self, cx
: &DocContext
) -> Item
{
2778 source
: DUMMY_SP
.clean(cx
),
2779 name
: Some(self.name
.clean(cx
)),
2781 inner
: AssociatedConstItem(self.ty
.clean(cx
), None
),
2783 def_id
: self.def_id
,
2790 impl<'tcx
> Clean
<Item
> for ty
::AssociatedType
<'tcx
> {
2791 fn clean(&self, cx
: &DocContext
) -> Item
{
2792 let my_name
= self.name
.clean(cx
);
2794 let mut bounds
= if let ty
::TraitContainer(did
) = self.container
{
2795 // When loading a cross-crate associated type, the bounds for this type
2796 // are actually located on the trait/impl itself, so we need to load
2797 // all of the generics from there and then look for bounds that are
2798 // applied to this associated type in question.
2799 let def
= cx
.tcx().lookup_trait_def(did
);
2800 let predicates
= cx
.tcx().lookup_predicates(did
);
2801 let generics
= (&def
.generics
, &predicates
, subst
::TypeSpace
).clean(cx
);
2802 generics
.where_predicates
.iter().filter_map(|pred
| {
2803 let (name
, self_type
, trait_
, bounds
) = match *pred
{
2804 WherePredicate
::BoundPredicate
{
2805 ty
: QPath { ref name, ref self_type, ref trait_ }
,
2807 } => (name
, self_type
, trait_
, bounds
),
2810 if *name
!= my_name { return None }
2812 ResolvedPath { did, .. }
if did
== self.container
.id() => {}
2816 Generic(ref s
) if *s
== "Self" => {}
2820 }).flat_map(|i
| i
.iter().cloned()).collect
::<Vec
<_
>>()
2825 // Our Sized/?Sized bound didn't get handled when creating the generics
2826 // because we didn't actually get our whole set of bounds until just now
2827 // (some of them may have come from the trait). If we do have a sized
2828 // bound, we remove it, and if we don't then we add the `?Sized` bound
2830 match bounds
.iter().position(|b
| b
.is_sized_bound(cx
)) {
2831 Some(i
) => { bounds.remove(i); }
2832 None
=> bounds
.push(TyParamBound
::maybe_sized(cx
)),
2836 source
: DUMMY_SP
.clean(cx
),
2837 name
: Some(self.name
.clean(cx
)),
2838 attrs
: inline
::load_attrs(cx
, cx
.tcx(), self.def_id
),
2839 inner
: AssociatedTypeItem(bounds
, self.ty
.clean(cx
)),
2840 visibility
: self.vis
.clean(cx
),
2841 def_id
: self.def_id
,
2842 stability
: stability
::lookup_stability(cx
.tcx(), self.def_id
).clean(cx
),
2843 deprecation
: stability
::lookup_deprecation(cx
.tcx(), self.def_id
).clean(cx
),
2848 impl<'a
> Clean
<Typedef
> for (ty
::TypeScheme
<'a
>, ty
::GenericPredicates
<'a
>,
2850 fn clean(&self, cx
: &DocContext
) -> Typedef
{
2851 let (ref ty_scheme
, ref predicates
, ps
) = *self;
2853 type_
: ty_scheme
.ty
.clean(cx
),
2854 generics
: (&ty_scheme
.generics
, predicates
, ps
).clean(cx
)
2859 fn lang_struct(cx
: &DocContext
, did
: Option
<DefId
>,
2860 t
: ty
::Ty
, name
: &str,
2861 fallback
: fn(Box
<Type
>) -> Type
) -> Type
{
2862 let did
= match did
{
2864 None
=> return fallback(box t
.clean(cx
)),
2866 inline
::record_extern_fqn(cx
, did
, TypeStruct
);
2872 segments
: vec
![PathSegment
{
2873 name
: name
.to_string(),
2874 params
: PathParameters
::AngleBracketed
{
2876 types
: vec
![t
.clean(cx
)],
2885 /// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
2886 #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)]
2887 pub struct TypeBinding
{
2892 impl Clean
<TypeBinding
> for hir
::TypeBinding
{
2893 fn clean(&self, cx
: &DocContext
) -> TypeBinding
{
2895 name
: self.name
.clean(cx
),
2896 ty
: self.ty
.clean(cx
)