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::StructField
::*;
18 pub use self::VariantKind
::*;
19 pub use self::Mutability
::*;
20 pub use self::Import
::*;
21 pub use self::ItemEnum
::*;
22 pub use self::Attribute
::*;
23 pub use self::TyParamBound
::*;
24 pub use self::SelfTy
::*;
25 pub use self::FunctionRetTy
::*;
32 use syntax
::attr
::{AttributeMethods, AttrMetaMethods}
;
34 use syntax
::codemap
::{DUMMY_SP, Pos, Spanned}
;
35 use syntax
::parse
::token
::{self, InternedString, special_idents}
;
38 use rustc_trans
::back
::link
;
39 use rustc
::metadata
::cstore
;
40 use rustc
::metadata
::csearch
;
41 use rustc
::metadata
::decoder
;
42 use rustc
::middle
::def
;
43 use rustc
::middle
::subst
::{self, ParamSpace, VecPerParamSpace}
;
44 use rustc
::middle
::ty
;
45 use rustc
::middle
::stability
;
47 use std
::collections
::HashMap
;
48 use std
::path
::PathBuf
;
56 /// A stable identifier to the particular version of JSON output.
57 /// Increment this when the `Crate` and related structures change.
58 pub const SCHEMA_VERSION
: &'
static str = "0.8.3";
63 // extract the stability index for a node from tcx, if possible
64 fn get_stability(cx
: &DocContext
, def_id
: ast
::DefId
) -> Option
<Stability
> {
65 cx
.tcx_opt().and_then(|tcx
| stability
::lookup(tcx
, def_id
)).clean(cx
)
69 fn clean(&self, cx
: &DocContext
) -> T
;
72 impl<T
: Clean
<U
>, U
> Clean
<Vec
<U
>> for [T
] {
73 fn clean(&self, cx
: &DocContext
) -> Vec
<U
> {
74 self.iter().map(|x
| x
.clean(cx
)).collect()
78 impl<T
: Clean
<U
>, U
> Clean
<VecPerParamSpace
<U
>> for VecPerParamSpace
<T
> {
79 fn clean(&self, cx
: &DocContext
) -> VecPerParamSpace
<U
> {
80 self.map(|x
| x
.clean(cx
))
84 impl<T
: Clean
<U
>, U
> Clean
<U
> for P
<T
> {
85 fn clean(&self, cx
: &DocContext
) -> U
{
90 impl<T
: Clean
<U
>, U
> Clean
<U
> for Rc
<T
> {
91 fn clean(&self, cx
: &DocContext
) -> U
{
96 impl<T
: Clean
<U
>, U
> Clean
<Option
<U
>> for Option
<T
> {
97 fn clean(&self, cx
: &DocContext
) -> Option
<U
> {
100 &Some(ref v
) => Some(v
.clean(cx
))
105 impl<T
, U
> Clean
<U
> for ty
::Binder
<T
> where T
: Clean
<U
> {
106 fn clean(&self, cx
: &DocContext
) -> U
{
111 impl<T
: Clean
<U
>, U
> Clean
<Vec
<U
>> for syntax
::owned_slice
::OwnedSlice
<T
> {
112 fn clean(&self, cx
: &DocContext
) -> Vec
<U
> {
113 self.iter().map(|x
| x
.clean(cx
)).collect()
117 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
121 pub module
: Option
<Item
>,
122 pub externs
: Vec
<(ast
::CrateNum
, ExternalCrate
)>,
123 pub primitives
: Vec
<PrimitiveType
>,
124 pub external_traits
: HashMap
<ast
::DefId
, Trait
>,
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 cx
.sess().cstore
.iter_crate_data(|n
, meta
| {
137 externs
.push((n
, meta
.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 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
{
178 let prim
= match PrimitiveType
::find(&child
.attrs
) {
182 primitives
.push(prim
);
184 source
: Span
::empty(),
185 name
: Some(prim
.to_url_str().to_string()),
186 attrs
: child
.attrs
.clone(),
187 visibility
: Some(ast
::Public
),
189 def_id
: ast_util
::local_def(prim
.to_node_id()),
190 inner
: PrimitiveItem(prim
),
196 let src
= match cx
.input
{
197 Input
::File(ref path
) => path
.clone(),
198 Input
::Str(_
) => PathBuf
::new() // FIXME: this is wrong
202 name
: name
.to_string(),
204 module
: Some(module
),
206 primitives
: primitives
,
207 external_traits
: cx
.external_traits
.borrow_mut().take()
208 .unwrap_or(HashMap
::new()),
213 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
214 pub struct ExternalCrate
{
216 pub attrs
: Vec
<Attribute
>,
217 pub primitives
: Vec
<PrimitiveType
>,
220 impl Clean
<ExternalCrate
> for cstore
::crate_metadata
{
221 fn clean(&self, cx
: &DocContext
) -> ExternalCrate
{
222 let mut primitives
= Vec
::new();
223 cx
.tcx_opt().map(|tcx
| {
224 csearch
::each_top_level_item_of_crate(&tcx
.sess
.cstore
,
227 let did
= match def
{
228 decoder
::DlDef(def
::DefMod(did
)) => did
,
231 let attrs
= inline
::load_attrs(cx
, tcx
, did
);
232 PrimitiveType
::find(&attrs
).map(|prim
| primitives
.push(prim
));
236 name
: self.name
.to_string(),
237 attrs
: decoder
::get_crate_attributes(self.data()).clean(cx
),
238 primitives
: primitives
,
243 /// Anything with a source location and set of attributes and, optionally, a
244 /// name. That is, anything that can be documented. This doesn't correspond
245 /// directly to the AST's concept of an item; it's a strict superset.
246 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
250 /// Not everything has a name. E.g., impls
251 pub name
: Option
<String
>,
252 pub attrs
: Vec
<Attribute
> ,
254 pub visibility
: Option
<Visibility
>,
255 pub def_id
: ast
::DefId
,
256 pub stability
: Option
<Stability
>,
260 /// Finds the `doc` attribute as a List and returns the list of attributes
262 pub fn doc_list
<'a
>(&'a
self) -> Option
<&'a
[Attribute
]> {
263 for attr
in &self.attrs
{
265 List(ref x
, ref list
) if "doc" == *x
=> {
274 /// Finds the `doc` attribute as a NameValue and returns the corresponding
276 pub fn doc_value
<'a
>(&'a
self) -> Option
<&'a
str> {
277 for attr
in &self.attrs
{
279 NameValue(ref x
, ref v
) if "doc" == *x
=> {
288 pub fn is_hidden_from_doc(&self) -> bool
{
289 match self.doc_list() {
293 Word(ref s
) if "hidden" == *s
=> {
305 pub fn is_mod(&self) -> bool
{
306 match self.inner { ModuleItem(..) => true, _ => false }
308 pub fn is_trait(&self) -> bool
{
309 match self.inner { TraitItem(..) => true, _ => false }
311 pub fn is_struct(&self) -> bool
{
312 match self.inner { StructItem(..) => true, _ => false }
314 pub fn is_enum(&self) -> bool
{
315 match self.inner { EnumItem(..) => true, _ => false }
317 pub fn is_fn(&self) -> bool
{
318 match self.inner { FunctionItem(..) => true, _ => false }
321 pub fn stability_class(&self) -> String
{
322 match self.stability
{
324 let mut base
= match s
.level
{
325 attr
::Unstable
=> "unstable".to_string(),
326 attr
::Stable
=> String
::new(),
328 if !s
.deprecated_since
.is_empty() {
329 base
.push_str(" deprecated");
338 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
340 ExternCrateItem(String
, Option
<String
>),
344 FunctionItem(Function
),
346 TypedefItem(Typedef
, bool
/* is associated type */),
348 ConstantItem(Constant
),
351 /// A method signature only. Used for required methods in traits (ie,
352 /// non-default-methods).
353 TyMethodItem(TyMethod
),
354 /// A method with a body.
356 StructFieldItem(StructField
),
357 VariantItem(Variant
),
358 /// `fn`s from an extern block
359 ForeignFunctionItem(Function
),
360 /// `static`s from an extern block
361 ForeignStaticItem(Static
),
363 PrimitiveItem(PrimitiveType
),
364 AssociatedConstItem(Type
, Option
<String
>),
365 AssociatedTypeItem(Vec
<TyParamBound
>, Option
<Type
>),
366 DefaultImplItem(DefaultImpl
),
369 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
371 pub items
: Vec
<Item
>,
375 impl Clean
<Item
> for doctree
::Module
{
376 fn clean(&self, cx
: &DocContext
) -> Item
{
377 let name
= if self.name
.is_some() {
378 self.name
.unwrap().clean(cx
)
383 let mut items
: Vec
<Item
> = vec
![];
384 items
.extend(self.extern_crates
.iter().map(|x
| x
.clean(cx
)));
385 items
.extend(self.imports
.iter().flat_map(|x
| x
.clean(cx
)));
386 items
.extend(self.structs
.iter().map(|x
| x
.clean(cx
)));
387 items
.extend(self.enums
.iter().map(|x
| x
.clean(cx
)));
388 items
.extend(self.fns
.iter().map(|x
| x
.clean(cx
)));
389 items
.extend(self.foreigns
.iter().flat_map(|x
| x
.clean(cx
)));
390 items
.extend(self.mods
.iter().map(|x
| x
.clean(cx
)));
391 items
.extend(self.typedefs
.iter().map(|x
| x
.clean(cx
)));
392 items
.extend(self.statics
.iter().map(|x
| x
.clean(cx
)));
393 items
.extend(self.constants
.iter().map(|x
| x
.clean(cx
)));
394 items
.extend(self.traits
.iter().map(|x
| x
.clean(cx
)));
395 items
.extend(self.impls
.iter().flat_map(|x
| x
.clean(cx
)));
396 items
.extend(self.macros
.iter().map(|x
| x
.clean(cx
)));
397 items
.extend(self.def_traits
.iter().map(|x
| x
.clean(cx
)));
399 // determine if we should display the inner contents or
400 // the outer `mod` item for the source code.
402 let cm
= cx
.sess().codemap();
403 let outer
= cm
.lookup_char_pos(self.where_outer
.lo
);
404 let inner
= cm
.lookup_char_pos(self.where_inner
.lo
);
405 if outer
.file
.start_pos
== inner
.file
.start_pos
{
409 // mod foo; (and a separate FileMap for the contents)
416 attrs
: self.attrs
.clean(cx
),
417 source
: whence
.clean(cx
),
418 visibility
: self.vis
.clean(cx
),
419 stability
: self.stab
.clean(cx
),
420 def_id
: ast_util
::local_def(self.id
),
421 inner
: ModuleItem(Module
{
422 is_crate
: self.is_crate
,
429 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
432 List(String
, Vec
<Attribute
> ),
433 NameValue(String
, String
)
436 impl Clean
<Attribute
> for ast
::MetaItem
{
437 fn clean(&self, cx
: &DocContext
) -> Attribute
{
439 ast
::MetaWord(ref s
) => Word(s
.to_string()),
440 ast
::MetaList(ref s
, ref l
) => {
441 List(s
.to_string(), l
.clean(cx
))
443 ast
::MetaNameValue(ref s
, ref v
) => {
444 NameValue(s
.to_string(), lit_to_string(v
))
450 impl Clean
<Attribute
> for ast
::Attribute
{
451 fn clean(&self, cx
: &DocContext
) -> Attribute
{
452 self.with_desugared_doc(|a
| a
.node
.value
.clean(cx
))
456 // This is a rough approximation that gets us what we want.
457 impl attr
::AttrMetaMethods
for Attribute
{
458 fn name(&self) -> InternedString
{
460 Word(ref n
) | List(ref n
, _
) | NameValue(ref n
, _
) => {
461 token
::intern_and_get_ident(n
)
466 fn value_str(&self) -> Option
<InternedString
> {
468 NameValue(_
, ref v
) => {
469 Some(token
::intern_and_get_ident(v
))
474 fn meta_item_list
<'a
>(&'a
self) -> Option
<&'a
[P
<ast
::MetaItem
>]> { None }
475 fn span(&self) -> codemap
::Span { unimplemented!() }
477 impl<'a
> attr
::AttrMetaMethods
for &'a Attribute
{
478 fn name(&self) -> InternedString { (**self).name() }
479 fn value_str(&self) -> Option
<InternedString
> { (**self).value_str() }
480 fn meta_item_list(&self) -> Option
<&[P
<ast
::MetaItem
>]> { None }
481 fn span(&self) -> codemap
::Span { unimplemented!() }
484 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
488 pub bounds
: Vec
<TyParamBound
>,
489 pub default: Option
<Type
>,
492 impl Clean
<TyParam
> for ast
::TyParam
{
493 fn clean(&self, cx
: &DocContext
) -> TyParam
{
495 name
: self.ident
.clean(cx
),
496 did
: ast
::DefId { krate: ast::LOCAL_CRATE, node: self.id }
,
497 bounds
: self.bounds
.clean(cx
),
498 default: self.default.clean(cx
),
503 impl<'tcx
> Clean
<TyParam
> for ty
::TypeParameterDef
<'tcx
> {
504 fn clean(&self, cx
: &DocContext
) -> TyParam
{
505 cx
.external_typarams
.borrow_mut().as_mut().unwrap()
506 .insert(self.def_id
, self.name
.clean(cx
));
508 name
: self.name
.clean(cx
),
510 bounds
: vec
![], // these are filled in from the where-clauses
511 default: self.default.clean(cx
),
516 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
517 pub enum TyParamBound
{
518 RegionBound(Lifetime
),
519 TraitBound(PolyTrait
, ast
::TraitBoundModifier
)
523 fn maybe_sized(cx
: &DocContext
) -> TyParamBound
{
524 use syntax
::ast
::TraitBoundModifier
as TBM
;
525 let mut sized_bound
= ty
::BoundSized
.clean(cx
);
526 if let TyParamBound
::TraitBound(_
, ref mut tbm
) = sized_bound
{
532 fn is_sized_bound(&self, cx
: &DocContext
) -> bool
{
533 use syntax
::ast
::TraitBoundModifier
as TBM
;
534 if let Some(tcx
) = cx
.tcx_opt() {
535 let sized_did
= match tcx
.lang_items
.sized_trait() {
539 if let TyParamBound
::TraitBound(PolyTrait
{
540 trait_
: Type
::ResolvedPath { did, .. }
, ..
541 }, TBM
::None
) = *self {
542 if did
== sized_did
{
551 impl Clean
<TyParamBound
> for ast
::TyParamBound
{
552 fn clean(&self, cx
: &DocContext
) -> TyParamBound
{
554 ast
::RegionTyParamBound(lt
) => RegionBound(lt
.clean(cx
)),
555 ast
::TraitTyParamBound(ref t
, modifier
) => TraitBound(t
.clean(cx
), modifier
),
560 impl<'tcx
> Clean
<(Vec
<TyParamBound
>, Vec
<TypeBinding
>)> for ty
::ExistentialBounds
<'tcx
> {
561 fn clean(&self, cx
: &DocContext
) -> (Vec
<TyParamBound
>, Vec
<TypeBinding
>) {
562 let mut tp_bounds
= vec
![];
563 self.region_bound
.clean(cx
).map(|b
| tp_bounds
.push(RegionBound(b
)));
564 for bb
in &self.builtin_bounds
{
565 tp_bounds
.push(bb
.clean(cx
));
568 let mut bindings
= vec
![];
569 for &ty
::Binder(ref pb
) in &self.projection_bounds
{
570 bindings
.push(TypeBinding
{
571 name
: pb
.projection_ty
.item_name
.clean(cx
),
576 (tp_bounds
, bindings
)
580 fn external_path_params(cx
: &DocContext
, trait_did
: Option
<ast
::DefId
>,
581 bindings
: Vec
<TypeBinding
>, substs
: &subst
::Substs
) -> PathParameters
{
582 let lifetimes
= substs
.regions().get_slice(subst
::TypeSpace
)
584 .filter_map(|v
| v
.clean(cx
))
586 let types
= substs
.types
.get_slice(subst
::TypeSpace
).to_vec();
588 match (trait_did
, cx
.tcx_opt()) {
589 // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
590 (Some(did
), Some(ref tcx
)) if tcx
.lang_items
.fn_trait_kind(did
).is_some() => {
591 assert_eq
!(types
.len(), 1);
592 let inputs
= match types
[0].sty
{
593 ty
::TyTuple(ref tys
) => tys
.iter().map(|t
| t
.clean(cx
)).collect(),
595 return PathParameters
::AngleBracketed
{
596 lifetimes
: lifetimes
,
597 types
: types
.clean(cx
),
603 // FIXME(#20299) return type comes from a projection now
604 // match types[1].sty {
605 // ty::TyTuple(ref v) if v.is_empty() => None, // -> ()
606 // _ => Some(types[1].clean(cx))
608 PathParameters
::Parenthesized
{
614 PathParameters
::AngleBracketed
{
615 lifetimes
: lifetimes
,
616 types
: types
.clean(cx
),
623 // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
624 // from Fn<(A, B,), C> to Fn(A, B) -> C
625 fn external_path(cx
: &DocContext
, name
: &str, trait_did
: Option
<ast
::DefId
>,
626 bindings
: Vec
<TypeBinding
>, substs
: &subst
::Substs
) -> Path
{
629 segments
: vec
![PathSegment
{
630 name
: name
.to_string(),
631 params
: external_path_params(cx
, trait_did
, bindings
, substs
)
636 impl Clean
<TyParamBound
> for ty
::BuiltinBound
{
637 fn clean(&self, cx
: &DocContext
) -> TyParamBound
{
638 let tcx
= match cx
.tcx_opt() {
640 None
=> return RegionBound(Lifetime
::statik())
642 let empty
= subst
::Substs
::empty();
643 let (did
, path
) = match *self {
645 (tcx
.lang_items
.send_trait().unwrap(),
646 external_path(cx
, "Send", None
, vec
![], &empty
)),
648 (tcx
.lang_items
.sized_trait().unwrap(),
649 external_path(cx
, "Sized", None
, vec
![], &empty
)),
651 (tcx
.lang_items
.copy_trait().unwrap(),
652 external_path(cx
, "Copy", None
, vec
![], &empty
)),
654 (tcx
.lang_items
.sync_trait().unwrap(),
655 external_path(cx
, "Sync", None
, vec
![], &empty
)),
657 let fqn
= csearch
::get_item_path(tcx
, did
);
658 let fqn
= fqn
.into_iter().map(|i
| i
.to_string()).collect();
659 cx
.external_paths
.borrow_mut().as_mut().unwrap().insert(did
,
661 TraitBound(PolyTrait
{
662 trait_
: ResolvedPath
{
669 }, ast
::TraitBoundModifier
::None
)
673 impl<'tcx
> Clean
<TyParamBound
> for ty
::TraitRef
<'tcx
> {
674 fn clean(&self, cx
: &DocContext
) -> TyParamBound
{
675 let tcx
= match cx
.tcx_opt() {
677 None
=> return RegionBound(Lifetime
::statik())
679 let fqn
= csearch
::get_item_path(tcx
, self.def_id
);
680 let fqn
= fqn
.into_iter().map(|i
| i
.to_string())
681 .collect
::<Vec
<String
>>();
682 let path
= external_path(cx
, fqn
.last().unwrap(),
683 Some(self.def_id
), vec
![], self.substs
);
684 cx
.external_paths
.borrow_mut().as_mut().unwrap().insert(self.def_id
,
687 debug
!("ty::TraitRef\n substs.types(TypeSpace): {:?}\n",
688 self.substs
.types
.get_slice(ParamSpace
::TypeSpace
));
690 // collect any late bound regions
691 let mut late_bounds
= vec
![];
692 for &ty_s
in self.substs
.types
.get_slice(ParamSpace
::TypeSpace
) {
693 if let ty
::TyTuple(ref ts
) = ty_s
.sty
{
695 if let ty
::TyRef(ref reg
, _
) = ty_s
.sty
{
696 if let &ty
::Region
::ReLateBound(_
, _
) = *reg
{
697 debug
!(" hit an ReLateBound {:?}", reg
);
698 if let Some(lt
) = reg
.clean(cx
) {
707 TraitBound(PolyTrait
{
708 trait_
: ResolvedPath
{
714 lifetimes
: late_bounds
715 }, ast
::TraitBoundModifier
::None
)
719 impl<'tcx
> Clean
<Option
<Vec
<TyParamBound
>>> for subst
::Substs
<'tcx
> {
720 fn clean(&self, cx
: &DocContext
) -> Option
<Vec
<TyParamBound
>> {
721 let mut v
= Vec
::new();
722 v
.extend(self.regions().iter().filter_map(|r
| r
.clean(cx
)).map(RegionBound
));
723 v
.extend(self.types
.iter().map(|t
| TraitBound(PolyTrait
{
726 }, ast
::TraitBoundModifier
::None
)));
727 if !v
.is_empty() {Some(v)}
else {None}
731 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
732 pub struct Lifetime(String
);
735 pub fn get_ref
<'a
>(&'a
self) -> &'a
str {
736 let Lifetime(ref s
) = *self;
741 pub fn statik() -> Lifetime
{
742 Lifetime("'static".to_string())
746 impl Clean
<Lifetime
> for ast
::Lifetime
{
747 fn clean(&self, _
: &DocContext
) -> Lifetime
{
748 Lifetime(token
::get_name(self.name
).to_string())
752 impl Clean
<Lifetime
> for ast
::LifetimeDef
{
753 fn clean(&self, _
: &DocContext
) -> Lifetime
{
754 Lifetime(token
::get_name(self.lifetime
.name
).to_string())
758 impl Clean
<Lifetime
> for ty
::RegionParameterDef
{
759 fn clean(&self, _
: &DocContext
) -> Lifetime
{
760 Lifetime(token
::get_name(self.name
).to_string())
764 impl Clean
<Option
<Lifetime
>> for ty
::Region
{
765 fn clean(&self, cx
: &DocContext
) -> Option
<Lifetime
> {
767 ty
::ReStatic
=> Some(Lifetime
::statik()),
768 ty
::ReLateBound(_
, ty
::BrNamed(_
, name
)) =>
769 Some(Lifetime(token
::get_name(name
).to_string())),
770 ty
::ReEarlyBound(ref data
) => Some(Lifetime(data
.name
.clean(cx
))),
772 ty
::ReLateBound(..) |
776 ty
::ReEmpty(..) => None
781 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
782 pub enum WherePredicate
{
783 BoundPredicate { ty: Type, bounds: Vec<TyParamBound> }
,
784 RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>}
,
785 EqPredicate { lhs: Type, rhs: Type }
788 impl Clean
<WherePredicate
> for ast
::WherePredicate
{
789 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
791 ast
::WherePredicate
::BoundPredicate(ref wbp
) => {
792 WherePredicate
::BoundPredicate
{
793 ty
: wbp
.bounded_ty
.clean(cx
),
794 bounds
: wbp
.bounds
.clean(cx
)
798 ast
::WherePredicate
::RegionPredicate(ref wrp
) => {
799 WherePredicate
::RegionPredicate
{
800 lifetime
: wrp
.lifetime
.clean(cx
),
801 bounds
: wrp
.bounds
.clean(cx
)
805 ast
::WherePredicate
::EqPredicate(_
) => {
806 unimplemented
!() // FIXME(#20041)
812 impl<'a
> Clean
<WherePredicate
> for ty
::Predicate
<'a
> {
813 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
814 use rustc
::middle
::ty
::Predicate
;
817 Predicate
::Trait(ref pred
) => pred
.clean(cx
),
818 Predicate
::Equate(ref pred
) => pred
.clean(cx
),
819 Predicate
::RegionOutlives(ref pred
) => pred
.clean(cx
),
820 Predicate
::TypeOutlives(ref pred
) => pred
.clean(cx
),
821 Predicate
::Projection(ref pred
) => pred
.clean(cx
)
826 impl<'a
> Clean
<WherePredicate
> for ty
::TraitPredicate
<'a
> {
827 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
828 WherePredicate
::BoundPredicate
{
829 ty
: self.trait_ref
.substs
.self_ty().clean(cx
).unwrap(),
830 bounds
: vec
![self.trait_ref
.clean(cx
)]
835 impl<'tcx
> Clean
<WherePredicate
> for ty
::EquatePredicate
<'tcx
> {
836 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
837 let ty
::EquatePredicate(ref lhs
, ref rhs
) = *self;
838 WherePredicate
::EqPredicate
{
845 impl Clean
<WherePredicate
> for ty
::OutlivesPredicate
<ty
::Region
, ty
::Region
> {
846 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
847 let ty
::OutlivesPredicate(ref a
, ref b
) = *self;
848 WherePredicate
::RegionPredicate
{
849 lifetime
: a
.clean(cx
).unwrap(),
850 bounds
: vec
![b
.clean(cx
).unwrap()]
855 impl<'tcx
> Clean
<WherePredicate
> for ty
::OutlivesPredicate
<ty
::Ty
<'tcx
>, ty
::Region
> {
856 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
857 let ty
::OutlivesPredicate(ref ty
, ref lt
) = *self;
859 WherePredicate
::BoundPredicate
{
861 bounds
: vec
![TyParamBound
::RegionBound(lt
.clean(cx
).unwrap())]
866 impl<'tcx
> Clean
<WherePredicate
> for ty
::ProjectionPredicate
<'tcx
> {
867 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
868 WherePredicate
::EqPredicate
{
869 lhs
: self.projection_ty
.clean(cx
),
870 rhs
: self.ty
.clean(cx
)
875 impl<'tcx
> Clean
<Type
> for ty
::ProjectionTy
<'tcx
> {
876 fn clean(&self, cx
: &DocContext
) -> Type
{
877 let trait_
= match self.trait_ref
.clean(cx
) {
878 TyParamBound
::TraitBound(t
, _
) => t
.trait_
,
879 TyParamBound
::RegionBound(_
) => {
880 panic
!("cleaning a trait got a region")
884 name
: self.item_name
.clean(cx
),
885 self_type
: box self.trait_ref
.self_ty().clean(cx
),
891 // maybe use a Generic enum and use Vec<Generic>?
892 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
893 pub struct Generics
{
894 pub lifetimes
: Vec
<Lifetime
>,
895 pub type_params
: Vec
<TyParam
>,
896 pub where_predicates
: Vec
<WherePredicate
>
899 impl Clean
<Generics
> for ast
::Generics
{
900 fn clean(&self, cx
: &DocContext
) -> Generics
{
902 lifetimes
: self.lifetimes
.clean(cx
),
903 type_params
: self.ty_params
.clean(cx
),
904 where_predicates
: self.where_clause
.predicates
.clean(cx
)
909 impl<'a
, 'tcx
> Clean
<Generics
> for (&'a ty
::Generics
<'tcx
>,
910 &'a ty
::GenericPredicates
<'tcx
>,
912 fn clean(&self, cx
: &DocContext
) -> Generics
{
913 use std
::collections
::HashSet
;
914 use self::WherePredicate
as WP
;
916 let (gens
, preds
, space
) = *self;
918 // Bounds in the type_params and lifetimes fields are repeated in the
919 // predicates field (see rustc_typeck::collect::ty_generics), so remove
921 let stripped_typarams
= gens
.types
.get_slice(space
).iter().map(|tp
| {
923 }).collect
::<Vec
<_
>>();
924 let stripped_lifetimes
= gens
.regions
.get_slice(space
).iter().map(|rp
| {
925 let mut srp
= rp
.clone();
926 srp
.bounds
= Vec
::new();
928 }).collect
::<Vec
<_
>>();
930 let mut where_predicates
= preds
.predicates
.get_slice(space
)
933 // Type parameters and have a Sized bound by default unless removed with
934 // ?Sized. Scan through the predicates and mark any type parameter with
935 // a Sized bound, removing the bounds as we find them.
937 // Note that associated types also have a sized bound by default, but we
938 // don't actually know the set of associated types right here so that's
939 // handled in cleaning associated types
940 let mut sized_params
= HashSet
::new();
941 where_predicates
.retain(|pred
| {
943 WP
::BoundPredicate { ty: Generic(ref g), ref bounds }
=> {
944 if bounds
.iter().any(|b
| b
.is_sized_bound(cx
)) {
945 sized_params
.insert(g
.clone());
955 // Run through the type parameters again and insert a ?Sized
956 // unbound for any we didn't find to be Sized.
957 for tp
in &stripped_typarams
{
958 if !sized_params
.contains(&tp
.name
) {
959 where_predicates
.push(WP
::BoundPredicate
{
960 ty
: Type
::Generic(tp
.name
.clone()),
961 bounds
: vec
![TyParamBound
::maybe_sized(cx
)],
966 // It would be nice to collect all of the bounds on a type and recombine
967 // them if possible, to avoid e.g. `where T: Foo, T: Bar, T: Sized, T: 'a`
968 // and instead see `where T: Foo + Bar + Sized + 'a`
971 type_params
: simplify
::ty_params(stripped_typarams
),
972 lifetimes
: stripped_lifetimes
,
973 where_predicates
: simplify
::where_clauses(cx
, where_predicates
),
978 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
980 pub generics
: Generics
,
982 pub unsafety
: ast
::Unsafety
,
983 pub constness
: ast
::Constness
,
988 impl Clean
<Method
> for ast
::MethodSig
{
989 fn clean(&self, cx
: &DocContext
) -> Method
{
990 let all_inputs
= &self.decl
.inputs
;
991 let inputs
= match self.explicit_self
.node
{
992 ast
::SelfStatic
=> &**all_inputs
,
993 _
=> &all_inputs
[1..]
997 values
: inputs
.clean(cx
),
999 output
: self.decl
.output
.clean(cx
),
1003 generics
: self.generics
.clean(cx
),
1004 self_
: self.explicit_self
.node
.clean(cx
),
1005 unsafety
: self.unsafety
,
1006 constness
: self.constness
,
1013 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1014 pub struct TyMethod
{
1015 pub unsafety
: ast
::Unsafety
,
1017 pub generics
: Generics
,
1022 impl Clean
<TyMethod
> for ast
::MethodSig
{
1023 fn clean(&self, cx
: &DocContext
) -> TyMethod
{
1024 let inputs
= match self.explicit_self
.node
{
1025 ast
::SelfStatic
=> &*self.decl
.inputs
,
1026 _
=> &self.decl
.inputs
[1..]
1030 values
: inputs
.clean(cx
),
1032 output
: self.decl
.output
.clean(cx
),
1036 unsafety
: self.unsafety
.clone(),
1038 self_
: self.explicit_self
.node
.clean(cx
),
1039 generics
: self.generics
.clean(cx
),
1045 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1049 SelfBorrowed(Option
<Lifetime
>, Mutability
),
1053 impl Clean
<SelfTy
> for ast
::ExplicitSelf_
{
1054 fn clean(&self, cx
: &DocContext
) -> SelfTy
{
1056 ast
::SelfStatic
=> SelfStatic
,
1057 ast
::SelfValue(_
) => SelfValue
,
1058 ast
::SelfRegion(ref lt
, ref mt
, _
) => {
1059 SelfBorrowed(lt
.clean(cx
), mt
.clean(cx
))
1061 ast
::SelfExplicit(ref typ
, _
) => SelfExplicit(typ
.clean(cx
)),
1066 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1067 pub struct Function
{
1069 pub generics
: Generics
,
1070 pub unsafety
: ast
::Unsafety
,
1071 pub constness
: ast
::Constness
,
1075 impl Clean
<Item
> for doctree
::Function
{
1076 fn clean(&self, cx
: &DocContext
) -> Item
{
1078 name
: Some(self.name
.clean(cx
)),
1079 attrs
: self.attrs
.clean(cx
),
1080 source
: self.whence
.clean(cx
),
1081 visibility
: self.vis
.clean(cx
),
1082 stability
: self.stab
.clean(cx
),
1083 def_id
: ast_util
::local_def(self.id
),
1084 inner
: FunctionItem(Function
{
1085 decl
: self.decl
.clean(cx
),
1086 generics
: self.generics
.clean(cx
),
1087 unsafety
: self.unsafety
,
1088 constness
: self.constness
,
1095 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1097 pub inputs
: Arguments
,
1098 pub output
: FunctionRetTy
,
1099 pub attrs
: Vec
<Attribute
>,
1102 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1103 pub struct Arguments
{
1104 pub values
: Vec
<Argument
>,
1107 impl Clean
<FnDecl
> for ast
::FnDecl
{
1108 fn clean(&self, cx
: &DocContext
) -> FnDecl
{
1111 values
: self.inputs
.clean(cx
),
1113 output
: self.output
.clean(cx
),
1119 impl<'tcx
> Clean
<Type
> for ty
::FnOutput
<'tcx
> {
1120 fn clean(&self, cx
: &DocContext
) -> Type
{
1122 ty
::FnConverging(ty
) => ty
.clean(cx
),
1123 ty
::FnDiverging
=> Bottom
1128 impl<'a
, 'tcx
> Clean
<FnDecl
> for (ast
::DefId
, &'a ty
::PolyFnSig
<'tcx
>) {
1129 fn clean(&self, cx
: &DocContext
) -> FnDecl
{
1130 let (did
, sig
) = *self;
1131 let mut names
= if did
.node
!= 0 {
1132 csearch
::get_method_arg_names(&cx
.tcx().sess
.cstore
, did
).into_iter()
1134 Vec
::new().into_iter()
1136 if names
.peek().map(|s
| &**s
) == Some("self") {
1137 let _
= names
.next();
1140 output
: Return(sig
.0.output
.clean(cx
)),
1143 values
: sig
.0.inputs
.iter().map(|t
| {
1147 name
: names
.next().unwrap_or("".to_string()),
1155 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1156 pub struct Argument
{
1159 pub id
: ast
::NodeId
,
1162 impl Clean
<Argument
> for ast
::Arg
{
1163 fn clean(&self, cx
: &DocContext
) -> Argument
{
1165 name
: name_from_pat(&*self.pat
),
1166 type_
: (self.ty
.clean(cx
)),
1172 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1173 pub enum FunctionRetTy
{
1179 impl Clean
<FunctionRetTy
> for ast
::FunctionRetTy
{
1180 fn clean(&self, cx
: &DocContext
) -> FunctionRetTy
{
1182 ast
::Return(ref typ
) => Return(typ
.clean(cx
)),
1183 ast
::DefaultReturn(..) => DefaultReturn
,
1184 ast
::NoReturn(..) => NoReturn
1189 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1191 pub unsafety
: ast
::Unsafety
,
1192 pub items
: Vec
<Item
>,
1193 pub generics
: Generics
,
1194 pub bounds
: Vec
<TyParamBound
>,
1197 impl Clean
<Item
> for doctree
::Trait
{
1198 fn clean(&self, cx
: &DocContext
) -> Item
{
1200 name
: Some(self.name
.clean(cx
)),
1201 attrs
: self.attrs
.clean(cx
),
1202 source
: self.whence
.clean(cx
),
1203 def_id
: ast_util
::local_def(self.id
),
1204 visibility
: self.vis
.clean(cx
),
1205 stability
: self.stab
.clean(cx
),
1206 inner
: TraitItem(Trait
{
1207 unsafety
: self.unsafety
,
1208 items
: self.items
.clean(cx
),
1209 generics
: self.generics
.clean(cx
),
1210 bounds
: self.bounds
.clean(cx
),
1216 impl Clean
<Type
> for ast
::TraitRef
{
1217 fn clean(&self, cx
: &DocContext
) -> Type
{
1218 resolve_type(cx
, self.path
.clean(cx
), self.ref_id
)
1222 impl Clean
<PolyTrait
> for ast
::PolyTraitRef
{
1223 fn clean(&self, cx
: &DocContext
) -> PolyTrait
{
1225 trait_
: self.trait_ref
.clean(cx
),
1226 lifetimes
: self.bound_lifetimes
.clean(cx
)
1231 impl Clean
<Item
> for ast
::TraitItem
{
1232 fn clean(&self, cx
: &DocContext
) -> Item
{
1233 let inner
= match self.node
{
1234 ast
::ConstTraitItem(ref ty
, ref default) => {
1235 AssociatedConstItem(ty
.clean(cx
),
1236 default.as_ref().map(|expr
|
1237 expr
.span
.to_src(cx
)))
1239 ast
::MethodTraitItem(ref sig
, Some(_
)) => {
1240 MethodItem(sig
.clean(cx
))
1242 ast
::MethodTraitItem(ref sig
, None
) => {
1243 TyMethodItem(sig
.clean(cx
))
1245 ast
::TypeTraitItem(ref bounds
, ref default) => {
1246 AssociatedTypeItem(bounds
.clean(cx
), default.clean(cx
))
1250 name
: Some(self.ident
.clean(cx
)),
1251 attrs
: self.attrs
.clean(cx
),
1252 source
: self.span
.clean(cx
),
1253 def_id
: ast_util
::local_def(self.id
),
1255 stability
: get_stability(cx
, ast_util
::local_def(self.id
)),
1261 impl Clean
<Item
> for ast
::ImplItem
{
1262 fn clean(&self, cx
: &DocContext
) -> Item
{
1263 let inner
= match self.node
{
1264 ast
::ConstImplItem(ref ty
, ref expr
) => {
1265 ConstantItem(Constant
{
1266 type_
: ty
.clean(cx
),
1267 expr
: expr
.span
.to_src(cx
),
1270 ast
::MethodImplItem(ref sig
, _
) => {
1271 MethodItem(sig
.clean(cx
))
1273 ast
::TypeImplItem(ref ty
) => TypedefItem(Typedef
{
1274 type_
: ty
.clean(cx
),
1275 generics
: Generics
{
1276 lifetimes
: Vec
::new(),
1277 type_params
: Vec
::new(),
1278 where_predicates
: Vec
::new()
1281 ast
::MacImplItem(_
) => {
1283 source
: self.span
.to_src(cx
),
1284 imported_from
: None
,
1289 name
: Some(self.ident
.clean(cx
)),
1290 source
: self.span
.clean(cx
),
1291 attrs
: self.attrs
.clean(cx
),
1292 def_id
: ast_util
::local_def(self.id
),
1293 visibility
: self.vis
.clean(cx
),
1294 stability
: get_stability(cx
, ast_util
::local_def(self.id
)),
1300 impl<'tcx
> Clean
<Item
> for ty
::Method
<'tcx
> {
1301 fn clean(&self, cx
: &DocContext
) -> Item
{
1302 let (self_
, sig
) = match self.explicit_self
{
1303 ty
::StaticExplicitSelfCategory
=> (ast
::SelfStatic
.clean(cx
),
1304 self.fty
.sig
.clone()),
1306 let sig
= ty
::Binder(ty
::FnSig
{
1307 inputs
: self.fty
.sig
.0.inputs
[1..].to_vec(),
1308 ..self.fty
.sig
.0.clone()
1311 ty
::ByValueExplicitSelfCategory
=> SelfValue
,
1312 ty
::ByReferenceExplicitSelfCategory(..) => {
1313 match self.fty
.sig
.0.inputs
[0].sty
{
1314 ty
::TyRef(r
, mt
) => {
1315 SelfBorrowed(r
.clean(cx
), mt
.mutbl
.clean(cx
))
1317 _
=> unreachable
!(),
1320 ty
::ByBoxExplicitSelfCategory
=> {
1321 SelfExplicit(self.fty
.sig
.0.inputs
[0].clean(cx
))
1323 ty
::StaticExplicitSelfCategory
=> unreachable
!(),
1329 let generics
= (&self.generics
, &self.predicates
,
1330 subst
::FnSpace
).clean(cx
);
1331 let decl
= (self.def_id
, &sig
).clean(cx
);
1332 let provided
= match self.container
{
1333 ty
::ImplContainer(..) => false,
1334 ty
::TraitContainer(did
) => {
1335 ty
::provided_trait_methods(cx
.tcx(), did
).iter().any(|m
| {
1336 m
.def_id
== self.def_id
1340 let inner
= if provided
{
1342 unsafety
: self.fty
.unsafety
,
1348 // trait methods canot (currently, at least) be const
1349 constness
: ast
::Constness
::NotConst
,
1352 TyMethodItem(TyMethod
{
1353 unsafety
: self.fty
.unsafety
,
1362 name
: Some(self.name
.clean(cx
)),
1363 visibility
: Some(ast
::Inherited
),
1364 stability
: get_stability(cx
, self.def_id
),
1365 def_id
: self.def_id
,
1366 attrs
: inline
::load_attrs(cx
, cx
.tcx(), self.def_id
),
1367 source
: Span
::empty(),
1373 impl<'tcx
> Clean
<Item
> for ty
::ImplOrTraitItem
<'tcx
> {
1374 fn clean(&self, cx
: &DocContext
) -> Item
{
1376 ty
::ConstTraitItem(ref cti
) => cti
.clean(cx
),
1377 ty
::MethodTraitItem(ref mti
) => mti
.clean(cx
),
1378 ty
::TypeTraitItem(ref tti
) => tti
.clean(cx
),
1383 /// A trait reference, which may have higher ranked lifetimes.
1384 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1385 pub struct PolyTrait
{
1387 pub lifetimes
: Vec
<Lifetime
>
1390 /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
1391 /// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
1392 /// it does not preserve mutability or boxes.
1393 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1395 /// structs/enums/traits (most that'd be an ast::TyPath)
1398 typarams
: Option
<Vec
<TyParamBound
>>,
1400 /// true if is a `T::Name` path for associated types
1403 /// For parameterized types, so the consumer of the JSON don't go
1404 /// looking for types which don't exist anywhere.
1406 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1407 /// arrays, slices, and tuples.
1408 Primitive(PrimitiveType
),
1410 BareFunction(Box
<BareFunctionDecl
>),
1413 FixedVector(Box
<Type
>, String
),
1417 RawPointer(Mutability
, Box
<Type
>),
1419 lifetime
: Option
<Lifetime
>,
1420 mutability
: Mutability
,
1424 // <Type as Trait>::Name
1427 self_type
: Box
<Type
>,
1435 PolyTraitRef(Vec
<TyParamBound
>),
1438 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
1439 pub enum PrimitiveType
{
1440 Isize
, I8
, I16
, I32
, I64
,
1441 Usize
, U8
, U16
, U32
, U64
,
1449 PrimitiveRawPointer
,
1452 #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
1466 pub fn primitive_type(&self) -> Option
<PrimitiveType
> {
1468 Primitive(p
) | BorrowedRef { type_: box Primitive(p), ..}
=> Some(p
),
1469 Vector(..) | BorrowedRef{ type_: box Vector(..), .. }
=> Some(Slice
),
1470 FixedVector(..) | BorrowedRef { type_: box FixedVector(..), .. }
=> {
1473 Tuple(..) => Some(PrimitiveTuple
),
1474 RawPointer(..) => Some(PrimitiveRawPointer
),
1480 impl PrimitiveType
{
1481 fn from_str(s
: &str) -> Option
<PrimitiveType
> {
1483 "isize" => Some(Isize
),
1488 "usize" => Some(Usize
),
1493 "bool" => Some(Bool
),
1494 "char" => Some(Char
),
1498 "array" => Some(Array
),
1499 "slice" => Some(Slice
),
1500 "tuple" => Some(PrimitiveTuple
),
1501 "pointer" => Some(PrimitiveRawPointer
),
1506 fn find(attrs
: &[Attribute
]) -> Option
<PrimitiveType
> {
1508 let list
= match *attr
{
1509 List(ref k
, ref l
) if *k
== "doc" => l
,
1512 for sub_attr
in list
{
1513 let value
= match *sub_attr
{
1514 NameValue(ref k
, ref v
)
1515 if *k
== "primitive" => v
,
1518 match PrimitiveType
::from_str(value
) {
1519 Some(p
) => return Some(p
),
1527 pub fn to_string(&self) -> &'
static str {
1546 PrimitiveTuple
=> "tuple",
1547 PrimitiveRawPointer
=> "pointer",
1551 pub fn to_url_str(&self) -> &'
static str {
1555 /// Creates a rustdoc-specific node id for primitive types.
1557 /// These node ids are generally never used by the AST itself.
1558 pub fn to_node_id(&self) -> ast
::NodeId
{
1559 u32::MAX
- 1 - (*self as u32)
1563 impl Clean
<Type
> for ast
::Ty
{
1564 fn clean(&self, cx
: &DocContext
) -> Type
{
1567 TyPtr(ref m
) => RawPointer(m
.mutbl
.clean(cx
), box m
.ty
.clean(cx
)),
1568 TyRptr(ref l
, ref m
) =>
1569 BorrowedRef
{lifetime
: l
.clean(cx
), mutability
: m
.mutbl
.clean(cx
),
1570 type_
: box m
.ty
.clean(cx
)},
1571 TyVec(ref ty
) => Vector(box ty
.clean(cx
)),
1572 TyFixedLengthVec(ref ty
, ref e
) => FixedVector(box ty
.clean(cx
),
1574 TyTup(ref tys
) => Tuple(tys
.clean(cx
)),
1575 TyPath(None
, ref p
) => {
1576 resolve_type(cx
, p
.clean(cx
), self.id
)
1578 TyPath(Some(ref qself
), ref p
) => {
1579 let mut trait_path
= p
.clone();
1580 trait_path
.segments
.pop();
1582 name
: p
.segments
.last().unwrap().identifier
.clean(cx
),
1583 self_type
: box qself
.ty
.clean(cx
),
1584 trait_
: box resolve_type(cx
, trait_path
.clean(cx
), self.id
)
1587 TyObjectSum(ref lhs
, ref bounds
) => {
1588 let lhs_ty
= lhs
.clean(cx
);
1590 ResolvedPath { path, typarams: None, did, is_generic }
=> {
1593 typarams
: Some(bounds
.clean(cx
)),
1595 is_generic
: is_generic
,
1599 lhs_ty
// shouldn't happen
1603 TyBareFn(ref barefn
) => BareFunction(box barefn
.clean(cx
)),
1604 TyParen(ref ty
) => ty
.clean(cx
),
1605 TyPolyTraitRef(ref bounds
) => {
1606 PolyTraitRef(bounds
.clean(cx
))
1612 panic
!("Unimplemented type {:?}", self.node
)
1618 impl<'tcx
> Clean
<Type
> for ty
::Ty
<'tcx
> {
1619 fn clean(&self, cx
: &DocContext
) -> Type
{
1621 ty
::TyBool
=> Primitive(Bool
),
1622 ty
::TyChar
=> Primitive(Char
),
1623 ty
::TyInt(ast
::TyIs
) => Primitive(Isize
),
1624 ty
::TyInt(ast
::TyI8
) => Primitive(I8
),
1625 ty
::TyInt(ast
::TyI16
) => Primitive(I16
),
1626 ty
::TyInt(ast
::TyI32
) => Primitive(I32
),
1627 ty
::TyInt(ast
::TyI64
) => Primitive(I64
),
1628 ty
::TyUint(ast
::TyUs
) => Primitive(Usize
),
1629 ty
::TyUint(ast
::TyU8
) => Primitive(U8
),
1630 ty
::TyUint(ast
::TyU16
) => Primitive(U16
),
1631 ty
::TyUint(ast
::TyU32
) => Primitive(U32
),
1632 ty
::TyUint(ast
::TyU64
) => Primitive(U64
),
1633 ty
::TyFloat(ast
::TyF32
) => Primitive(F32
),
1634 ty
::TyFloat(ast
::TyF64
) => Primitive(F64
),
1635 ty
::TyStr
=> Primitive(Str
),
1637 let box_did
= cx
.tcx_opt().and_then(|tcx
| {
1638 tcx
.lang_items
.owned_box()
1640 lang_struct(cx
, box_did
, t
, "Box", Unique
)
1642 ty
::TySlice(ty
) => Vector(box ty
.clean(cx
)),
1643 ty
::TyArray(ty
, i
) => FixedVector(box ty
.clean(cx
),
1645 ty
::TyRawPtr(mt
) => RawPointer(mt
.mutbl
.clean(cx
), box mt
.ty
.clean(cx
)),
1646 ty
::TyRef(r
, mt
) => BorrowedRef
{
1647 lifetime
: r
.clean(cx
),
1648 mutability
: mt
.mutbl
.clean(cx
),
1649 type_
: box mt
.ty
.clean(cx
),
1651 ty
::TyBareFn(_
, ref fty
) => BareFunction(box BareFunctionDecl
{
1652 unsafety
: fty
.unsafety
,
1653 generics
: Generics
{
1654 lifetimes
: Vec
::new(),
1655 type_params
: Vec
::new(),
1656 where_predicates
: Vec
::new()
1658 decl
: (ast_util
::local_def(0), &fty
.sig
).clean(cx
),
1659 abi
: fty
.abi
.to_string(),
1661 ty
::TyStruct(did
, substs
) |
1662 ty
::TyEnum(did
, substs
) => {
1663 let fqn
= csearch
::get_item_path(cx
.tcx(), did
);
1664 let fqn
: Vec
<_
> = fqn
.into_iter().map(|i
| i
.to_string()).collect();
1665 let kind
= match self.sty
{
1666 ty
::TyStruct(..) => TypeStruct
,
1669 let path
= external_path(cx
, &fqn
.last().unwrap().to_string(),
1670 None
, vec
![], substs
);
1671 cx
.external_paths
.borrow_mut().as_mut().unwrap().insert(did
, (fqn
, kind
));
1679 ty
::TyTrait(box ty
::TraitTy { ref principal, ref bounds }
) => {
1680 let did
= principal
.def_id();
1681 let fqn
= csearch
::get_item_path(cx
.tcx(), did
);
1682 let fqn
: Vec
<_
> = fqn
.into_iter().map(|i
| i
.to_string()).collect();
1683 let (typarams
, bindings
) = bounds
.clean(cx
);
1684 let path
= external_path(cx
, &fqn
.last().unwrap().to_string(),
1685 Some(did
), bindings
, principal
.substs());
1686 cx
.external_paths
.borrow_mut().as_mut().unwrap().insert(did
, (fqn
, TypeTrait
));
1689 typarams
: Some(typarams
),
1694 ty
::TyTuple(ref t
) => Tuple(t
.clean(cx
)),
1696 ty
::TyProjection(ref data
) => data
.clean(cx
),
1698 ty
::TyParam(ref p
) => Generic(token
::get_name(p
.name
).to_string()),
1700 ty
::TyClosure(..) => Tuple(vec
![]), // FIXME(pcwalton)
1702 ty
::TyInfer(..) => panic
!("TyInfer"),
1703 ty
::TyError
=> panic
!("TyError"),
1708 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1709 pub enum StructField
{
1710 HiddenStructField
, // inserted later by strip passes
1711 TypedStructField(Type
),
1714 impl Clean
<Item
> for ast
::StructField
{
1715 fn clean(&self, cx
: &DocContext
) -> Item
{
1716 let (name
, vis
) = match self.node
.kind
{
1717 ast
::NamedField(id
, vis
) => (Some(id
), vis
),
1718 ast
::UnnamedField(vis
) => (None
, vis
)
1721 name
: name
.clean(cx
),
1722 attrs
: self.node
.attrs
.clean(cx
),
1723 source
: self.span
.clean(cx
),
1724 visibility
: Some(vis
),
1725 stability
: get_stability(cx
, ast_util
::local_def(self.node
.id
)),
1726 def_id
: ast_util
::local_def(self.node
.id
),
1727 inner
: StructFieldItem(TypedStructField(self.node
.ty
.clean(cx
))),
1732 impl Clean
<Item
> for ty
::field_ty
{
1733 fn clean(&self, cx
: &DocContext
) -> Item
{
1734 use syntax
::parse
::token
::special_idents
::unnamed_field
;
1735 use rustc
::metadata
::csearch
;
1737 let attr_map
= csearch
::get_struct_field_attrs(&cx
.tcx().sess
.cstore
, self.id
);
1739 let (name
, attrs
) = if self.name
== unnamed_field
.name
{
1742 (Some(self.name
), Some(attr_map
.get(&self.id
.node
).unwrap()))
1745 let ty
= ty
::lookup_item_type(cx
.tcx(), self.id
);
1748 name
: name
.clean(cx
),
1749 attrs
: attrs
.unwrap_or(&Vec
::new()).clean(cx
),
1750 source
: Span
::empty(),
1751 visibility
: Some(self.vis
),
1752 stability
: get_stability(cx
, self.id
),
1754 inner
: StructFieldItem(TypedStructField(ty
.ty
.clean(cx
))),
1759 pub type Visibility
= ast
::Visibility
;
1761 impl Clean
<Option
<Visibility
>> for ast
::Visibility
{
1762 fn clean(&self, _
: &DocContext
) -> Option
<Visibility
> {
1767 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1769 pub struct_type
: doctree
::StructType
,
1770 pub generics
: Generics
,
1771 pub fields
: Vec
<Item
>,
1772 pub fields_stripped
: bool
,
1775 impl Clean
<Item
> for doctree
::Struct
{
1776 fn clean(&self, cx
: &DocContext
) -> Item
{
1778 name
: Some(self.name
.clean(cx
)),
1779 attrs
: self.attrs
.clean(cx
),
1780 source
: self.whence
.clean(cx
),
1781 def_id
: ast_util
::local_def(self.id
),
1782 visibility
: self.vis
.clean(cx
),
1783 stability
: self.stab
.clean(cx
),
1784 inner
: StructItem(Struct
{
1785 struct_type
: self.struct_type
,
1786 generics
: self.generics
.clean(cx
),
1787 fields
: self.fields
.clean(cx
),
1788 fields_stripped
: false,
1794 /// This is a more limited form of the standard Struct, different in that
1795 /// it lacks the things most items have (name, id, parameterization). Found
1796 /// only as a variant in an enum.
1797 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1798 pub struct VariantStruct
{
1799 pub struct_type
: doctree
::StructType
,
1800 pub fields
: Vec
<Item
>,
1801 pub fields_stripped
: bool
,
1804 impl Clean
<VariantStruct
> for syntax
::ast
::StructDef
{
1805 fn clean(&self, cx
: &DocContext
) -> VariantStruct
{
1807 struct_type
: doctree
::struct_type_from_def(self),
1808 fields
: self.fields
.clean(cx
),
1809 fields_stripped
: false,
1814 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1816 pub variants
: Vec
<Item
>,
1817 pub generics
: Generics
,
1818 pub variants_stripped
: bool
,
1821 impl Clean
<Item
> for doctree
::Enum
{
1822 fn clean(&self, cx
: &DocContext
) -> Item
{
1824 name
: Some(self.name
.clean(cx
)),
1825 attrs
: self.attrs
.clean(cx
),
1826 source
: self.whence
.clean(cx
),
1827 def_id
: ast_util
::local_def(self.id
),
1828 visibility
: self.vis
.clean(cx
),
1829 stability
: self.stab
.clean(cx
),
1830 inner
: EnumItem(Enum
{
1831 variants
: self.variants
.clean(cx
),
1832 generics
: self.generics
.clean(cx
),
1833 variants_stripped
: false,
1839 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1840 pub struct Variant
{
1841 pub kind
: VariantKind
,
1844 impl Clean
<Item
> for doctree
::Variant
{
1845 fn clean(&self, cx
: &DocContext
) -> Item
{
1847 name
: Some(self.name
.clean(cx
)),
1848 attrs
: self.attrs
.clean(cx
),
1849 source
: self.whence
.clean(cx
),
1850 visibility
: self.vis
.clean(cx
),
1851 stability
: self.stab
.clean(cx
),
1852 def_id
: ast_util
::local_def(self.id
),
1853 inner
: VariantItem(Variant
{
1854 kind
: self.kind
.clean(cx
),
1860 impl<'tcx
> Clean
<Item
> for ty
::VariantInfo
<'tcx
> {
1861 fn clean(&self, cx
: &DocContext
) -> Item
{
1862 // use syntax::parse::token::special_idents::unnamed_field;
1863 let kind
= match self.arg_names
.as_ref().map(|s
| &**s
) {
1864 None
| Some([]) if self.args
.is_empty() => CLikeVariant
,
1865 None
| Some([]) => {
1866 TupleVariant(self.args
.clean(cx
))
1869 StructVariant(VariantStruct
{
1870 struct_type
: doctree
::Plain
,
1871 fields_stripped
: false,
1872 fields
: s
.iter().zip(&self.args
).map(|(name
, ty
)| {
1874 source
: Span
::empty(),
1875 name
: Some(name
.clean(cx
)),
1877 visibility
: Some(ast
::Public
),
1878 // FIXME: this is not accurate, we need an id for
1879 // the specific field but we're using the id
1880 // for the whole variant. Thus we read the
1881 // stability from the whole variant as well.
1882 // Struct variants are experimental and need
1883 // more infrastructure work before we can get
1884 // at the needed information here.
1886 stability
: get_stability(cx
, self.id
),
1887 inner
: StructFieldItem(
1888 TypedStructField(ty
.clean(cx
))
1896 name
: Some(self.name
.clean(cx
)),
1897 attrs
: inline
::load_attrs(cx
, cx
.tcx(), self.id
),
1898 source
: Span
::empty(),
1899 visibility
: Some(ast
::Public
),
1901 inner
: VariantItem(Variant { kind: kind }
),
1902 stability
: get_stability(cx
, self.id
),
1907 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1908 pub enum VariantKind
{
1910 TupleVariant(Vec
<Type
>),
1911 StructVariant(VariantStruct
),
1914 impl Clean
<VariantKind
> for ast
::VariantKind
{
1915 fn clean(&self, cx
: &DocContext
) -> VariantKind
{
1917 &ast
::TupleVariantKind(ref args
) => {
1918 if args
.is_empty() {
1921 TupleVariant(args
.iter().map(|x
| x
.ty
.clean(cx
)).collect())
1924 &ast
::StructVariantKind(ref sd
) => StructVariant(sd
.clean(cx
)),
1929 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1931 pub filename
: String
,
1939 fn empty() -> Span
{
1941 filename
: "".to_string(),
1942 loline
: 0, locol
: 0,
1943 hiline
: 0, hicol
: 0,
1948 impl Clean
<Span
> for syntax
::codemap
::Span
{
1949 fn clean(&self, cx
: &DocContext
) -> Span
{
1950 let cm
= cx
.sess().codemap();
1951 let filename
= cm
.span_to_filename(*self);
1952 let lo
= cm
.lookup_char_pos(self.lo
);
1953 let hi
= cm
.lookup_char_pos(self.hi
);
1955 filename
: filename
.to_string(),
1957 locol
: lo
.col
.to_usize(),
1959 hicol
: hi
.col
.to_usize(),
1964 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1967 pub segments
: Vec
<PathSegment
>,
1971 pub fn singleton(name
: String
) -> Path
{
1974 segments
: vec
![PathSegment
{
1976 params
: PathParameters
::AngleBracketed
{
1977 lifetimes
: Vec
::new(),
1979 bindings
: Vec
::new()
1986 impl Clean
<Path
> for ast
::Path
{
1987 fn clean(&self, cx
: &DocContext
) -> Path
{
1989 global
: self.global
,
1990 segments
: self.segments
.clean(cx
),
1995 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1996 pub enum PathParameters
{
1998 lifetimes
: Vec
<Lifetime
>,
2000 bindings
: Vec
<TypeBinding
>
2004 output
: Option
<Type
>
2008 impl Clean
<PathParameters
> for ast
::PathParameters
{
2009 fn clean(&self, cx
: &DocContext
) -> PathParameters
{
2011 ast
::AngleBracketedParameters(ref data
) => {
2012 PathParameters
::AngleBracketed
{
2013 lifetimes
: data
.lifetimes
.clean(cx
),
2014 types
: data
.types
.clean(cx
),
2015 bindings
: data
.bindings
.clean(cx
)
2019 ast
::ParenthesizedParameters(ref data
) => {
2020 PathParameters
::Parenthesized
{
2021 inputs
: data
.inputs
.clean(cx
),
2022 output
: data
.output
.clean(cx
)
2029 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2030 pub struct PathSegment
{
2032 pub params
: PathParameters
2035 impl Clean
<PathSegment
> for ast
::PathSegment
{
2036 fn clean(&self, cx
: &DocContext
) -> PathSegment
{
2038 name
: self.identifier
.clean(cx
),
2039 params
: self.parameters
.clean(cx
)
2044 fn path_to_string(p
: &ast
::Path
) -> String
{
2045 let mut s
= String
::new();
2046 let mut first
= true;
2047 for i
in p
.segments
.iter().map(|x
| token
::get_ident(x
.identifier
)) {
2048 if !first
|| p
.global
{
2058 impl Clean
<String
> for ast
::Ident
{
2059 fn clean(&self, _
: &DocContext
) -> String
{
2060 token
::get_ident(*self).to_string()
2064 impl Clean
<String
> for ast
::Name
{
2065 fn clean(&self, _
: &DocContext
) -> String
{
2066 token
::get_name(*self).to_string()
2070 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2071 pub struct Typedef
{
2073 pub generics
: Generics
,
2076 impl Clean
<Item
> for doctree
::Typedef
{
2077 fn clean(&self, cx
: &DocContext
) -> Item
{
2079 name
: Some(self.name
.clean(cx
)),
2080 attrs
: self.attrs
.clean(cx
),
2081 source
: self.whence
.clean(cx
),
2082 def_id
: ast_util
::local_def(self.id
.clone()),
2083 visibility
: self.vis
.clean(cx
),
2084 stability
: self.stab
.clean(cx
),
2085 inner
: TypedefItem(Typedef
{
2086 type_
: self.ty
.clean(cx
),
2087 generics
: self.gen
.clean(cx
),
2093 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2094 pub struct BareFunctionDecl
{
2095 pub unsafety
: ast
::Unsafety
,
2096 pub generics
: Generics
,
2101 impl Clean
<BareFunctionDecl
> for ast
::BareFnTy
{
2102 fn clean(&self, cx
: &DocContext
) -> BareFunctionDecl
{
2104 unsafety
: self.unsafety
,
2105 generics
: Generics
{
2106 lifetimes
: self.lifetimes
.clean(cx
),
2107 type_params
: Vec
::new(),
2108 where_predicates
: Vec
::new()
2110 decl
: self.decl
.clean(cx
),
2111 abi
: self.abi
.to_string(),
2116 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2119 pub mutability
: Mutability
,
2120 /// It's useful to have the value of a static documented, but I have no
2121 /// desire to represent expressions (that'd basically be all of the AST,
2122 /// which is huge!). So, have a string.
2126 impl Clean
<Item
> for doctree
::Static
{
2127 fn clean(&self, cx
: &DocContext
) -> Item
{
2128 debug
!("cleaning static {}: {:?}", self.name
.clean(cx
), self);
2130 name
: Some(self.name
.clean(cx
)),
2131 attrs
: self.attrs
.clean(cx
),
2132 source
: self.whence
.clean(cx
),
2133 def_id
: ast_util
::local_def(self.id
),
2134 visibility
: self.vis
.clean(cx
),
2135 stability
: self.stab
.clean(cx
),
2136 inner
: StaticItem(Static
{
2137 type_
: self.type_
.clean(cx
),
2138 mutability
: self.mutability
.clean(cx
),
2139 expr
: self.expr
.span
.to_src(cx
),
2145 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2146 pub struct Constant
{
2151 impl Clean
<Item
> for doctree
::Constant
{
2152 fn clean(&self, cx
: &DocContext
) -> Item
{
2154 name
: Some(self.name
.clean(cx
)),
2155 attrs
: self.attrs
.clean(cx
),
2156 source
: self.whence
.clean(cx
),
2157 def_id
: ast_util
::local_def(self.id
),
2158 visibility
: self.vis
.clean(cx
),
2159 stability
: self.stab
.clean(cx
),
2160 inner
: ConstantItem(Constant
{
2161 type_
: self.type_
.clean(cx
),
2162 expr
: self.expr
.span
.to_src(cx
),
2168 #[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)]
2169 pub enum Mutability
{
2174 impl Clean
<Mutability
> for ast
::Mutability
{
2175 fn clean(&self, _
: &DocContext
) -> Mutability
{
2177 &ast
::MutMutable
=> Mutable
,
2178 &ast
::MutImmutable
=> Immutable
,
2183 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)]
2184 pub enum ImplPolarity
{
2189 impl Clean
<ImplPolarity
> for ast
::ImplPolarity
{
2190 fn clean(&self, _
: &DocContext
) -> ImplPolarity
{
2192 &ast
::ImplPolarity
::Positive
=> ImplPolarity
::Positive
,
2193 &ast
::ImplPolarity
::Negative
=> ImplPolarity
::Negative
,
2198 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2200 pub unsafety
: ast
::Unsafety
,
2201 pub generics
: Generics
,
2202 pub trait_
: Option
<Type
>,
2204 pub items
: Vec
<Item
>,
2206 pub polarity
: Option
<ImplPolarity
>,
2209 fn detect_derived
<M
: AttrMetaMethods
>(attrs
: &[M
]) -> bool
{
2210 attr
::contains_name(attrs
, "automatically_derived")
2213 impl Clean
<Vec
<Item
>> for doctree
::Impl
{
2214 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
2215 let mut ret
= Vec
::new();
2216 let trait_
= self.trait_
.clean(cx
);
2217 let items
= self.items
.clean(cx
);
2219 // If this impl block is an implementation of the Deref trait, then we
2220 // need to try inlining the target's inherent impl blocks as well.
2221 if let Some(ResolvedPath { did, .. }
) = trait_
{
2222 if Some(did
) == cx
.deref_trait_did
.get() {
2223 build_deref_target_impls(cx
, &items
, &mut ret
);
2229 attrs
: self.attrs
.clean(cx
),
2230 source
: self.whence
.clean(cx
),
2231 def_id
: ast_util
::local_def(self.id
),
2232 visibility
: self.vis
.clean(cx
),
2233 stability
: self.stab
.clean(cx
),
2234 inner
: ImplItem(Impl
{
2235 unsafety
: self.unsafety
,
2236 generics
: self.generics
.clean(cx
),
2238 for_
: self.for_
.clean(cx
),
2240 derived
: detect_derived(&self.attrs
),
2241 polarity
: Some(self.polarity
.clean(cx
)),
2248 fn build_deref_target_impls(cx
: &DocContext
,
2250 ret
: &mut Vec
<Item
>) {
2251 let tcx
= match cx
.tcx_opt() {
2257 let target
= match item
.inner
{
2258 TypedefItem(ref t
, true) => &t
.type_
,
2261 let primitive
= match *target
{
2262 ResolvedPath { did, .. }
if ast_util
::is_local(did
) => continue,
2263 ResolvedPath { did, .. }
=> {
2264 ret
.extend(inline
::build_impls(cx
, tcx
, did
));
2267 _
=> match target
.primitive_type() {
2272 let did
= match primitive
{
2273 Isize
=> tcx
.lang_items
.isize_impl(),
2274 I8
=> tcx
.lang_items
.i8_impl(),
2275 I16
=> tcx
.lang_items
.i16_impl(),
2276 I32
=> tcx
.lang_items
.i32_impl(),
2277 I64
=> tcx
.lang_items
.i64_impl(),
2278 Usize
=> tcx
.lang_items
.usize_impl(),
2279 U8
=> tcx
.lang_items
.u8_impl(),
2280 U16
=> tcx
.lang_items
.u16_impl(),
2281 U32
=> tcx
.lang_items
.u32_impl(),
2282 U64
=> tcx
.lang_items
.u64_impl(),
2283 F32
=> tcx
.lang_items
.f32_impl(),
2284 F64
=> tcx
.lang_items
.f64_impl(),
2285 Char
=> tcx
.lang_items
.char_impl(),
2287 Str
=> tcx
.lang_items
.str_impl(),
2288 Slice
=> tcx
.lang_items
.slice_impl(),
2289 Array
=> tcx
.lang_items
.slice_impl(),
2290 PrimitiveTuple
=> None
,
2291 PrimitiveRawPointer
=> tcx
.lang_items
.const_ptr_impl(),
2293 if let Some(did
) = did
{
2294 if !ast_util
::is_local(did
) {
2295 inline
::build_impl(cx
, tcx
, did
, ret
);
2301 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2302 pub struct DefaultImpl
{
2303 pub unsafety
: ast
::Unsafety
,
2307 impl Clean
<Item
> for doctree
::DefaultImpl
{
2308 fn clean(&self, cx
: &DocContext
) -> Item
{
2311 attrs
: self.attrs
.clean(cx
),
2312 source
: self.whence
.clean(cx
),
2313 def_id
: ast_util
::local_def(self.id
),
2314 visibility
: Some(ast
::Public
),
2316 inner
: DefaultImplItem(DefaultImpl
{
2317 unsafety
: self.unsafety
,
2318 trait_
: self.trait_
.clean(cx
),
2324 impl Clean
<Item
> for doctree
::ExternCrate
{
2325 fn clean(&self, cx
: &DocContext
) -> Item
{
2328 attrs
: self.attrs
.clean(cx
),
2329 source
: self.whence
.clean(cx
),
2330 def_id
: ast_util
::local_def(0),
2331 visibility
: self.vis
.clean(cx
),
2333 inner
: ExternCrateItem(self.name
.clean(cx
), self.path
.clone())
2338 impl Clean
<Vec
<Item
>> for doctree
::Import
{
2339 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
2340 // We consider inlining the documentation of `pub use` statements, but we
2341 // forcefully don't inline if this is not public or if the
2342 // #[doc(no_inline)] attribute is present.
2343 let denied
= self.vis
!= ast
::Public
|| self.attrs
.iter().any(|a
| {
2344 &a
.name()[..] == "doc" && match a
.meta_item_list() {
2345 Some(l
) => attr
::contains_name(l
, "no_inline"),
2349 let (mut ret
, inner
) = match self.node
{
2350 ast
::ViewPathGlob(ref p
) => {
2351 (vec
![], GlobImport(resolve_use_source(cx
, p
.clean(cx
), self.id
)))
2353 ast
::ViewPathList(ref p
, ref list
) => {
2354 // Attempt to inline all reexported items, but be sure
2355 // to keep any non-inlineable reexports so they can be
2356 // listed in the documentation.
2357 let mut ret
= vec
![];
2358 let remaining
= if !denied
{
2359 let mut remaining
= vec
![];
2361 match inline
::try_inline(cx
, path
.node
.id(), None
) {
2366 remaining
.push(path
.clean(cx
));
2374 if remaining
.is_empty() {
2377 (ret
, ImportList(resolve_use_source(cx
, p
.clean(cx
), self.id
),
2380 ast
::ViewPathSimple(i
, ref p
) => {
2382 match inline
::try_inline(cx
, self.id
, Some(i
)) {
2383 Some(items
) => return items
,
2387 (vec
![], SimpleImport(i
.clean(cx
),
2388 resolve_use_source(cx
, p
.clean(cx
), self.id
)))
2393 attrs
: self.attrs
.clean(cx
),
2394 source
: self.whence
.clean(cx
),
2395 def_id
: ast_util
::local_def(0),
2396 visibility
: self.vis
.clean(cx
),
2398 inner
: ImportItem(inner
)
2404 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2406 // use source as str;
2407 SimpleImport(String
, ImportSource
),
2409 GlobImport(ImportSource
),
2410 // use source::{a, b, c};
2411 ImportList(ImportSource
, Vec
<ViewListIdent
>),
2414 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2415 pub struct ImportSource
{
2417 pub did
: Option
<ast
::DefId
>,
2420 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2421 pub struct ViewListIdent
{
2423 pub source
: Option
<ast
::DefId
>,
2426 impl Clean
<ViewListIdent
> for ast
::PathListItem
{
2427 fn clean(&self, cx
: &DocContext
) -> ViewListIdent
{
2429 ast
::PathListIdent { id, name }
=> ViewListIdent
{
2430 name
: name
.clean(cx
),
2431 source
: resolve_def(cx
, id
)
2433 ast
::PathListMod { id }
=> ViewListIdent
{
2434 name
: "self".to_string(),
2435 source
: resolve_def(cx
, id
)
2441 impl Clean
<Vec
<Item
>> for ast
::ForeignMod
{
2442 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
2443 let mut items
= self.items
.clean(cx
);
2444 for item
in &mut items
{
2446 ForeignFunctionItem(ref mut f
) => f
.abi
= self.abi
,
2454 impl Clean
<Item
> for ast
::ForeignItem
{
2455 fn clean(&self, cx
: &DocContext
) -> Item
{
2456 let inner
= match self.node
{
2457 ast
::ForeignItemFn(ref decl
, ref generics
) => {
2458 ForeignFunctionItem(Function
{
2459 decl
: decl
.clean(cx
),
2460 generics
: generics
.clean(cx
),
2461 unsafety
: ast
::Unsafety
::Unsafe
,
2463 constness
: ast
::Constness
::NotConst
,
2466 ast
::ForeignItemStatic(ref ty
, mutbl
) => {
2467 ForeignStaticItem(Static
{
2468 type_
: ty
.clean(cx
),
2469 mutability
: if mutbl {Mutable}
else {Immutable}
,
2470 expr
: "".to_string(),
2475 name
: Some(self.ident
.clean(cx
)),
2476 attrs
: self.attrs
.clean(cx
),
2477 source
: self.span
.clean(cx
),
2478 def_id
: ast_util
::local_def(self.id
),
2479 visibility
: self.vis
.clean(cx
),
2480 stability
: get_stability(cx
, ast_util
::local_def(self.id
)),
2489 fn to_src(&self, cx
: &DocContext
) -> String
;
2492 impl ToSource
for syntax
::codemap
::Span
{
2493 fn to_src(&self, cx
: &DocContext
) -> String
{
2494 debug
!("converting span {:?} to snippet", self.clean(cx
));
2495 let sn
= match cx
.sess().codemap().span_to_snippet(*self) {
2496 Ok(x
) => x
.to_string(),
2497 Err(_
) => "".to_string()
2499 debug
!("got snippet {}", sn
);
2504 fn lit_to_string(lit
: &ast
::Lit
) -> String
{
2506 ast
::LitStr(ref st
, _
) => st
.to_string(),
2507 ast
::LitBinary(ref data
) => format
!("{:?}", data
),
2508 ast
::LitByte(b
) => {
2509 let mut res
= String
::from("b'");
2510 for c
in (b
as char).escape_default() {
2516 ast
::LitChar(c
) => format
!("'{}'", c
),
2517 ast
::LitInt(i
, _t
) => i
.to_string(),
2518 ast
::LitFloat(ref f
, _t
) => f
.to_string(),
2519 ast
::LitFloatUnsuffixed(ref f
) => f
.to_string(),
2520 ast
::LitBool(b
) => b
.to_string(),
2524 fn name_from_pat(p
: &ast
::Pat
) -> String
{
2526 debug
!("Trying to get a name from pattern: {:?}", p
);
2529 PatWild(PatWildSingle
) => "_".to_string(),
2530 PatWild(PatWildMulti
) => "..".to_string(),
2531 PatIdent(_
, ref p
, _
) => token
::get_ident(p
.node
).to_string(),
2532 PatEnum(ref p
, _
) => path_to_string(p
),
2533 PatQPath(..) => panic
!("tried to get argument name from PatQPath, \
2534 which is not allowed in function arguments"),
2535 PatStruct(ref name
, ref fields
, etc
) => {
2536 format
!("{} {{ {}{} }}", path_to_string(name
),
2537 fields
.iter().map(|&Spanned { node: ref fp, .. }
|
2538 format
!("{}: {}", fp
.ident
.as_str(), name_from_pat(&*fp
.pat
)))
2539 .collect
::<Vec
<String
>>().connect(", "),
2540 if etc { ", ..." }
else { "" }
2543 PatTup(ref elts
) => format
!("({})", elts
.iter().map(|p
| name_from_pat(&**p
))
2544 .collect
::<Vec
<String
>>().connect(", ")),
2545 PatBox(ref p
) => name_from_pat(&**p
),
2546 PatRegion(ref p
, _
) => name_from_pat(&**p
),
2548 warn
!("tried to get argument name from PatLit, \
2549 which is silly in function arguments");
2552 PatRange(..) => panic
!("tried to get argument name from PatRange, \
2553 which is not allowed in function arguments"),
2554 PatVec(ref begin
, ref mid
, ref end
) => {
2555 let begin
= begin
.iter().map(|p
| name_from_pat(&**p
));
2556 let mid
= mid
.as_ref().map(|p
| format
!("..{}", name_from_pat(&**p
))).into_iter();
2557 let end
= end
.iter().map(|p
| name_from_pat(&**p
));
2558 format
!("[{}]", begin
.chain(mid
).chain(end
).collect
::<Vec
<_
>>().connect(", "))
2561 warn
!("can't document the name of a function argument \
2562 produced by a pattern macro");
2563 "(argument produced by macro)".to_string()
2568 /// Given a Type, resolve it using the def_map
2569 fn resolve_type(cx
: &DocContext
,
2571 id
: ast
::NodeId
) -> Type
{
2572 let tcx
= match cx
.tcx_opt() {
2574 // If we're extracting tests, this return value doesn't matter.
2575 None
=> return Primitive(Bool
),
2577 debug
!("searching for {} in defmap", id
);
2578 let def
= match tcx
.def_map
.borrow().get(&id
) {
2579 Some(k
) => k
.full_def(),
2580 None
=> panic
!("unresolved id not in defmap")
2583 let is_generic
= match def
{
2584 def
::DefPrimTy(p
) => match p
{
2585 ast
::TyStr
=> return Primitive(Str
),
2586 ast
::TyBool
=> return Primitive(Bool
),
2587 ast
::TyChar
=> return Primitive(Char
),
2588 ast
::TyInt(ast
::TyIs
) => return Primitive(Isize
),
2589 ast
::TyInt(ast
::TyI8
) => return Primitive(I8
),
2590 ast
::TyInt(ast
::TyI16
) => return Primitive(I16
),
2591 ast
::TyInt(ast
::TyI32
) => return Primitive(I32
),
2592 ast
::TyInt(ast
::TyI64
) => return Primitive(I64
),
2593 ast
::TyUint(ast
::TyUs
) => return Primitive(Usize
),
2594 ast
::TyUint(ast
::TyU8
) => return Primitive(U8
),
2595 ast
::TyUint(ast
::TyU16
) => return Primitive(U16
),
2596 ast
::TyUint(ast
::TyU32
) => return Primitive(U32
),
2597 ast
::TyUint(ast
::TyU64
) => return Primitive(U64
),
2598 ast
::TyFloat(ast
::TyF32
) => return Primitive(F32
),
2599 ast
::TyFloat(ast
::TyF64
) => return Primitive(F64
),
2601 def
::DefSelfTy(..) if path
.segments
.len() == 1 => {
2602 return Generic(token
::get_name(special_idents
::type_self
.name
).to_string());
2604 def
::DefSelfTy(..) | def
::DefTyParam(..) => true,
2607 let did
= register_def(&*cx
, def
);
2608 ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic }
2611 fn register_def(cx
: &DocContext
, def
: def
::Def
) -> ast
::DefId
{
2612 let (did
, kind
) = match def
{
2613 def
::DefFn(i
, _
) => (i
, TypeFunction
),
2614 def
::DefTy(i
, false) => (i
, TypeTypedef
),
2615 def
::DefTy(i
, true) => (i
, TypeEnum
),
2616 def
::DefTrait(i
) => (i
, TypeTrait
),
2617 def
::DefStruct(i
) => (i
, TypeStruct
),
2618 def
::DefMod(i
) => (i
, TypeModule
),
2619 def
::DefStatic(i
, _
) => (i
, TypeStatic
),
2620 def
::DefVariant(i
, _
, _
) => (i
, TypeEnum
),
2621 _
=> return def
.def_id()
2623 if ast_util
::is_local(did
) { return did }
2624 let tcx
= match cx
.tcx_opt() {
2628 inline
::record_extern_fqn(cx
, did
, kind
);
2629 if let TypeTrait
= kind
{
2630 let t
= inline
::build_external_trait(cx
, tcx
, did
);
2631 cx
.external_traits
.borrow_mut().as_mut().unwrap().insert(did
, t
);
2636 fn resolve_use_source(cx
: &DocContext
, path
: Path
, id
: ast
::NodeId
) -> ImportSource
{
2639 did
: resolve_def(cx
, id
),
2643 fn resolve_def(cx
: &DocContext
, id
: ast
::NodeId
) -> Option
<ast
::DefId
> {
2644 cx
.tcx_opt().and_then(|tcx
| {
2645 tcx
.def_map
.borrow().get(&id
).map(|d
| register_def(cx
, d
.full_def()))
2649 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2652 pub imported_from
: Option
<String
>,
2655 impl Clean
<Item
> for doctree
::Macro
{
2656 fn clean(&self, cx
: &DocContext
) -> Item
{
2658 name
: Some(format
!("{}!", self.name
.clean(cx
))),
2659 attrs
: self.attrs
.clean(cx
),
2660 source
: self.whence
.clean(cx
),
2661 visibility
: ast
::Public
.clean(cx
),
2662 stability
: self.stab
.clean(cx
),
2663 def_id
: ast_util
::local_def(self.id
),
2664 inner
: MacroItem(Macro
{
2665 source
: self.whence
.to_src(cx
),
2666 imported_from
: self.imported_from
.clean(cx
),
2672 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2673 pub struct Stability
{
2674 pub level
: attr
::StabilityLevel
,
2675 pub feature
: String
,
2677 pub deprecated_since
: String
,
2681 impl Clean
<Stability
> for attr
::Stability
{
2682 fn clean(&self, _
: &DocContext
) -> Stability
{
2685 feature
: self.feature
.to_string(),
2686 since
: self.since
.as_ref().map_or("".to_string(),
2687 |interned
| interned
.to_string()),
2688 deprecated_since
: self.deprecated_since
.as_ref().map_or("".to_string(),
2689 |istr
| istr
.to_string()),
2690 reason
: self.reason
.as_ref().map_or("".to_string(),
2691 |interned
| interned
.to_string()),
2696 impl<'a
> Clean
<Stability
> for &'a attr
::Stability
{
2697 fn clean(&self, _
: &DocContext
) -> Stability
{
2700 feature
: self.feature
.to_string(),
2701 since
: self.since
.as_ref().map_or("".to_string(),
2702 |interned
| interned
.to_string()),
2703 deprecated_since
: self.deprecated_since
.as_ref().map_or("".to_string(),
2704 |istr
| istr
.to_string()),
2705 reason
: self.reason
.as_ref().map_or("".to_string(),
2706 |interned
| interned
.to_string()),
2711 impl<'tcx
> Clean
<Item
> for ty
::AssociatedConst
<'tcx
> {
2712 fn clean(&self, cx
: &DocContext
) -> Item
{
2714 source
: DUMMY_SP
.clean(cx
),
2715 name
: Some(self.name
.clean(cx
)),
2717 inner
: AssociatedConstItem(self.ty
.clean(cx
), None
),
2719 def_id
: self.def_id
,
2725 impl<'tcx
> Clean
<Item
> for ty
::AssociatedType
<'tcx
> {
2726 fn clean(&self, cx
: &DocContext
) -> Item
{
2727 let my_name
= self.name
.clean(cx
);
2729 let mut bounds
= if let ty
::TraitContainer(did
) = self.container
{
2730 // When loading a cross-crate associated type, the bounds for this type
2731 // are actually located on the trait/impl itself, so we need to load
2732 // all of the generics from there and then look for bounds that are
2733 // applied to this associated type in question.
2734 let def
= ty
::lookup_trait_def(cx
.tcx(), did
);
2735 let predicates
= ty
::lookup_predicates(cx
.tcx(), did
);
2736 let generics
= (&def
.generics
, &predicates
, subst
::TypeSpace
).clean(cx
);
2737 generics
.where_predicates
.iter().filter_map(|pred
| {
2738 let (name
, self_type
, trait_
, bounds
) = match *pred
{
2739 WherePredicate
::BoundPredicate
{
2740 ty
: QPath { ref name, ref self_type, ref trait_ }
,
2742 } => (name
, self_type
, trait_
, bounds
),
2745 if *name
!= my_name { return None }
2747 ResolvedPath { did, .. }
if did
== self.container
.id() => {}
2751 Generic(ref s
) if *s
== "Self" => {}
2755 }).flat_map(|i
| i
.iter().cloned()).collect
::<Vec
<_
>>()
2760 // Our Sized/?Sized bound didn't get handled when creating the generics
2761 // because we didn't actually get our whole set of bounds until just now
2762 // (some of them may have come from the trait). If we do have a sized
2763 // bound, we remove it, and if we don't then we add the `?Sized` bound
2765 match bounds
.iter().position(|b
| b
.is_sized_bound(cx
)) {
2766 Some(i
) => { bounds.remove(i); }
2767 None
=> bounds
.push(TyParamBound
::maybe_sized(cx
)),
2771 source
: DUMMY_SP
.clean(cx
),
2772 name
: Some(self.name
.clean(cx
)),
2773 attrs
: inline
::load_attrs(cx
, cx
.tcx(), self.def_id
),
2774 inner
: AssociatedTypeItem(bounds
, self.ty
.clean(cx
)),
2775 visibility
: self.vis
.clean(cx
),
2776 def_id
: self.def_id
,
2777 stability
: stability
::lookup(cx
.tcx(), self.def_id
).clean(cx
),
2782 impl<'a
> Clean
<Typedef
> for (ty
::TypeScheme
<'a
>, ty
::GenericPredicates
<'a
>,
2784 fn clean(&self, cx
: &DocContext
) -> Typedef
{
2785 let (ref ty_scheme
, ref predicates
, ps
) = *self;
2787 type_
: ty_scheme
.ty
.clean(cx
),
2788 generics
: (&ty_scheme
.generics
, predicates
, ps
).clean(cx
)
2793 fn lang_struct(cx
: &DocContext
, did
: Option
<ast
::DefId
>,
2794 t
: ty
::Ty
, name
: &str,
2795 fallback
: fn(Box
<Type
>) -> Type
) -> Type
{
2796 let did
= match did
{
2798 None
=> return fallback(box t
.clean(cx
)),
2800 let fqn
= csearch
::get_item_path(cx
.tcx(), did
);
2801 let fqn
: Vec
<String
> = fqn
.into_iter().map(|i
| {
2804 cx
.external_paths
.borrow_mut().as_mut().unwrap().insert(did
, (fqn
, TypeStruct
));
2810 segments
: vec
![PathSegment
{
2811 name
: name
.to_string(),
2812 params
: PathParameters
::AngleBracketed
{
2814 types
: vec
![t
.clean(cx
)],
2823 /// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
2824 #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)]
2825 pub struct TypeBinding
{
2830 impl Clean
<TypeBinding
> for ast
::TypeBinding
{
2831 fn clean(&self, cx
: &DocContext
) -> TypeBinding
{
2833 name
: self.ident
.clean(cx
),
2834 ty
: self.ty
.clean(cx
)