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 static 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 let mut externs
= Vec
::new();
132 cx
.sess().cstore
.iter_crate_data(|n
, meta
| {
133 externs
.push((n
, meta
.clean(cx
)));
135 externs
.sort_by(|&(a
, _
), &(b
, _
)| a
.cmp(&b
));
137 // Figure out the name of this crate
138 let input
= &cx
.input
;
139 let name
= link
::find_crate_name(None
, &self.attrs
, input
);
141 // Clean the crate, translating the entire libsyntax AST to one that is
142 // understood by rustdoc.
143 let mut module
= self.module
.clean(cx
);
145 // Collect all inner modules which are tagged as implementations of
148 // Note that this loop only searches the top-level items of the crate,
149 // and this is intentional. If we were to search the entire crate for an
150 // item tagged with `#[doc(primitive)]` then we we would also have to
151 // search the entirety of external modules for items tagged
152 // `#[doc(primitive)]`, which is a pretty inefficient process (decoding
153 // all that metadata unconditionally).
155 // In order to keep the metadata load under control, the
156 // `#[doc(primitive)]` feature is explicitly designed to only allow the
157 // primitive tags to show up as the top level items in a crate.
159 // Also note that this does not attempt to deal with modules tagged
160 // duplicately for the same primitive. This is handled later on when
161 // rendering by delegating everything to a hash map.
162 let mut primitives
= Vec
::new();
164 let m
= match module
.inner
{
165 ModuleItem(ref mut m
) => m
,
168 let mut tmp
= Vec
::new();
169 for child
in &mut m
.items
{
174 let prim
= match PrimitiveType
::find(&child
.attrs
) {
178 primitives
.push(prim
);
180 source
: Span
::empty(),
181 name
: Some(prim
.to_url_str().to_string()),
182 attrs
: child
.attrs
.clone(),
183 visibility
: Some(ast
::Public
),
185 def_id
: ast_util
::local_def(prim
.to_node_id()),
186 inner
: PrimitiveItem(prim
),
189 m
.items
.extend(tmp
.into_iter());
192 let src
= match cx
.input
{
193 Input
::File(ref path
) => path
.clone(),
194 Input
::Str(_
) => PathBuf
::new() // FIXME: this is wrong
198 name
: name
.to_string(),
200 module
: Some(module
),
202 primitives
: primitives
,
203 external_traits
: cx
.external_traits
.borrow_mut().take()
204 .unwrap_or(HashMap
::new()),
209 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
210 pub struct ExternalCrate
{
212 pub attrs
: Vec
<Attribute
>,
213 pub primitives
: Vec
<PrimitiveType
>,
216 impl Clean
<ExternalCrate
> for cstore
::crate_metadata
{
217 fn clean(&self, cx
: &DocContext
) -> ExternalCrate
{
218 let mut primitives
= Vec
::new();
219 cx
.tcx_opt().map(|tcx
| {
220 csearch
::each_top_level_item_of_crate(&tcx
.sess
.cstore
,
223 let did
= match def
{
224 decoder
::DlDef(def
::DefMod(did
)) => did
,
227 let attrs
= inline
::load_attrs(cx
, tcx
, did
);
228 PrimitiveType
::find(&attrs
).map(|prim
| primitives
.push(prim
));
232 name
: self.name
.to_string(),
233 attrs
: decoder
::get_crate_attributes(self.data()).clean(cx
),
234 primitives
: primitives
,
239 /// Anything with a source location and set of attributes and, optionally, a
240 /// name. That is, anything that can be documented. This doesn't correspond
241 /// directly to the AST's concept of an item; it's a strict superset.
242 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
246 /// Not everything has a name. E.g., impls
247 pub name
: Option
<String
>,
248 pub attrs
: Vec
<Attribute
> ,
250 pub visibility
: Option
<Visibility
>,
251 pub def_id
: ast
::DefId
,
252 pub stability
: Option
<Stability
>,
256 /// Finds the `doc` attribute as a List and returns the list of attributes
258 pub fn doc_list
<'a
>(&'a
self) -> Option
<&'a
[Attribute
]> {
259 for attr
in &self.attrs
{
261 List(ref x
, ref list
) if "doc" == *x
=> {
270 /// Finds the `doc` attribute as a NameValue and returns the corresponding
272 pub fn doc_value
<'a
>(&'a
self) -> Option
<&'a
str> {
273 for attr
in &self.attrs
{
275 NameValue(ref x
, ref v
) if "doc" == *x
=> {
284 pub fn is_hidden_from_doc(&self) -> bool
{
285 match self.doc_list() {
289 Word(ref s
) if "hidden" == *s
=> {
301 pub fn is_mod(&self) -> bool
{
302 match self.inner { ModuleItem(..) => true, _ => false }
304 pub fn is_trait(&self) -> bool
{
305 match self.inner { TraitItem(..) => true, _ => false }
307 pub fn is_struct(&self) -> bool
{
308 match self.inner { StructItem(..) => true, _ => false }
310 pub fn is_enum(&self) -> bool
{
311 match self.inner { EnumItem(..) => true, _ => false }
313 pub fn is_fn(&self) -> bool
{
314 match self.inner { FunctionItem(..) => true, _ => false }
318 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
320 ExternCrateItem(String
, Option
<String
>),
324 FunctionItem(Function
),
326 TypedefItem(Typedef
),
328 ConstantItem(Constant
),
331 /// A method signature only. Used for required methods in traits (ie,
332 /// non-default-methods).
333 TyMethodItem(TyMethod
),
334 /// A method with a body.
336 StructFieldItem(StructField
),
337 VariantItem(Variant
),
338 /// `fn`s from an extern block
339 ForeignFunctionItem(Function
),
340 /// `static`s from an extern block
341 ForeignStaticItem(Static
),
343 PrimitiveItem(PrimitiveType
),
344 AssociatedTypeItem(Vec
<TyParamBound
>, Option
<Type
>),
345 DefaultImplItem(DefaultImpl
),
348 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
350 pub items
: Vec
<Item
>,
354 impl Clean
<Item
> for doctree
::Module
{
355 fn clean(&self, cx
: &DocContext
) -> Item
{
356 let name
= if self.name
.is_some() {
357 self.name
.unwrap().clean(cx
)
362 let mut items
: Vec
<Item
> = vec
![];
363 items
.extend(self.extern_crates
.iter().map(|x
| x
.clean(cx
)));
364 items
.extend(self.imports
.iter().flat_map(|x
| x
.clean(cx
).into_iter()));
365 items
.extend(self.structs
.iter().map(|x
| x
.clean(cx
)));
366 items
.extend(self.enums
.iter().map(|x
| x
.clean(cx
)));
367 items
.extend(self.fns
.iter().map(|x
| x
.clean(cx
)));
368 items
.extend(self.foreigns
.iter().flat_map(|x
| x
.clean(cx
).into_iter()));
369 items
.extend(self.mods
.iter().map(|x
| x
.clean(cx
)));
370 items
.extend(self.typedefs
.iter().map(|x
| x
.clean(cx
)));
371 items
.extend(self.statics
.iter().map(|x
| x
.clean(cx
)));
372 items
.extend(self.constants
.iter().map(|x
| x
.clean(cx
)));
373 items
.extend(self.traits
.iter().map(|x
| x
.clean(cx
)));
374 items
.extend(self.impls
.iter().map(|x
| x
.clean(cx
)));
375 items
.extend(self.macros
.iter().map(|x
| x
.clean(cx
)));
376 items
.extend(self.def_traits
.iter().map(|x
| x
.clean(cx
)));
378 // determine if we should display the inner contents or
379 // the outer `mod` item for the source code.
381 let cm
= cx
.sess().codemap();
382 let outer
= cm
.lookup_char_pos(self.where_outer
.lo
);
383 let inner
= cm
.lookup_char_pos(self.where_inner
.lo
);
384 if outer
.file
.start_pos
== inner
.file
.start_pos
{
388 // mod foo; (and a separate FileMap for the contents)
395 attrs
: self.attrs
.clean(cx
),
396 source
: whence
.clean(cx
),
397 visibility
: self.vis
.clean(cx
),
398 stability
: self.stab
.clean(cx
),
399 def_id
: ast_util
::local_def(self.id
),
400 inner
: ModuleItem(Module
{
401 is_crate
: self.is_crate
,
408 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
411 List(String
, Vec
<Attribute
> ),
412 NameValue(String
, String
)
415 impl Clean
<Attribute
> for ast
::MetaItem
{
416 fn clean(&self, cx
: &DocContext
) -> Attribute
{
418 ast
::MetaWord(ref s
) => Word(s
.to_string()),
419 ast
::MetaList(ref s
, ref l
) => {
420 List(s
.to_string(), l
.clean(cx
))
422 ast
::MetaNameValue(ref s
, ref v
) => {
423 NameValue(s
.to_string(), lit_to_string(v
))
429 impl Clean
<Attribute
> for ast
::Attribute
{
430 fn clean(&self, cx
: &DocContext
) -> Attribute
{
431 self.with_desugared_doc(|a
| a
.node
.value
.clean(cx
))
435 // This is a rough approximation that gets us what we want.
436 impl attr
::AttrMetaMethods
for Attribute
{
437 fn name(&self) -> InternedString
{
439 Word(ref n
) | List(ref n
, _
) | NameValue(ref n
, _
) => {
440 token
::intern_and_get_ident(n
)
445 fn value_str(&self) -> Option
<InternedString
> {
447 NameValue(_
, ref v
) => {
448 Some(token
::intern_and_get_ident(v
))
453 fn meta_item_list
<'a
>(&'a
self) -> Option
<&'a
[P
<ast
::MetaItem
>]> { None }
454 fn span(&self) -> codemap
::Span { unimplemented!() }
456 impl<'a
> attr
::AttrMetaMethods
for &'a Attribute
{
457 fn name(&self) -> InternedString { (**self).name() }
458 fn value_str(&self) -> Option
<InternedString
> { (**self).value_str() }
459 fn meta_item_list(&self) -> Option
<&[P
<ast
::MetaItem
>]> { None }
460 fn span(&self) -> codemap
::Span { unimplemented!() }
463 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
467 pub bounds
: Vec
<TyParamBound
>,
468 pub default: Option
<Type
>,
471 impl Clean
<TyParam
> for ast
::TyParam
{
472 fn clean(&self, cx
: &DocContext
) -> TyParam
{
474 name
: self.ident
.clean(cx
),
475 did
: ast
::DefId { krate: ast::LOCAL_CRATE, node: self.id }
,
476 bounds
: self.bounds
.clean(cx
),
477 default: self.default.clean(cx
),
482 impl<'tcx
> Clean
<TyParam
> for ty
::TypeParameterDef
<'tcx
> {
483 fn clean(&self, cx
: &DocContext
) -> TyParam
{
484 cx
.external_typarams
.borrow_mut().as_mut().unwrap()
485 .insert(self.def_id
, self.name
.clean(cx
));
487 name
: self.name
.clean(cx
),
489 bounds
: vec
![], // these are filled in from the where-clauses
490 default: self.default.clean(cx
),
495 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
496 pub enum TyParamBound
{
497 RegionBound(Lifetime
),
498 TraitBound(PolyTrait
, ast
::TraitBoundModifier
)
502 fn maybe_sized(cx
: &DocContext
) -> TyParamBound
{
503 use syntax
::ast
::TraitBoundModifier
as TBM
;
504 let mut sized_bound
= ty
::BuiltinBound
::BoundSized
.clean(cx
);
505 if let TyParamBound
::TraitBound(_
, ref mut tbm
) = sized_bound
{
511 fn is_sized_bound(&self, cx
: &DocContext
) -> bool
{
512 use syntax
::ast
::TraitBoundModifier
as TBM
;
513 if let Some(tcx
) = cx
.tcx_opt() {
514 let sized_did
= match tcx
.lang_items
.sized_trait() {
518 if let TyParamBound
::TraitBound(PolyTrait
{
519 trait_
: Type
::ResolvedPath { did, .. }
, ..
520 }, TBM
::None
) = *self {
521 if did
== sized_did
{
530 impl Clean
<TyParamBound
> for ast
::TyParamBound
{
531 fn clean(&self, cx
: &DocContext
) -> TyParamBound
{
533 ast
::RegionTyParamBound(lt
) => RegionBound(lt
.clean(cx
)),
534 ast
::TraitTyParamBound(ref t
, modifier
) => TraitBound(t
.clean(cx
), modifier
),
539 impl<'tcx
> Clean
<(Vec
<TyParamBound
>, Vec
<TypeBinding
>)> for ty
::ExistentialBounds
<'tcx
> {
540 fn clean(&self, cx
: &DocContext
) -> (Vec
<TyParamBound
>, Vec
<TypeBinding
>) {
541 let mut tp_bounds
= vec
![];
542 self.region_bound
.clean(cx
).map(|b
| tp_bounds
.push(RegionBound(b
)));
543 for bb
in &self.builtin_bounds
{
544 tp_bounds
.push(bb
.clean(cx
));
547 let mut bindings
= vec
![];
548 for &ty
::Binder(ref pb
) in &self.projection_bounds
{
549 bindings
.push(TypeBinding
{
550 name
: pb
.projection_ty
.item_name
.clean(cx
),
555 (tp_bounds
, bindings
)
559 fn external_path_params(cx
: &DocContext
, trait_did
: Option
<ast
::DefId
>,
560 bindings
: Vec
<TypeBinding
>, substs
: &subst
::Substs
) -> PathParameters
{
561 use rustc
::middle
::ty
::sty
;
562 let lifetimes
= substs
.regions().get_slice(subst
::TypeSpace
)
564 .filter_map(|v
| v
.clean(cx
))
566 let types
= substs
.types
.get_slice(subst
::TypeSpace
).to_vec();
568 match (trait_did
, cx
.tcx_opt()) {
569 // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C
570 (Some(did
), Some(ref tcx
)) if tcx
.lang_items
.fn_trait_kind(did
).is_some() => {
571 assert_eq
!(types
.len(), 1);
572 let inputs
= match types
[0].sty
{
573 sty
::ty_tup(ref tys
) => tys
.iter().map(|t
| t
.clean(cx
)).collect(),
575 return PathParameters
::AngleBracketed
{
576 lifetimes
: lifetimes
,
577 types
: types
.clean(cx
),
583 // FIXME(#20299) return type comes from a projection now
584 // match types[1].sty {
585 // sty::ty_tup(ref v) if v.is_empty() => None, // -> ()
586 // _ => Some(types[1].clean(cx))
588 PathParameters
::Parenthesized
{
594 PathParameters
::AngleBracketed
{
595 lifetimes
: lifetimes
,
596 types
: types
.clean(cx
),
603 // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
604 // from Fn<(A, B,), C> to Fn(A, B) -> C
605 fn external_path(cx
: &DocContext
, name
: &str, trait_did
: Option
<ast
::DefId
>,
606 bindings
: Vec
<TypeBinding
>, substs
: &subst
::Substs
) -> Path
{
609 segments
: vec
![PathSegment
{
610 name
: name
.to_string(),
611 params
: external_path_params(cx
, trait_did
, bindings
, substs
)
616 impl Clean
<TyParamBound
> for ty
::BuiltinBound
{
617 fn clean(&self, cx
: &DocContext
) -> TyParamBound
{
618 let tcx
= match cx
.tcx_opt() {
620 None
=> return RegionBound(Lifetime
::statik())
622 let empty
= subst
::Substs
::empty();
623 let (did
, path
) = match *self {
625 (tcx
.lang_items
.send_trait().unwrap(),
626 external_path(cx
, "Send", None
, vec
![], &empty
)),
628 (tcx
.lang_items
.sized_trait().unwrap(),
629 external_path(cx
, "Sized", None
, vec
![], &empty
)),
631 (tcx
.lang_items
.copy_trait().unwrap(),
632 external_path(cx
, "Copy", None
, vec
![], &empty
)),
634 (tcx
.lang_items
.sync_trait().unwrap(),
635 external_path(cx
, "Sync", None
, vec
![], &empty
)),
637 let fqn
= csearch
::get_item_path(tcx
, did
);
638 let fqn
= fqn
.into_iter().map(|i
| i
.to_string()).collect();
639 cx
.external_paths
.borrow_mut().as_mut().unwrap().insert(did
,
641 TraitBound(PolyTrait
{
642 trait_
: ResolvedPath
{
648 }, ast
::TraitBoundModifier
::None
)
652 impl<'tcx
> Clean
<TyParamBound
> for ty
::TraitRef
<'tcx
> {
653 fn clean(&self, cx
: &DocContext
) -> TyParamBound
{
654 let tcx
= match cx
.tcx_opt() {
656 None
=> return RegionBound(Lifetime
::statik())
658 let fqn
= csearch
::get_item_path(tcx
, self.def_id
);
659 let fqn
= fqn
.into_iter().map(|i
| i
.to_string())
660 .collect
::<Vec
<String
>>();
661 let path
= external_path(cx
, fqn
.last().unwrap(),
662 Some(self.def_id
), vec
![], self.substs
);
663 cx
.external_paths
.borrow_mut().as_mut().unwrap().insert(self.def_id
,
666 debug
!("ty::TraitRef\n substs.types(TypeSpace): {:?}\n",
667 self.substs
.types
.get_slice(ParamSpace
::TypeSpace
));
669 // collect any late bound regions
670 let mut late_bounds
= vec
![];
671 for &ty_s
in self.substs
.types
.get_slice(ParamSpace
::TypeSpace
) {
672 use rustc
::middle
::ty
::{Region, sty}
;
673 if let sty
::ty_tup(ref ts
) = ty_s
.sty
{
675 if let sty
::ty_rptr(ref reg
, _
) = ty_s
.sty
{
676 if let &Region
::ReLateBound(_
, _
) = *reg
{
677 debug
!(" hit an ReLateBound {:?}", reg
);
678 if let Some(lt
) = reg
.clean(cx
) {
687 TraitBound(PolyTrait
{
688 trait_
: ResolvedPath { path: path, typarams: None, did: self.def_id, }
,
689 lifetimes
: late_bounds
690 }, ast
::TraitBoundModifier
::None
)
694 impl<'tcx
> Clean
<Vec
<TyParamBound
>> for ty
::ParamBounds
<'tcx
> {
695 fn clean(&self, cx
: &DocContext
) -> Vec
<TyParamBound
> {
696 let mut v
= Vec
::new();
697 for t
in &self.trait_bounds
{
700 for r
in self.region_bounds
.iter().filter_map(|r
| r
.clean(cx
)) {
701 v
.push(RegionBound(r
));
707 impl<'tcx
> Clean
<Option
<Vec
<TyParamBound
>>> for subst
::Substs
<'tcx
> {
708 fn clean(&self, cx
: &DocContext
) -> Option
<Vec
<TyParamBound
>> {
709 let mut v
= Vec
::new();
710 v
.extend(self.regions().iter().filter_map(|r
| r
.clean(cx
)).map(RegionBound
));
711 v
.extend(self.types
.iter().map(|t
| TraitBound(PolyTrait
{
714 }, ast
::TraitBoundModifier
::None
)));
715 if !v
.is_empty() {Some(v)}
else {None}
719 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
720 pub struct Lifetime(String
);
723 pub fn get_ref
<'a
>(&'a
self) -> &'a
str {
724 let Lifetime(ref s
) = *self;
729 pub fn statik() -> Lifetime
{
730 Lifetime("'static".to_string())
734 impl Clean
<Lifetime
> for ast
::Lifetime
{
735 fn clean(&self, _
: &DocContext
) -> Lifetime
{
736 Lifetime(token
::get_name(self.name
).to_string())
740 impl Clean
<Lifetime
> for ast
::LifetimeDef
{
741 fn clean(&self, _
: &DocContext
) -> Lifetime
{
742 Lifetime(token
::get_name(self.lifetime
.name
).to_string())
746 impl Clean
<Lifetime
> for ty
::RegionParameterDef
{
747 fn clean(&self, _
: &DocContext
) -> Lifetime
{
748 Lifetime(token
::get_name(self.name
).to_string())
752 impl Clean
<Option
<Lifetime
>> for ty
::Region
{
753 fn clean(&self, cx
: &DocContext
) -> Option
<Lifetime
> {
755 ty
::ReStatic
=> Some(Lifetime
::statik()),
756 ty
::ReLateBound(_
, ty
::BrNamed(_
, name
)) =>
757 Some(Lifetime(token
::get_name(name
).to_string())),
758 ty
::ReEarlyBound(ref data
) => Some(Lifetime(data
.name
.clean(cx
))),
760 ty
::ReLateBound(..) |
764 ty
::ReEmpty(..) => None
769 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
770 pub enum WherePredicate
{
771 BoundPredicate { ty: Type, bounds: Vec<TyParamBound> }
,
772 RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>}
,
773 EqPredicate { lhs: Type, rhs: Type }
776 impl Clean
<WherePredicate
> for ast
::WherePredicate
{
777 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
779 ast
::WherePredicate
::BoundPredicate(ref wbp
) => {
780 WherePredicate
::BoundPredicate
{
781 ty
: wbp
.bounded_ty
.clean(cx
),
782 bounds
: wbp
.bounds
.clean(cx
)
786 ast
::WherePredicate
::RegionPredicate(ref wrp
) => {
787 WherePredicate
::RegionPredicate
{
788 lifetime
: wrp
.lifetime
.clean(cx
),
789 bounds
: wrp
.bounds
.clean(cx
)
793 ast
::WherePredicate
::EqPredicate(_
) => {
794 unimplemented
!() // FIXME(#20041)
800 impl<'a
> Clean
<WherePredicate
> for ty
::Predicate
<'a
> {
801 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
802 use rustc
::middle
::ty
::Predicate
;
805 Predicate
::Trait(ref pred
) => pred
.clean(cx
),
806 Predicate
::Equate(ref pred
) => pred
.clean(cx
),
807 Predicate
::RegionOutlives(ref pred
) => pred
.clean(cx
),
808 Predicate
::TypeOutlives(ref pred
) => pred
.clean(cx
),
809 Predicate
::Projection(ref pred
) => pred
.clean(cx
)
814 impl<'a
> Clean
<WherePredicate
> for ty
::TraitPredicate
<'a
> {
815 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
816 WherePredicate
::BoundPredicate
{
817 ty
: self.trait_ref
.substs
.self_ty().clean(cx
).unwrap(),
818 bounds
: vec
![self.trait_ref
.clean(cx
)]
823 impl<'tcx
> Clean
<WherePredicate
> for ty
::EquatePredicate
<'tcx
> {
824 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
825 let ty
::EquatePredicate(ref lhs
, ref rhs
) = *self;
826 WherePredicate
::EqPredicate
{
833 impl Clean
<WherePredicate
> for ty
::OutlivesPredicate
<ty
::Region
, ty
::Region
> {
834 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
835 let ty
::OutlivesPredicate(ref a
, ref b
) = *self;
836 WherePredicate
::RegionPredicate
{
837 lifetime
: a
.clean(cx
).unwrap(),
838 bounds
: vec
![b
.clean(cx
).unwrap()]
843 impl<'tcx
> Clean
<WherePredicate
> for ty
::OutlivesPredicate
<ty
::Ty
<'tcx
>, ty
::Region
> {
844 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
845 let ty
::OutlivesPredicate(ref ty
, ref lt
) = *self;
847 WherePredicate
::BoundPredicate
{
849 bounds
: vec
![TyParamBound
::RegionBound(lt
.clean(cx
).unwrap())]
854 impl<'tcx
> Clean
<WherePredicate
> for ty
::ProjectionPredicate
<'tcx
> {
855 fn clean(&self, cx
: &DocContext
) -> WherePredicate
{
856 WherePredicate
::EqPredicate
{
857 lhs
: self.projection_ty
.clean(cx
),
858 rhs
: self.ty
.clean(cx
)
863 impl<'tcx
> Clean
<Type
> for ty
::ProjectionTy
<'tcx
> {
864 fn clean(&self, cx
: &DocContext
) -> Type
{
865 let trait_
= match self.trait_ref
.clean(cx
) {
866 TyParamBound
::TraitBound(t
, _
) => t
.trait_
,
867 TyParamBound
::RegionBound(_
) => {
868 panic
!("cleaning a trait got a region")
872 name
: self.item_name
.clean(cx
),
873 self_type
: box self.trait_ref
.self_ty().clean(cx
),
879 // maybe use a Generic enum and use ~[Generic]?
880 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
881 pub struct Generics
{
882 pub lifetimes
: Vec
<Lifetime
>,
883 pub type_params
: Vec
<TyParam
>,
884 pub where_predicates
: Vec
<WherePredicate
>
887 impl Clean
<Generics
> for ast
::Generics
{
888 fn clean(&self, cx
: &DocContext
) -> Generics
{
890 lifetimes
: self.lifetimes
.clean(cx
),
891 type_params
: self.ty_params
.clean(cx
),
892 where_predicates
: self.where_clause
.predicates
.clean(cx
)
897 impl<'a
, 'tcx
> Clean
<Generics
> for (&'a ty
::Generics
<'tcx
>,
898 &'a ty
::GenericPredicates
<'tcx
>,
900 fn clean(&self, cx
: &DocContext
) -> Generics
{
901 use std
::collections
::HashSet
;
902 use self::WherePredicate
as WP
;
904 let (gens
, preds
, space
) = *self;
906 // Bounds in the type_params and lifetimes fields are repeated in the
907 // predicates field (see rustc_typeck::collect::ty_generics), so remove
909 let stripped_typarams
= gens
.types
.get_slice(space
).iter().map(|tp
| {
911 }).collect
::<Vec
<_
>>();
912 let stripped_lifetimes
= gens
.regions
.get_slice(space
).iter().map(|rp
| {
913 let mut srp
= rp
.clone();
914 srp
.bounds
= Vec
::new();
916 }).collect
::<Vec
<_
>>();
918 let mut where_predicates
= preds
.predicates
.get_slice(space
)
921 // Type parameters and have a Sized bound by default unless removed with
922 // ?Sized. Scan through the predicates and mark any type parameter with
923 // a Sized bound, removing the bounds as we find them.
925 // Note that associated types also have a sized bound by default, but we
926 // don't actually konw the set of associated types right here so that's
927 // handled in cleaning associated types
928 let mut sized_params
= HashSet
::new();
929 where_predicates
.retain(|pred
| {
931 WP
::BoundPredicate { ty: Generic(ref g), ref bounds }
=> {
932 if bounds
.iter().any(|b
| b
.is_sized_bound(cx
)) {
933 sized_params
.insert(g
.clone());
943 // Run through the type parameters again and insert a ?Sized
944 // unbound for any we didn't find to be Sized.
945 for tp
in &stripped_typarams
{
946 if !sized_params
.contains(&tp
.name
) {
947 where_predicates
.push(WP
::BoundPredicate
{
948 ty
: Type
::Generic(tp
.name
.clone()),
949 bounds
: vec
![TyParamBound
::maybe_sized(cx
)],
954 // It would be nice to collect all of the bounds on a type and recombine
955 // them if possible, to avoid e.g. `where T: Foo, T: Bar, T: Sized, T: 'a`
956 // and instead see `where T: Foo + Bar + Sized + 'a`
959 type_params
: simplify
::ty_params(stripped_typarams
),
960 lifetimes
: stripped_lifetimes
,
961 where_predicates
: simplify
::where_clauses(cx
, where_predicates
),
966 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
968 pub generics
: Generics
,
970 pub unsafety
: ast
::Unsafety
,
975 impl Clean
<Method
> for ast
::MethodSig
{
976 fn clean(&self, cx
: &DocContext
) -> Method
{
977 let all_inputs
= &self.decl
.inputs
;
978 let inputs
= match self.explicit_self
.node
{
979 ast
::SelfStatic
=> &**all_inputs
,
980 _
=> &all_inputs
[1..]
984 values
: inputs
.clean(cx
),
986 output
: self.decl
.output
.clean(cx
),
990 generics
: self.generics
.clean(cx
),
991 self_
: self.explicit_self
.node
.clean(cx
),
992 unsafety
: self.unsafety
.clone(),
999 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1000 pub struct TyMethod
{
1001 pub unsafety
: ast
::Unsafety
,
1003 pub generics
: Generics
,
1008 impl Clean
<TyMethod
> for ast
::MethodSig
{
1009 fn clean(&self, cx
: &DocContext
) -> TyMethod
{
1010 let inputs
= match self.explicit_self
.node
{
1011 ast
::SelfStatic
=> &*self.decl
.inputs
,
1012 _
=> &self.decl
.inputs
[1..]
1016 values
: inputs
.clean(cx
),
1018 output
: self.decl
.output
.clean(cx
),
1022 unsafety
: self.unsafety
.clone(),
1024 self_
: self.explicit_self
.node
.clean(cx
),
1025 generics
: self.generics
.clean(cx
),
1031 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1035 SelfBorrowed(Option
<Lifetime
>, Mutability
),
1039 impl Clean
<SelfTy
> for ast
::ExplicitSelf_
{
1040 fn clean(&self, cx
: &DocContext
) -> SelfTy
{
1042 ast
::SelfStatic
=> SelfStatic
,
1043 ast
::SelfValue(_
) => SelfValue
,
1044 ast
::SelfRegion(ref lt
, ref mt
, _
) => {
1045 SelfBorrowed(lt
.clean(cx
), mt
.clean(cx
))
1047 ast
::SelfExplicit(ref typ
, _
) => SelfExplicit(typ
.clean(cx
)),
1052 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1053 pub struct Function
{
1055 pub generics
: Generics
,
1056 pub unsafety
: ast
::Unsafety
,
1060 impl Clean
<Item
> for doctree
::Function
{
1061 fn clean(&self, cx
: &DocContext
) -> Item
{
1063 name
: Some(self.name
.clean(cx
)),
1064 attrs
: self.attrs
.clean(cx
),
1065 source
: self.whence
.clean(cx
),
1066 visibility
: self.vis
.clean(cx
),
1067 stability
: self.stab
.clean(cx
),
1068 def_id
: ast_util
::local_def(self.id
),
1069 inner
: FunctionItem(Function
{
1070 decl
: self.decl
.clean(cx
),
1071 generics
: self.generics
.clean(cx
),
1072 unsafety
: self.unsafety
,
1079 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1081 pub inputs
: Arguments
,
1082 pub output
: FunctionRetTy
,
1083 pub attrs
: Vec
<Attribute
>,
1086 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1087 pub struct Arguments
{
1088 pub values
: Vec
<Argument
>,
1091 impl Clean
<FnDecl
> for ast
::FnDecl
{
1092 fn clean(&self, cx
: &DocContext
) -> FnDecl
{
1095 values
: self.inputs
.clean(cx
),
1097 output
: self.output
.clean(cx
),
1103 impl<'tcx
> Clean
<Type
> for ty
::FnOutput
<'tcx
> {
1104 fn clean(&self, cx
: &DocContext
) -> Type
{
1106 ty
::FnConverging(ty
) => ty
.clean(cx
),
1107 ty
::FnDiverging
=> Bottom
1112 impl<'a
, 'tcx
> Clean
<FnDecl
> for (ast
::DefId
, &'a ty
::PolyFnSig
<'tcx
>) {
1113 fn clean(&self, cx
: &DocContext
) -> FnDecl
{
1114 let (did
, sig
) = *self;
1115 let mut names
= if did
.node
!= 0 {
1116 csearch
::get_method_arg_names(&cx
.tcx().sess
.cstore
, did
).into_iter()
1118 Vec
::new().into_iter()
1120 if names
.peek().map(|s
| &**s
) == Some("self") {
1121 let _
= names
.next();
1124 output
: Return(sig
.0.output
.clean(cx
)),
1127 values
: sig
.0.inputs
.iter().map(|t
| {
1131 name
: names
.next().unwrap_or("".to_string()),
1139 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1140 pub struct Argument
{
1143 pub id
: ast
::NodeId
,
1146 impl Clean
<Argument
> for ast
::Arg
{
1147 fn clean(&self, cx
: &DocContext
) -> Argument
{
1149 name
: name_from_pat(&*self.pat
),
1150 type_
: (self.ty
.clean(cx
)),
1156 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1157 pub enum FunctionRetTy
{
1163 impl Clean
<FunctionRetTy
> for ast
::FunctionRetTy
{
1164 fn clean(&self, cx
: &DocContext
) -> FunctionRetTy
{
1166 ast
::Return(ref typ
) => Return(typ
.clean(cx
)),
1167 ast
::DefaultReturn(..) => DefaultReturn
,
1168 ast
::NoReturn(..) => NoReturn
1173 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1175 pub unsafety
: ast
::Unsafety
,
1176 pub items
: Vec
<Item
>,
1177 pub generics
: Generics
,
1178 pub bounds
: Vec
<TyParamBound
>,
1181 impl Clean
<Item
> for doctree
::Trait
{
1182 fn clean(&self, cx
: &DocContext
) -> Item
{
1184 name
: Some(self.name
.clean(cx
)),
1185 attrs
: self.attrs
.clean(cx
),
1186 source
: self.whence
.clean(cx
),
1187 def_id
: ast_util
::local_def(self.id
),
1188 visibility
: self.vis
.clean(cx
),
1189 stability
: self.stab
.clean(cx
),
1190 inner
: TraitItem(Trait
{
1191 unsafety
: self.unsafety
,
1192 items
: self.items
.clean(cx
),
1193 generics
: self.generics
.clean(cx
),
1194 bounds
: self.bounds
.clean(cx
),
1200 impl Clean
<Type
> for ast
::TraitRef
{
1201 fn clean(&self, cx
: &DocContext
) -> Type
{
1202 resolve_type(cx
, self.path
.clean(cx
), self.ref_id
)
1206 impl Clean
<PolyTrait
> for ast
::PolyTraitRef
{
1207 fn clean(&self, cx
: &DocContext
) -> PolyTrait
{
1209 trait_
: self.trait_ref
.clean(cx
),
1210 lifetimes
: self.bound_lifetimes
.clean(cx
)
1215 impl Clean
<Item
> for ast
::TraitItem
{
1216 fn clean(&self, cx
: &DocContext
) -> Item
{
1217 let inner
= match self.node
{
1218 ast
::MethodTraitItem(ref sig
, Some(_
)) => {
1219 MethodItem(sig
.clean(cx
))
1221 ast
::MethodTraitItem(ref sig
, None
) => {
1222 TyMethodItem(sig
.clean(cx
))
1224 ast
::TypeTraitItem(ref bounds
, ref default) => {
1225 AssociatedTypeItem(bounds
.clean(cx
), default.clean(cx
))
1229 name
: Some(self.ident
.clean(cx
)),
1230 attrs
: self.attrs
.clean(cx
),
1231 source
: self.span
.clean(cx
),
1232 def_id
: ast_util
::local_def(self.id
),
1234 stability
: get_stability(cx
, ast_util
::local_def(self.id
)),
1240 impl Clean
<Item
> for ast
::ImplItem
{
1241 fn clean(&self, cx
: &DocContext
) -> Item
{
1242 let inner
= match self.node
{
1243 ast
::MethodImplItem(ref sig
, _
) => {
1244 MethodItem(sig
.clean(cx
))
1246 ast
::TypeImplItem(ref ty
) => TypedefItem(Typedef
{
1247 type_
: ty
.clean(cx
),
1248 generics
: Generics
{
1249 lifetimes
: Vec
::new(),
1250 type_params
: Vec
::new(),
1251 where_predicates
: Vec
::new()
1254 ast
::MacImplItem(_
) => {
1256 source
: self.span
.to_src(cx
),
1261 name
: Some(self.ident
.clean(cx
)),
1262 source
: self.span
.clean(cx
),
1263 attrs
: self.attrs
.clean(cx
),
1264 def_id
: ast_util
::local_def(self.id
),
1265 visibility
: self.vis
.clean(cx
),
1266 stability
: get_stability(cx
, ast_util
::local_def(self.id
)),
1272 impl<'tcx
> Clean
<Item
> for ty
::Method
<'tcx
> {
1273 fn clean(&self, cx
: &DocContext
) -> Item
{
1274 let (self_
, sig
) = match self.explicit_self
{
1275 ty
::StaticExplicitSelfCategory
=> (ast
::SelfStatic
.clean(cx
),
1276 self.fty
.sig
.clone()),
1278 let sig
= ty
::Binder(ty
::FnSig
{
1279 inputs
: self.fty
.sig
.0.inputs
[1..].to_vec(),
1280 ..self.fty
.sig
.0.clone()
1283 ty
::ByValueExplicitSelfCategory
=> SelfValue
,
1284 ty
::ByReferenceExplicitSelfCategory(..) => {
1285 match self.fty
.sig
.0.inputs
[0].sty
{
1286 ty
::ty_rptr(r
, mt
) => {
1287 SelfBorrowed(r
.clean(cx
), mt
.mutbl
.clean(cx
))
1289 _
=> unreachable
!(),
1292 ty
::ByBoxExplicitSelfCategory
=> {
1293 SelfExplicit(self.fty
.sig
.0.inputs
[0].clean(cx
))
1295 ty
::StaticExplicitSelfCategory
=> unreachable
!(),
1301 let generics
= (&self.generics
, &self.predicates
,
1302 subst
::FnSpace
).clean(cx
);
1303 let decl
= (self.def_id
, &sig
).clean(cx
);
1304 let provided
= match self.container
{
1305 ty
::ImplContainer(..) => false,
1306 ty
::TraitContainer(did
) => {
1307 ty
::provided_trait_methods(cx
.tcx(), did
).iter().any(|m
| {
1308 m
.def_id
== self.def_id
1312 let inner
= if provided
{
1314 unsafety
: self.fty
.unsafety
,
1321 TyMethodItem(TyMethod
{
1322 unsafety
: self.fty
.unsafety
,
1331 name
: Some(self.name
.clean(cx
)),
1332 visibility
: Some(ast
::Inherited
),
1333 stability
: get_stability(cx
, self.def_id
),
1334 def_id
: self.def_id
,
1335 attrs
: inline
::load_attrs(cx
, cx
.tcx(), self.def_id
),
1336 source
: Span
::empty(),
1342 impl<'tcx
> Clean
<Item
> for ty
::ImplOrTraitItem
<'tcx
> {
1343 fn clean(&self, cx
: &DocContext
) -> Item
{
1345 ty
::MethodTraitItem(ref mti
) => mti
.clean(cx
),
1346 ty
::TypeTraitItem(ref tti
) => tti
.clean(cx
),
1351 /// A trait reference, which may have higher ranked lifetimes.
1352 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1353 pub struct PolyTrait
{
1355 pub lifetimes
: Vec
<Lifetime
>
1358 /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
1359 /// type out of the AST/ty::ctxt given one of these, if more information is needed. Most importantly
1360 /// it does not preserve mutability or boxes.
1361 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1363 /// structs/enums/traits (anything that'd be an ast::TyPath)
1366 typarams
: Option
<Vec
<TyParamBound
>>,
1369 /// For parameterized types, so the consumer of the JSON don't go
1370 /// looking for types which don't exist anywhere.
1372 /// Primitives are the fixed-size numeric types (plus int/usize/float), char,
1373 /// arrays, slices, and tuples.
1374 Primitive(PrimitiveType
),
1376 BareFunction(Box
<BareFunctionDecl
>),
1379 FixedVector(Box
<Type
>, String
),
1383 RawPointer(Mutability
, Box
<Type
>),
1385 lifetime
: Option
<Lifetime
>,
1386 mutability
: Mutability
,
1390 // <Type as Trait>::Name
1393 self_type
: Box
<Type
>,
1401 PolyTraitRef(Vec
<TyParamBound
>),
1404 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)]
1405 pub enum PrimitiveType
{
1406 Isize
, I8
, I16
, I32
, I64
,
1407 Usize
, U8
, U16
, U32
, U64
,
1415 PrimitiveRawPointer
,
1418 #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)]
1432 pub fn primitive_type(&self) -> Option
<PrimitiveType
> {
1434 Primitive(p
) | BorrowedRef { type_: box Primitive(p), ..}
=> Some(p
),
1435 Vector(..) | BorrowedRef{ type_: box Vector(..), .. }
=> Some(Slice
),
1436 FixedVector(..) | BorrowedRef { type_: box FixedVector(..), .. }
=> {
1439 Tuple(..) => Some(PrimitiveTuple
),
1440 RawPointer(..) => Some(PrimitiveRawPointer
),
1446 impl PrimitiveType
{
1447 fn from_str(s
: &str) -> Option
<PrimitiveType
> {
1449 "isize" => Some(Isize
),
1454 "usize" => Some(Usize
),
1459 "bool" => Some(Bool
),
1460 "char" => Some(Char
),
1464 "array" => Some(Array
),
1465 "slice" => Some(Slice
),
1466 "tuple" => Some(PrimitiveTuple
),
1467 "pointer" => Some(PrimitiveRawPointer
),
1472 fn find(attrs
: &[Attribute
]) -> Option
<PrimitiveType
> {
1474 let list
= match *attr
{
1475 List(ref k
, ref l
) if *k
== "doc" => l
,
1478 for sub_attr
in list
{
1479 let value
= match *sub_attr
{
1480 NameValue(ref k
, ref v
)
1481 if *k
== "primitive" => v
,
1484 match PrimitiveType
::from_str(value
) {
1485 Some(p
) => return Some(p
),
1493 pub fn to_string(&self) -> &'
static str {
1512 PrimitiveTuple
=> "tuple",
1513 PrimitiveRawPointer
=> "pointer",
1517 pub fn to_url_str(&self) -> &'
static str {
1521 /// Creates a rustdoc-specific node id for primitive types.
1523 /// These node ids are generally never used by the AST itself.
1524 pub fn to_node_id(&self) -> ast
::NodeId
{
1525 u32::MAX
- 1 - (*self as u32)
1529 impl Clean
<Type
> for ast
::Ty
{
1530 fn clean(&self, cx
: &DocContext
) -> Type
{
1533 TyPtr(ref m
) => RawPointer(m
.mutbl
.clean(cx
), box m
.ty
.clean(cx
)),
1534 TyRptr(ref l
, ref m
) =>
1535 BorrowedRef
{lifetime
: l
.clean(cx
), mutability
: m
.mutbl
.clean(cx
),
1536 type_
: box m
.ty
.clean(cx
)},
1537 TyVec(ref ty
) => Vector(box ty
.clean(cx
)),
1538 TyFixedLengthVec(ref ty
, ref e
) => FixedVector(box ty
.clean(cx
),
1540 TyTup(ref tys
) => Tuple(tys
.clean(cx
)),
1541 TyPath(None
, ref p
) => {
1542 resolve_type(cx
, p
.clean(cx
), self.id
)
1544 TyPath(Some(ref qself
), ref p
) => {
1545 let mut trait_path
= p
.clone();
1546 trait_path
.segments
.pop();
1548 name
: p
.segments
.last().unwrap().identifier
.clean(cx
),
1549 self_type
: box qself
.ty
.clean(cx
),
1550 trait_
: box resolve_type(cx
, trait_path
.clean(cx
), self.id
)
1553 TyObjectSum(ref lhs
, ref bounds
) => {
1554 let lhs_ty
= lhs
.clean(cx
);
1556 ResolvedPath { path, typarams: None, did }
=> {
1557 ResolvedPath { path: path, typarams: Some(bounds.clean(cx)), did: did}
1560 lhs_ty
// shouldn't happen
1564 TyBareFn(ref barefn
) => BareFunction(box barefn
.clean(cx
)),
1565 TyParen(ref ty
) => ty
.clean(cx
),
1566 TyPolyTraitRef(ref bounds
) => {
1567 PolyTraitRef(bounds
.clean(cx
))
1573 panic
!("Unimplemented type {:?}", self.node
)
1579 impl<'tcx
> Clean
<Type
> for ty
::Ty
<'tcx
> {
1580 fn clean(&self, cx
: &DocContext
) -> Type
{
1582 ty
::ty_bool
=> Primitive(Bool
),
1583 ty
::ty_char
=> Primitive(Char
),
1584 ty
::ty_int(ast
::TyIs
) => Primitive(Isize
),
1585 ty
::ty_int(ast
::TyI8
) => Primitive(I8
),
1586 ty
::ty_int(ast
::TyI16
) => Primitive(I16
),
1587 ty
::ty_int(ast
::TyI32
) => Primitive(I32
),
1588 ty
::ty_int(ast
::TyI64
) => Primitive(I64
),
1589 ty
::ty_uint(ast
::TyUs
) => Primitive(Usize
),
1590 ty
::ty_uint(ast
::TyU8
) => Primitive(U8
),
1591 ty
::ty_uint(ast
::TyU16
) => Primitive(U16
),
1592 ty
::ty_uint(ast
::TyU32
) => Primitive(U32
),
1593 ty
::ty_uint(ast
::TyU64
) => Primitive(U64
),
1594 ty
::ty_float(ast
::TyF32
) => Primitive(F32
),
1595 ty
::ty_float(ast
::TyF64
) => Primitive(F64
),
1596 ty
::ty_str
=> Primitive(Str
),
1598 let box_did
= cx
.tcx_opt().and_then(|tcx
| {
1599 tcx
.lang_items
.owned_box()
1601 lang_struct(cx
, box_did
, t
, "Box", Unique
)
1603 ty
::ty_vec(ty
, None
) => Vector(box ty
.clean(cx
)),
1604 ty
::ty_vec(ty
, Some(i
)) => FixedVector(box ty
.clean(cx
),
1606 ty
::ty_ptr(mt
) => RawPointer(mt
.mutbl
.clean(cx
), box mt
.ty
.clean(cx
)),
1607 ty
::ty_rptr(r
, mt
) => BorrowedRef
{
1608 lifetime
: r
.clean(cx
),
1609 mutability
: mt
.mutbl
.clean(cx
),
1610 type_
: box mt
.ty
.clean(cx
),
1612 ty
::ty_bare_fn(_
, ref fty
) => BareFunction(box BareFunctionDecl
{
1613 unsafety
: fty
.unsafety
,
1614 generics
: Generics
{
1615 lifetimes
: Vec
::new(),
1616 type_params
: Vec
::new(),
1617 where_predicates
: Vec
::new()
1619 decl
: (ast_util
::local_def(0), &fty
.sig
).clean(cx
),
1620 abi
: fty
.abi
.to_string(),
1622 ty
::ty_struct(did
, substs
) |
1623 ty
::ty_enum(did
, substs
) => {
1624 let fqn
= csearch
::get_item_path(cx
.tcx(), did
);
1625 let fqn
: Vec
<_
> = fqn
.into_iter().map(|i
| i
.to_string()).collect();
1626 let kind
= match self.sty
{
1627 ty
::ty_struct(..) => TypeStruct
,
1630 let path
= external_path(cx
, &fqn
.last().unwrap().to_string(),
1631 None
, vec
![], substs
);
1632 cx
.external_paths
.borrow_mut().as_mut().unwrap().insert(did
, (fqn
, kind
));
1639 ty
::ty_trait(box ty
::TyTrait { ref principal, ref bounds }
) => {
1640 let did
= principal
.def_id();
1641 let fqn
= csearch
::get_item_path(cx
.tcx(), did
);
1642 let fqn
: Vec
<_
> = fqn
.into_iter().map(|i
| i
.to_string()).collect();
1643 let (typarams
, bindings
) = bounds
.clean(cx
);
1644 let path
= external_path(cx
, &fqn
.last().unwrap().to_string(),
1645 Some(did
), bindings
, principal
.substs());
1646 cx
.external_paths
.borrow_mut().as_mut().unwrap().insert(did
, (fqn
, TypeTrait
));
1649 typarams
: Some(typarams
),
1653 ty
::ty_tup(ref t
) => Tuple(t
.clean(cx
)),
1655 ty
::ty_projection(ref data
) => data
.clean(cx
),
1657 ty
::ty_param(ref p
) => Generic(token
::get_name(p
.name
).to_string()),
1659 ty
::ty_closure(..) => Tuple(vec
![]), // FIXME(pcwalton)
1661 ty
::ty_infer(..) => panic
!("ty_infer"),
1662 ty
::ty_err
=> panic
!("ty_err"),
1667 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1668 pub enum StructField
{
1669 HiddenStructField
, // inserted later by strip passes
1670 TypedStructField(Type
),
1673 impl Clean
<Item
> for ast
::StructField
{
1674 fn clean(&self, cx
: &DocContext
) -> Item
{
1675 let (name
, vis
) = match self.node
.kind
{
1676 ast
::NamedField(id
, vis
) => (Some(id
), vis
),
1677 ast
::UnnamedField(vis
) => (None
, vis
)
1680 name
: name
.clean(cx
),
1681 attrs
: self.node
.attrs
.clean(cx
),
1682 source
: self.span
.clean(cx
),
1683 visibility
: Some(vis
),
1684 stability
: get_stability(cx
, ast_util
::local_def(self.node
.id
)),
1685 def_id
: ast_util
::local_def(self.node
.id
),
1686 inner
: StructFieldItem(TypedStructField(self.node
.ty
.clean(cx
))),
1691 impl Clean
<Item
> for ty
::field_ty
{
1692 fn clean(&self, cx
: &DocContext
) -> Item
{
1693 use syntax
::parse
::token
::special_idents
::unnamed_field
;
1694 use rustc
::metadata
::csearch
;
1696 let attr_map
= csearch
::get_struct_field_attrs(&cx
.tcx().sess
.cstore
, self.id
);
1698 let (name
, attrs
) = if self.name
== unnamed_field
.name
{
1701 (Some(self.name
), Some(attr_map
.get(&self.id
.node
).unwrap()))
1704 let ty
= ty
::lookup_item_type(cx
.tcx(), self.id
);
1707 name
: name
.clean(cx
),
1708 attrs
: attrs
.unwrap_or(&Vec
::new()).clean(cx
),
1709 source
: Span
::empty(),
1710 visibility
: Some(self.vis
),
1711 stability
: get_stability(cx
, self.id
),
1713 inner
: StructFieldItem(TypedStructField(ty
.ty
.clean(cx
))),
1718 pub type Visibility
= ast
::Visibility
;
1720 impl Clean
<Option
<Visibility
>> for ast
::Visibility
{
1721 fn clean(&self, _
: &DocContext
) -> Option
<Visibility
> {
1726 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1728 pub struct_type
: doctree
::StructType
,
1729 pub generics
: Generics
,
1730 pub fields
: Vec
<Item
>,
1731 pub fields_stripped
: bool
,
1734 impl Clean
<Item
> for doctree
::Struct
{
1735 fn clean(&self, cx
: &DocContext
) -> Item
{
1737 name
: Some(self.name
.clean(cx
)),
1738 attrs
: self.attrs
.clean(cx
),
1739 source
: self.whence
.clean(cx
),
1740 def_id
: ast_util
::local_def(self.id
),
1741 visibility
: self.vis
.clean(cx
),
1742 stability
: self.stab
.clean(cx
),
1743 inner
: StructItem(Struct
{
1744 struct_type
: self.struct_type
,
1745 generics
: self.generics
.clean(cx
),
1746 fields
: self.fields
.clean(cx
),
1747 fields_stripped
: false,
1753 /// This is a more limited form of the standard Struct, different in that
1754 /// it lacks the things most items have (name, id, parameterization). Found
1755 /// only as a variant in an enum.
1756 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1757 pub struct VariantStruct
{
1758 pub struct_type
: doctree
::StructType
,
1759 pub fields
: Vec
<Item
>,
1760 pub fields_stripped
: bool
,
1763 impl Clean
<VariantStruct
> for syntax
::ast
::StructDef
{
1764 fn clean(&self, cx
: &DocContext
) -> VariantStruct
{
1766 struct_type
: doctree
::struct_type_from_def(self),
1767 fields
: self.fields
.clean(cx
),
1768 fields_stripped
: false,
1773 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1775 pub variants
: Vec
<Item
>,
1776 pub generics
: Generics
,
1777 pub variants_stripped
: bool
,
1780 impl Clean
<Item
> for doctree
::Enum
{
1781 fn clean(&self, cx
: &DocContext
) -> Item
{
1783 name
: Some(self.name
.clean(cx
)),
1784 attrs
: self.attrs
.clean(cx
),
1785 source
: self.whence
.clean(cx
),
1786 def_id
: ast_util
::local_def(self.id
),
1787 visibility
: self.vis
.clean(cx
),
1788 stability
: self.stab
.clean(cx
),
1789 inner
: EnumItem(Enum
{
1790 variants
: self.variants
.clean(cx
),
1791 generics
: self.generics
.clean(cx
),
1792 variants_stripped
: false,
1798 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1799 pub struct Variant
{
1800 pub kind
: VariantKind
,
1803 impl Clean
<Item
> for doctree
::Variant
{
1804 fn clean(&self, cx
: &DocContext
) -> Item
{
1806 name
: Some(self.name
.clean(cx
)),
1807 attrs
: self.attrs
.clean(cx
),
1808 source
: self.whence
.clean(cx
),
1809 visibility
: self.vis
.clean(cx
),
1810 stability
: self.stab
.clean(cx
),
1811 def_id
: ast_util
::local_def(self.id
),
1812 inner
: VariantItem(Variant
{
1813 kind
: self.kind
.clean(cx
),
1819 impl<'tcx
> Clean
<Item
> for ty
::VariantInfo
<'tcx
> {
1820 fn clean(&self, cx
: &DocContext
) -> Item
{
1821 // use syntax::parse::token::special_idents::unnamed_field;
1822 let kind
= match self.arg_names
.as_ref().map(|s
| &**s
) {
1823 None
| Some([]) if self.args
.is_empty() => CLikeVariant
,
1824 None
| Some([]) => {
1825 TupleVariant(self.args
.clean(cx
))
1828 StructVariant(VariantStruct
{
1829 struct_type
: doctree
::Plain
,
1830 fields_stripped
: false,
1831 fields
: s
.iter().zip(self.args
.iter()).map(|(name
, ty
)| {
1833 source
: Span
::empty(),
1834 name
: Some(name
.clean(cx
)),
1836 visibility
: Some(ast
::Public
),
1837 // FIXME: this is not accurate, we need an id for
1838 // the specific field but we're using the id
1839 // for the whole variant. Thus we read the
1840 // stability from the whole variant as well.
1841 // Struct variants are experimental and need
1842 // more infrastructure work before we can get
1843 // at the needed information here.
1845 stability
: get_stability(cx
, self.id
),
1846 inner
: StructFieldItem(
1847 TypedStructField(ty
.clean(cx
))
1855 name
: Some(self.name
.clean(cx
)),
1856 attrs
: inline
::load_attrs(cx
, cx
.tcx(), self.id
),
1857 source
: Span
::empty(),
1858 visibility
: Some(ast
::Public
),
1860 inner
: VariantItem(Variant { kind: kind }
),
1861 stability
: get_stability(cx
, self.id
),
1866 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1867 pub enum VariantKind
{
1869 TupleVariant(Vec
<Type
>),
1870 StructVariant(VariantStruct
),
1873 impl Clean
<VariantKind
> for ast
::VariantKind
{
1874 fn clean(&self, cx
: &DocContext
) -> VariantKind
{
1876 &ast
::TupleVariantKind(ref args
) => {
1877 if args
.is_empty() {
1880 TupleVariant(args
.iter().map(|x
| x
.ty
.clean(cx
)).collect())
1883 &ast
::StructVariantKind(ref sd
) => StructVariant(sd
.clean(cx
)),
1888 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
1890 pub filename
: String
,
1898 fn empty() -> Span
{
1900 filename
: "".to_string(),
1901 loline
: 0, locol
: 0,
1902 hiline
: 0, hicol
: 0,
1907 impl Clean
<Span
> for syntax
::codemap
::Span
{
1908 fn clean(&self, cx
: &DocContext
) -> Span
{
1909 let cm
= cx
.sess().codemap();
1910 let filename
= cm
.span_to_filename(*self);
1911 let lo
= cm
.lookup_char_pos(self.lo
);
1912 let hi
= cm
.lookup_char_pos(self.hi
);
1914 filename
: filename
.to_string(),
1916 locol
: lo
.col
.to_usize(),
1918 hicol
: hi
.col
.to_usize(),
1923 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1926 pub segments
: Vec
<PathSegment
>,
1930 pub fn singleton(name
: String
) -> Path
{
1933 segments
: vec
![PathSegment
{
1935 params
: PathParameters
::AngleBracketed
{
1936 lifetimes
: Vec
::new(),
1938 bindings
: Vec
::new()
1945 impl Clean
<Path
> for ast
::Path
{
1946 fn clean(&self, cx
: &DocContext
) -> Path
{
1948 global
: self.global
,
1949 segments
: self.segments
.clean(cx
),
1954 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1955 pub enum PathParameters
{
1957 lifetimes
: Vec
<Lifetime
>,
1959 bindings
: Vec
<TypeBinding
>
1963 output
: Option
<Type
>
1967 impl Clean
<PathParameters
> for ast
::PathParameters
{
1968 fn clean(&self, cx
: &DocContext
) -> PathParameters
{
1970 ast
::AngleBracketedParameters(ref data
) => {
1971 PathParameters
::AngleBracketed
{
1972 lifetimes
: data
.lifetimes
.clean(cx
),
1973 types
: data
.types
.clean(cx
),
1974 bindings
: data
.bindings
.clean(cx
)
1978 ast
::ParenthesizedParameters(ref data
) => {
1979 PathParameters
::Parenthesized
{
1980 inputs
: data
.inputs
.clean(cx
),
1981 output
: data
.output
.clean(cx
)
1988 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
1989 pub struct PathSegment
{
1991 pub params
: PathParameters
1994 impl Clean
<PathSegment
> for ast
::PathSegment
{
1995 fn clean(&self, cx
: &DocContext
) -> PathSegment
{
1997 name
: self.identifier
.clean(cx
),
1998 params
: self.parameters
.clean(cx
)
2003 fn path_to_string(p
: &ast
::Path
) -> String
{
2004 let mut s
= String
::new();
2005 let mut first
= true;
2006 for i
in p
.segments
.iter().map(|x
| token
::get_ident(x
.identifier
)) {
2007 if !first
|| p
.global
{
2017 impl Clean
<String
> for ast
::Ident
{
2018 fn clean(&self, _
: &DocContext
) -> String
{
2019 token
::get_ident(*self).to_string()
2023 impl Clean
<String
> for ast
::Name
{
2024 fn clean(&self, _
: &DocContext
) -> String
{
2025 token
::get_name(*self).to_string()
2029 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2030 pub struct Typedef
{
2032 pub generics
: Generics
,
2035 impl Clean
<Item
> for doctree
::Typedef
{
2036 fn clean(&self, cx
: &DocContext
) -> Item
{
2038 name
: Some(self.name
.clean(cx
)),
2039 attrs
: self.attrs
.clean(cx
),
2040 source
: self.whence
.clean(cx
),
2041 def_id
: ast_util
::local_def(self.id
.clone()),
2042 visibility
: self.vis
.clean(cx
),
2043 stability
: self.stab
.clean(cx
),
2044 inner
: TypedefItem(Typedef
{
2045 type_
: self.ty
.clean(cx
),
2046 generics
: self.gen
.clean(cx
),
2052 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
2053 pub struct BareFunctionDecl
{
2054 pub unsafety
: ast
::Unsafety
,
2055 pub generics
: Generics
,
2060 impl Clean
<BareFunctionDecl
> for ast
::BareFnTy
{
2061 fn clean(&self, cx
: &DocContext
) -> BareFunctionDecl
{
2063 unsafety
: self.unsafety
,
2064 generics
: Generics
{
2065 lifetimes
: self.lifetimes
.clean(cx
),
2066 type_params
: Vec
::new(),
2067 where_predicates
: Vec
::new()
2069 decl
: self.decl
.clean(cx
),
2070 abi
: self.abi
.to_string(),
2075 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2078 pub mutability
: Mutability
,
2079 /// It's useful to have the value of a static documented, but I have no
2080 /// desire to represent expressions (that'd basically be all of the AST,
2081 /// which is huge!). So, have a string.
2085 impl Clean
<Item
> for doctree
::Static
{
2086 fn clean(&self, cx
: &DocContext
) -> Item
{
2087 debug
!("cleaning static {}: {:?}", self.name
.clean(cx
), self);
2089 name
: Some(self.name
.clean(cx
)),
2090 attrs
: self.attrs
.clean(cx
),
2091 source
: self.whence
.clean(cx
),
2092 def_id
: ast_util
::local_def(self.id
),
2093 visibility
: self.vis
.clean(cx
),
2094 stability
: self.stab
.clean(cx
),
2095 inner
: StaticItem(Static
{
2096 type_
: self.type_
.clean(cx
),
2097 mutability
: self.mutability
.clean(cx
),
2098 expr
: self.expr
.span
.to_src(cx
),
2104 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2105 pub struct Constant
{
2110 impl Clean
<Item
> for doctree
::Constant
{
2111 fn clean(&self, cx
: &DocContext
) -> Item
{
2113 name
: Some(self.name
.clean(cx
)),
2114 attrs
: self.attrs
.clean(cx
),
2115 source
: self.whence
.clean(cx
),
2116 def_id
: ast_util
::local_def(self.id
),
2117 visibility
: self.vis
.clean(cx
),
2118 stability
: self.stab
.clean(cx
),
2119 inner
: ConstantItem(Constant
{
2120 type_
: self.type_
.clean(cx
),
2121 expr
: self.expr
.span
.to_src(cx
),
2127 #[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)]
2128 pub enum Mutability
{
2133 impl Clean
<Mutability
> for ast
::Mutability
{
2134 fn clean(&self, _
: &DocContext
) -> Mutability
{
2136 &ast
::MutMutable
=> Mutable
,
2137 &ast
::MutImmutable
=> Immutable
,
2142 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)]
2143 pub enum ImplPolarity
{
2148 impl Clean
<ImplPolarity
> for ast
::ImplPolarity
{
2149 fn clean(&self, _
: &DocContext
) -> ImplPolarity
{
2151 &ast
::ImplPolarity
::Positive
=> ImplPolarity
::Positive
,
2152 &ast
::ImplPolarity
::Negative
=> ImplPolarity
::Negative
,
2157 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2159 pub unsafety
: ast
::Unsafety
,
2160 pub generics
: Generics
,
2161 pub trait_
: Option
<Type
>,
2163 pub items
: Vec
<Item
>,
2165 pub polarity
: Option
<ImplPolarity
>,
2168 fn detect_derived
<M
: AttrMetaMethods
>(attrs
: &[M
]) -> bool
{
2169 attr
::contains_name(attrs
, "automatically_derived")
2172 impl Clean
<Item
> for doctree
::Impl
{
2173 fn clean(&self, cx
: &DocContext
) -> Item
{
2176 attrs
: self.attrs
.clean(cx
),
2177 source
: self.whence
.clean(cx
),
2178 def_id
: ast_util
::local_def(self.id
),
2179 visibility
: self.vis
.clean(cx
),
2180 stability
: self.stab
.clean(cx
),
2181 inner
: ImplItem(Impl
{
2182 unsafety
: self.unsafety
,
2183 generics
: self.generics
.clean(cx
),
2184 trait_
: self.trait_
.clean(cx
),
2185 for_
: self.for_
.clean(cx
),
2186 items
: self.items
.clean(cx
),
2187 derived
: detect_derived(&self.attrs
),
2188 polarity
: Some(self.polarity
.clean(cx
)),
2194 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2195 pub struct DefaultImpl
{
2196 pub unsafety
: ast
::Unsafety
,
2200 impl Clean
<Item
> for doctree
::DefaultImpl
{
2201 fn clean(&self, cx
: &DocContext
) -> Item
{
2204 attrs
: self.attrs
.clean(cx
),
2205 source
: self.whence
.clean(cx
),
2206 def_id
: ast_util
::local_def(self.id
),
2207 visibility
: Some(ast
::Public
),
2209 inner
: DefaultImplItem(DefaultImpl
{
2210 unsafety
: self.unsafety
,
2211 trait_
: self.trait_
.clean(cx
),
2217 impl Clean
<Item
> for doctree
::ExternCrate
{
2218 fn clean(&self, cx
: &DocContext
) -> Item
{
2221 attrs
: self.attrs
.clean(cx
),
2222 source
: self.whence
.clean(cx
),
2223 def_id
: ast_util
::local_def(0),
2224 visibility
: self.vis
.clean(cx
),
2226 inner
: ExternCrateItem(self.name
.clean(cx
), self.path
.clone())
2231 impl Clean
<Vec
<Item
>> for doctree
::Import
{
2232 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
2233 // We consider inlining the documentation of `pub use` statements, but we
2234 // forcefully don't inline if this is not public or if the
2235 // #[doc(no_inline)] attribute is present.
2236 let denied
= self.vis
!= ast
::Public
|| self.attrs
.iter().any(|a
| {
2237 &a
.name()[..] == "doc" && match a
.meta_item_list() {
2238 Some(l
) => attr
::contains_name(l
, "no_inline"),
2242 let (mut ret
, inner
) = match self.node
{
2243 ast
::ViewPathGlob(ref p
) => {
2244 (vec
![], GlobImport(resolve_use_source(cx
, p
.clean(cx
), self.id
)))
2246 ast
::ViewPathList(ref p
, ref list
) => {
2247 // Attempt to inline all reexported items, but be sure
2248 // to keep any non-inlineable reexports so they can be
2249 // listed in the documentation.
2250 let mut ret
= vec
![];
2251 let remaining
= if !denied
{
2252 let mut remaining
= vec
![];
2254 match inline
::try_inline(cx
, path
.node
.id(), None
) {
2256 ret
.extend(items
.into_iter());
2259 remaining
.push(path
.clean(cx
));
2267 if remaining
.is_empty() {
2270 (ret
, ImportList(resolve_use_source(cx
, p
.clean(cx
), self.id
),
2273 ast
::ViewPathSimple(i
, ref p
) => {
2275 match inline
::try_inline(cx
, self.id
, Some(i
)) {
2276 Some(items
) => return items
,
2280 (vec
![], SimpleImport(i
.clean(cx
),
2281 resolve_use_source(cx
, p
.clean(cx
), self.id
)))
2286 attrs
: self.attrs
.clean(cx
),
2287 source
: self.whence
.clean(cx
),
2288 def_id
: ast_util
::local_def(0),
2289 visibility
: self.vis
.clean(cx
),
2291 inner
: ImportItem(inner
)
2297 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2299 // use source as str;
2300 SimpleImport(String
, ImportSource
),
2302 GlobImport(ImportSource
),
2303 // use source::{a, b, c};
2304 ImportList(ImportSource
, Vec
<ViewListIdent
>),
2307 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2308 pub struct ImportSource
{
2310 pub did
: Option
<ast
::DefId
>,
2313 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2314 pub struct ViewListIdent
{
2316 pub source
: Option
<ast
::DefId
>,
2319 impl Clean
<ViewListIdent
> for ast
::PathListItem
{
2320 fn clean(&self, cx
: &DocContext
) -> ViewListIdent
{
2322 ast
::PathListIdent { id, name }
=> ViewListIdent
{
2323 name
: name
.clean(cx
),
2324 source
: resolve_def(cx
, id
)
2326 ast
::PathListMod { id }
=> ViewListIdent
{
2327 name
: "self".to_string(),
2328 source
: resolve_def(cx
, id
)
2334 impl Clean
<Vec
<Item
>> for ast
::ForeignMod
{
2335 fn clean(&self, cx
: &DocContext
) -> Vec
<Item
> {
2336 let mut items
= self.items
.clean(cx
);
2337 for item
in &mut items
{
2339 ForeignFunctionItem(ref mut f
) => f
.abi
= self.abi
,
2347 impl Clean
<Item
> for ast
::ForeignItem
{
2348 fn clean(&self, cx
: &DocContext
) -> Item
{
2349 let inner
= match self.node
{
2350 ast
::ForeignItemFn(ref decl
, ref generics
) => {
2351 ForeignFunctionItem(Function
{
2352 decl
: decl
.clean(cx
),
2353 generics
: generics
.clean(cx
),
2354 unsafety
: ast
::Unsafety
::Unsafe
,
2358 ast
::ForeignItemStatic(ref ty
, mutbl
) => {
2359 ForeignStaticItem(Static
{
2360 type_
: ty
.clean(cx
),
2361 mutability
: if mutbl {Mutable}
else {Immutable}
,
2362 expr
: "".to_string(),
2367 name
: Some(self.ident
.clean(cx
)),
2368 attrs
: self.attrs
.clean(cx
),
2369 source
: self.span
.clean(cx
),
2370 def_id
: ast_util
::local_def(self.id
),
2371 visibility
: self.vis
.clean(cx
),
2372 stability
: get_stability(cx
, ast_util
::local_def(self.id
)),
2381 fn to_src(&self, cx
: &DocContext
) -> String
;
2384 impl ToSource
for syntax
::codemap
::Span
{
2385 fn to_src(&self, cx
: &DocContext
) -> String
{
2386 debug
!("converting span {:?} to snippet", self.clean(cx
));
2387 let sn
= match cx
.sess().codemap().span_to_snippet(*self) {
2388 Ok(x
) => x
.to_string(),
2389 Err(_
) => "".to_string()
2391 debug
!("got snippet {}", sn
);
2396 fn lit_to_string(lit
: &ast
::Lit
) -> String
{
2398 ast
::LitStr(ref st
, _
) => st
.to_string(),
2399 ast
::LitBinary(ref data
) => format
!("{:?}", data
),
2400 ast
::LitByte(b
) => {
2401 let mut res
= String
::from_str("b'");
2402 for c
in (b
as char).escape_default() {
2408 ast
::LitChar(c
) => format
!("'{}'", c
),
2409 ast
::LitInt(i
, _t
) => i
.to_string(),
2410 ast
::LitFloat(ref f
, _t
) => f
.to_string(),
2411 ast
::LitFloatUnsuffixed(ref f
) => f
.to_string(),
2412 ast
::LitBool(b
) => b
.to_string(),
2416 fn name_from_pat(p
: &ast
::Pat
) -> String
{
2418 debug
!("Trying to get a name from pattern: {:?}", p
);
2421 PatWild(PatWildSingle
) => "_".to_string(),
2422 PatWild(PatWildMulti
) => "..".to_string(),
2423 PatIdent(_
, ref p
, _
) => token
::get_ident(p
.node
).to_string(),
2424 PatEnum(ref p
, _
) => path_to_string(p
),
2425 PatStruct(ref name
, ref fields
, etc
) => {
2426 format
!("{} {{ {}{} }}", path_to_string(name
),
2427 fields
.iter().map(|&Spanned { node: ref fp, .. }
|
2428 format
!("{}: {}", fp
.ident
.as_str(), name_from_pat(&*fp
.pat
)))
2429 .collect
::<Vec
<String
>>().connect(", "),
2430 if etc { ", ..." }
else { "" }
2433 PatTup(ref elts
) => format
!("({})", elts
.iter().map(|p
| name_from_pat(&**p
))
2434 .collect
::<Vec
<String
>>().connect(", ")),
2435 PatBox(ref p
) => name_from_pat(&**p
),
2436 PatRegion(ref p
, _
) => name_from_pat(&**p
),
2438 warn
!("tried to get argument name from PatLit, \
2439 which is silly in function arguments");
2442 PatRange(..) => panic
!("tried to get argument name from PatRange, \
2443 which is not allowed in function arguments"),
2444 PatVec(ref begin
, ref mid
, ref end
) => {
2445 let begin
= begin
.iter().map(|p
| name_from_pat(&**p
));
2446 let mid
= mid
.as_ref().map(|p
| format
!("..{}", name_from_pat(&**p
))).into_iter();
2447 let end
= end
.iter().map(|p
| name_from_pat(&**p
));
2448 format
!("[{}]", begin
.chain(mid
).chain(end
).collect
::<Vec
<_
>>().connect(", "))
2451 warn
!("can't document the name of a function argument \
2452 produced by a pattern macro");
2453 "(argument produced by macro)".to_string()
2458 /// Given a Type, resolve it using the def_map
2459 fn resolve_type(cx
: &DocContext
,
2461 id
: ast
::NodeId
) -> Type
{
2462 let tcx
= match cx
.tcx_opt() {
2464 // If we're extracting tests, this return value doesn't matter.
2465 None
=> return Primitive(Bool
),
2467 debug
!("searching for {} in defmap", id
);
2468 let def
= match tcx
.def_map
.borrow().get(&id
) {
2469 Some(k
) => k
.full_def(),
2470 None
=> panic
!("unresolved id not in defmap")
2474 def
::DefSelfTy(..) if path
.segments
.len() == 1 => {
2475 return Generic(token
::get_name(special_idents
::type_self
.name
).to_string());
2477 def
::DefPrimTy(p
) => match p
{
2478 ast
::TyStr
=> return Primitive(Str
),
2479 ast
::TyBool
=> return Primitive(Bool
),
2480 ast
::TyChar
=> return Primitive(Char
),
2481 ast
::TyInt(ast
::TyIs
) => return Primitive(Isize
),
2482 ast
::TyInt(ast
::TyI8
) => return Primitive(I8
),
2483 ast
::TyInt(ast
::TyI16
) => return Primitive(I16
),
2484 ast
::TyInt(ast
::TyI32
) => return Primitive(I32
),
2485 ast
::TyInt(ast
::TyI64
) => return Primitive(I64
),
2486 ast
::TyUint(ast
::TyUs
) => return Primitive(Usize
),
2487 ast
::TyUint(ast
::TyU8
) => return Primitive(U8
),
2488 ast
::TyUint(ast
::TyU16
) => return Primitive(U16
),
2489 ast
::TyUint(ast
::TyU32
) => return Primitive(U32
),
2490 ast
::TyUint(ast
::TyU64
) => return Primitive(U64
),
2491 ast
::TyFloat(ast
::TyF32
) => return Primitive(F32
),
2492 ast
::TyFloat(ast
::TyF64
) => return Primitive(F64
),
2494 def
::DefTyParam(_
, _
, _
, n
) => {
2495 return Generic(token
::get_name(n
).to_string())
2499 let did
= register_def(&*cx
, def
);
2500 ResolvedPath { path: path, typarams: None, did: did }
2503 fn register_def(cx
: &DocContext
, def
: def
::Def
) -> ast
::DefId
{
2504 let (did
, kind
) = match def
{
2505 def
::DefFn(i
, _
) => (i
, TypeFunction
),
2506 def
::DefTy(i
, false) => (i
, TypeTypedef
),
2507 def
::DefTy(i
, true) => (i
, TypeEnum
),
2508 def
::DefTrait(i
) => (i
, TypeTrait
),
2509 def
::DefStruct(i
) => (i
, TypeStruct
),
2510 def
::DefMod(i
) => (i
, TypeModule
),
2511 def
::DefStatic(i
, _
) => (i
, TypeStatic
),
2512 def
::DefVariant(i
, _
, _
) => (i
, TypeEnum
),
2513 _
=> return def
.def_id()
2515 if ast_util
::is_local(did
) { return did }
2516 let tcx
= match cx
.tcx_opt() {
2520 inline
::record_extern_fqn(cx
, did
, kind
);
2521 if let TypeTrait
= kind
{
2522 let t
= inline
::build_external_trait(cx
, tcx
, did
);
2523 cx
.external_traits
.borrow_mut().as_mut().unwrap().insert(did
, t
);
2528 fn resolve_use_source(cx
: &DocContext
, path
: Path
, id
: ast
::NodeId
) -> ImportSource
{
2531 did
: resolve_def(cx
, id
),
2535 fn resolve_def(cx
: &DocContext
, id
: ast
::NodeId
) -> Option
<ast
::DefId
> {
2536 cx
.tcx_opt().and_then(|tcx
| {
2537 tcx
.def_map
.borrow().get(&id
).map(|d
| register_def(cx
, d
.full_def()))
2541 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2546 impl Clean
<Item
> for doctree
::Macro
{
2547 fn clean(&self, cx
: &DocContext
) -> Item
{
2549 name
: Some(format
!("{}!", self.name
.clean(cx
))),
2550 attrs
: self.attrs
.clean(cx
),
2551 source
: self.whence
.clean(cx
),
2552 visibility
: ast
::Public
.clean(cx
),
2553 stability
: self.stab
.clean(cx
),
2554 def_id
: ast_util
::local_def(self.id
),
2555 inner
: MacroItem(Macro
{
2556 source
: self.whence
.to_src(cx
),
2562 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
2563 pub struct Stability
{
2564 pub level
: attr
::StabilityLevel
,
2565 pub feature
: String
,
2567 pub deprecated_since
: String
,
2571 impl Clean
<Stability
> for attr
::Stability
{
2572 fn clean(&self, _
: &DocContext
) -> Stability
{
2575 feature
: self.feature
.to_string(),
2576 since
: self.since
.as_ref().map_or("".to_string(),
2577 |interned
| interned
.to_string()),
2578 deprecated_since
: self.deprecated_since
.as_ref().map_or("".to_string(),
2579 |istr
| istr
.to_string()),
2580 reason
: self.reason
.as_ref().map_or("".to_string(),
2581 |interned
| interned
.to_string()),
2586 impl Clean
<Item
> for ty
::AssociatedType
{
2587 fn clean(&self, cx
: &DocContext
) -> Item
{
2588 // When loading a cross-crate associated type, the bounds for this type
2589 // are actually located on the trait/impl itself, so we need to load
2590 // all of the generics from there and then look for bounds that are
2591 // applied to this associated type in question.
2592 let predicates
= ty
::lookup_predicates(cx
.tcx(), self.container
.id());
2593 let generics
= match self.container
{
2594 ty
::TraitContainer(did
) => {
2595 let def
= ty
::lookup_trait_def(cx
.tcx(), did
);
2596 (&def
.generics
, &predicates
, subst
::TypeSpace
).clean(cx
)
2598 ty
::ImplContainer(did
) => {
2599 let ty
= ty
::lookup_item_type(cx
.tcx(), did
);
2600 (&ty
.generics
, &predicates
, subst
::TypeSpace
).clean(cx
)
2603 let my_name
= self.name
.clean(cx
);
2604 let mut bounds
= generics
.where_predicates
.iter().filter_map(|pred
| {
2605 let (name
, self_type
, trait_
, bounds
) = match *pred
{
2606 WherePredicate
::BoundPredicate
{
2607 ty
: QPath { ref name, ref self_type, ref trait_ }
,
2609 } => (name
, self_type
, trait_
, bounds
),
2612 if *name
!= my_name { return None }
2614 ResolvedPath { did, .. }
if did
== self.container
.id() => {}
2618 Generic(ref s
) if *s
== "Self" => {}
2622 }).flat_map(|i
| i
.iter().cloned()).collect
::<Vec
<_
>>();
2624 // Our Sized/?Sized bound didn't get handled when creating the generics
2625 // because we didn't actually get our whole set of bounds until just now
2626 // (some of them may have come from the trait). If we do have a sized
2627 // bound, we remove it, and if we don't then we add the `?Sized` bound
2629 match bounds
.iter().position(|b
| b
.is_sized_bound(cx
)) {
2630 Some(i
) => { bounds.remove(i); }
2631 None
=> bounds
.push(TyParamBound
::maybe_sized(cx
)),
2635 source
: DUMMY_SP
.clean(cx
),
2636 name
: Some(self.name
.clean(cx
)),
2637 attrs
: inline
::load_attrs(cx
, cx
.tcx(), self.def_id
),
2638 inner
: AssociatedTypeItem(bounds
, None
),
2639 visibility
: self.vis
.clean(cx
),
2640 def_id
: self.def_id
,
2641 stability
: stability
::lookup(cx
.tcx(), self.def_id
).clean(cx
),
2646 impl<'a
> Clean
<Typedef
> for (ty
::TypeScheme
<'a
>, ty
::GenericPredicates
<'a
>,
2648 fn clean(&self, cx
: &DocContext
) -> Typedef
{
2649 let (ref ty_scheme
, ref predicates
, ps
) = *self;
2651 type_
: ty_scheme
.ty
.clean(cx
),
2652 generics
: (&ty_scheme
.generics
, predicates
, ps
).clean(cx
)
2657 fn lang_struct(cx
: &DocContext
, did
: Option
<ast
::DefId
>,
2658 t
: ty
::Ty
, name
: &str,
2659 fallback
: fn(Box
<Type
>) -> Type
) -> Type
{
2660 let did
= match did
{
2662 None
=> return fallback(box t
.clean(cx
)),
2664 let fqn
= csearch
::get_item_path(cx
.tcx(), did
);
2665 let fqn
: Vec
<String
> = fqn
.into_iter().map(|i
| {
2668 cx
.external_paths
.borrow_mut().as_mut().unwrap().insert(did
, (fqn
, TypeStruct
));
2674 segments
: vec
![PathSegment
{
2675 name
: name
.to_string(),
2676 params
: PathParameters
::AngleBracketed
{
2678 types
: vec
![t
.clean(cx
)],
2686 /// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
2687 #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)]
2688 pub struct TypeBinding
{
2693 impl Clean
<TypeBinding
> for ast
::TypeBinding
{
2694 fn clean(&self, cx
: &DocContext
) -> TypeBinding
{
2696 name
: self.ident
.clean(cx
),
2697 ty
: self.ty
.clean(cx
)