]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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. | |
4 | // | |
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. | |
10 | ||
11 | //! This module contains the "cleaned" pieces of the AST, and the functions | |
12 | //! that clean them. | |
13 | ||
1a4d82fc | 14 | pub use self::Type::*; |
1a4d82fc | 15 | pub use self::Mutability::*; |
1a4d82fc | 16 | pub use self::ItemEnum::*; |
1a4d82fc JJ |
17 | pub use self::TyParamBound::*; |
18 | pub use self::SelfTy::*; | |
19 | pub use self::FunctionRetTy::*; | |
a7813a04 | 20 | pub use self::Visibility::*; |
1a4d82fc | 21 | |
7453a54e | 22 | use syntax::abi::Abi; |
1a4d82fc | 23 | use syntax::ast; |
b039eaaf | 24 | use syntax::attr; |
3157f602 | 25 | use syntax::codemap::Spanned; |
1a4d82fc | 26 | use syntax::ptr::P; |
476ff2be | 27 | use syntax::symbol::keywords; |
3157f602 | 28 | use syntax_pos::{self, DUMMY_SP, Pos}; |
1a4d82fc | 29 | |
a7813a04 | 30 | use rustc::middle::privacy::AccessLevels; |
32a655c1 | 31 | use rustc::middle::resolve_lifetime as rl; |
476ff2be | 32 | use rustc::middle::lang_items; |
c30ab7b3 | 33 | use rustc::hir::def::{Def, CtorKind}; |
476ff2be | 34 | use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; |
9e0c209e SL |
35 | use rustc::ty::subst::Substs; |
36 | use rustc::ty::{self, AdtKind}; | |
1a4d82fc | 37 | use rustc::middle::stability; |
476ff2be | 38 | use rustc::util::nodemap::{FxHashMap, FxHashSet}; |
7cac9316 | 39 | use rustc_typeck::hir_ty_to_ty; |
1a4d82fc | 40 | |
54a0048b | 41 | use rustc::hir; |
e9174d1e | 42 | |
cc61c64b | 43 | use std::{mem, slice, vec}; |
9346a6ac | 44 | use std::path::PathBuf; |
1a4d82fc | 45 | use std::rc::Rc; |
a7813a04 | 46 | use std::sync::Arc; |
1a4d82fc | 47 | use std::u32; |
1a4d82fc JJ |
48 | |
49 | use core::DocContext; | |
50 | use doctree; | |
51 | use visit_ast; | |
54a0048b | 52 | use html::item_type::ItemType; |
1a4d82fc | 53 | |
a7813a04 | 54 | pub mod inline; |
9346a6ac | 55 | mod simplify; |
1a4d82fc JJ |
56 | |
57 | // extract the stability index for a node from tcx, if possible | |
e9174d1e | 58 | fn get_stability(cx: &DocContext, def_id: DefId) -> Option<Stability> { |
476ff2be | 59 | cx.tcx.lookup_stability(def_id).clean(cx) |
9cc50fc6 SL |
60 | } |
61 | ||
62 | fn get_deprecation(cx: &DocContext, def_id: DefId) -> Option<Deprecation> { | |
476ff2be | 63 | cx.tcx.lookup_deprecation(def_id).clean(cx) |
1a4d82fc JJ |
64 | } |
65 | ||
66 | pub trait Clean<T> { | |
67 | fn clean(&self, cx: &DocContext) -> T; | |
68 | } | |
69 | ||
c34b1796 | 70 | impl<T: Clean<U>, U> Clean<Vec<U>> for [T] { |
1a4d82fc JJ |
71 | fn clean(&self, cx: &DocContext) -> Vec<U> { |
72 | self.iter().map(|x| x.clean(cx)).collect() | |
73 | } | |
74 | } | |
75 | ||
1a4d82fc JJ |
76 | impl<T: Clean<U>, U> Clean<U> for P<T> { |
77 | fn clean(&self, cx: &DocContext) -> U { | |
78 | (**self).clean(cx) | |
79 | } | |
80 | } | |
81 | ||
82 | impl<T: Clean<U>, U> Clean<U> for Rc<T> { | |
83 | fn clean(&self, cx: &DocContext) -> U { | |
84 | (**self).clean(cx) | |
85 | } | |
86 | } | |
87 | ||
88 | impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> { | |
89 | fn clean(&self, cx: &DocContext) -> Option<U> { | |
54a0048b | 90 | self.as_ref().map(|v| v.clean(cx)) |
1a4d82fc JJ |
91 | } |
92 | } | |
93 | ||
85aaf69f SL |
94 | impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> { |
95 | fn clean(&self, cx: &DocContext) -> U { | |
96 | self.0.clean(cx) | |
97 | } | |
98 | } | |
99 | ||
9cc50fc6 | 100 | impl<T: Clean<U>, U> Clean<Vec<U>> for P<[T]> { |
1a4d82fc JJ |
101 | fn clean(&self, cx: &DocContext) -> Vec<U> { |
102 | self.iter().map(|x| x.clean(cx)).collect() | |
103 | } | |
104 | } | |
105 | ||
a7813a04 | 106 | #[derive(Clone, Debug)] |
1a4d82fc JJ |
107 | pub struct Crate { |
108 | pub name: String, | |
c34b1796 | 109 | pub src: PathBuf, |
1a4d82fc | 110 | pub module: Option<Item>, |
476ff2be SL |
111 | pub externs: Vec<(CrateNum, ExternalCrate)>, |
112 | pub primitives: Vec<(DefId, PrimitiveType, Attributes)>, | |
a7813a04 XL |
113 | pub access_levels: Arc<AccessLevels<DefId>>, |
114 | // These are later on moved into `CACHEKEY`, leaving the map empty. | |
115 | // Only here so that they can be filtered through the rustdoc passes. | |
476ff2be | 116 | pub external_traits: FxHashMap<DefId, Trait>, |
1a4d82fc JJ |
117 | } |
118 | ||
119 | impl<'a, 'tcx> Clean<Crate> for visit_ast::RustdocVisitor<'a, 'tcx> { | |
120 | fn clean(&self, cx: &DocContext) -> Crate { | |
a7813a04 | 121 | use ::visit_lib::LibEmbargoVisitor; |
85aaf69f | 122 | |
476ff2be SL |
123 | { |
124 | let mut r = cx.renderinfo.borrow_mut(); | |
125 | r.deref_trait_did = cx.tcx.lang_items.deref_trait(); | |
126 | r.deref_mut_trait_did = cx.tcx.lang_items.deref_mut_trait(); | |
041b39d2 | 127 | r.owned_box_did = cx.tcx.lang_items.owned_box(); |
d9579d0f AL |
128 | } |
129 | ||
1a4d82fc | 130 | let mut externs = Vec::new(); |
92a42be0 | 131 | for cnum in cx.sess().cstore.crates() { |
476ff2be SL |
132 | externs.push((cnum, cnum.clean(cx))); |
133 | // Analyze doc-reachability for extern items | |
134 | LibEmbargoVisitor::new(cx).visit_lib(cnum); | |
92a42be0 | 135 | } |
1a4d82fc JJ |
136 | externs.sort_by(|&(a, _), &(b, _)| a.cmp(&b)); |
137 | ||
1a4d82fc JJ |
138 | // Clean the crate, translating the entire libsyntax AST to one that is |
139 | // understood by rustdoc. | |
140 | let mut module = self.module.clean(cx); | |
141 | ||
476ff2be | 142 | let ExternalCrate { name, src, primitives, .. } = LOCAL_CRATE.clean(cx); |
1a4d82fc JJ |
143 | { |
144 | let m = match module.inner { | |
145 | ModuleItem(ref mut m) => m, | |
146 | _ => unreachable!(), | |
147 | }; | |
476ff2be SL |
148 | m.items.extend(primitives.iter().map(|&(def_id, prim, ref attrs)| { |
149 | Item { | |
1a4d82fc JJ |
150 | source: Span::empty(), |
151 | name: Some(prim.to_url_str().to_string()), | |
476ff2be | 152 | attrs: attrs.clone(), |
a7813a04 | 153 | visibility: Some(Public), |
32a655c1 SL |
154 | stability: get_stability(cx, def_id), |
155 | deprecation: get_deprecation(cx, def_id), | |
476ff2be | 156 | def_id: def_id, |
1a4d82fc | 157 | inner: PrimitiveItem(prim), |
7453a54e | 158 | } |
476ff2be SL |
159 | })); |
160 | } | |
85aaf69f | 161 | |
a7813a04 XL |
162 | let mut access_levels = cx.access_levels.borrow_mut(); |
163 | let mut external_traits = cx.external_traits.borrow_mut(); | |
164 | ||
1a4d82fc | 165 | Crate { |
476ff2be | 166 | name: name, |
85aaf69f | 167 | src: src, |
1a4d82fc JJ |
168 | module: Some(module), |
169 | externs: externs, | |
170 | primitives: primitives, | |
a7813a04 XL |
171 | access_levels: Arc::new(mem::replace(&mut access_levels, Default::default())), |
172 | external_traits: mem::replace(&mut external_traits, Default::default()), | |
1a4d82fc JJ |
173 | } |
174 | } | |
175 | } | |
176 | ||
85aaf69f | 177 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
178 | pub struct ExternalCrate { |
179 | pub name: String, | |
476ff2be SL |
180 | pub src: PathBuf, |
181 | pub attrs: Attributes, | |
182 | pub primitives: Vec<(DefId, PrimitiveType, Attributes)>, | |
1a4d82fc JJ |
183 | } |
184 | ||
92a42be0 | 185 | impl Clean<ExternalCrate> for CrateNum { |
1a4d82fc | 186 | fn clean(&self, cx: &DocContext) -> ExternalCrate { |
476ff2be SL |
187 | let root = DefId { krate: *self, index: CRATE_DEF_INDEX }; |
188 | let krate_span = cx.tcx.def_span(root); | |
189 | let krate_src = cx.sess().codemap().span_to_filename(krate_span); | |
190 | ||
191 | // Collect all inner modules which are tagged as implementations of | |
192 | // primitives. | |
193 | // | |
194 | // Note that this loop only searches the top-level items of the crate, | |
195 | // and this is intentional. If we were to search the entire crate for an | |
196 | // item tagged with `#[doc(primitive)]` then we would also have to | |
197 | // search the entirety of external modules for items tagged | |
198 | // `#[doc(primitive)]`, which is a pretty inefficient process (decoding | |
199 | // all that metadata unconditionally). | |
200 | // | |
201 | // In order to keep the metadata load under control, the | |
202 | // `#[doc(primitive)]` feature is explicitly designed to only allow the | |
203 | // primitive tags to show up as the top level items in a crate. | |
204 | // | |
205 | // Also note that this does not attempt to deal with modules tagged | |
206 | // duplicately for the same primitive. This is handled later on when | |
207 | // rendering by delegating everything to a hash map. | |
208 | let as_primitive = |def: Def| { | |
209 | if let Def::Mod(def_id) = def { | |
210 | let attrs = cx.tcx.get_attrs(def_id).clean(cx); | |
211 | let mut prim = None; | |
212 | for attr in attrs.lists("doc") { | |
213 | if let Some(v) = attr.value_str() { | |
214 | if attr.check_name("primitive") { | |
215 | prim = PrimitiveType::from_str(&v.as_str()); | |
216 | if prim.is_some() { | |
217 | break; | |
218 | } | |
219 | } | |
220 | } | |
221 | } | |
222 | return prim.map(|p| (def_id, p, attrs)); | |
92a42be0 | 223 | } |
476ff2be SL |
224 | None |
225 | }; | |
226 | let primitives = if root.is_local() { | |
32a655c1 SL |
227 | cx.tcx.hir.krate().module.item_ids.iter().filter_map(|&id| { |
228 | let item = cx.tcx.hir.expect_item(id.id); | |
476ff2be SL |
229 | match item.node { |
230 | hir::ItemMod(_) => { | |
32a655c1 | 231 | as_primitive(Def::Mod(cx.tcx.hir.local_def_id(id.id))) |
476ff2be SL |
232 | } |
233 | hir::ItemUse(ref path, hir::UseKind::Single) | |
234 | if item.vis == hir::Visibility::Public => { | |
235 | as_primitive(path.def).map(|(_, prim, attrs)| { | |
236 | // Pretend the primitive is local. | |
32a655c1 | 237 | (cx.tcx.hir.local_def_id(id.id), prim, attrs) |
476ff2be SL |
238 | }) |
239 | } | |
240 | _ => None | |
241 | } | |
242 | }).collect() | |
243 | } else { | |
041b39d2 | 244 | cx.tcx.sess.cstore.item_children(root, cx.tcx.sess).iter().map(|item| item.def) |
476ff2be SL |
245 | .filter_map(as_primitive).collect() |
246 | }; | |
247 | ||
1a4d82fc | 248 | ExternalCrate { |
476ff2be SL |
249 | name: cx.tcx.crate_name(*self).to_string(), |
250 | src: PathBuf::from(krate_src), | |
251 | attrs: cx.tcx.get_attrs(root).clean(cx), | |
1a4d82fc JJ |
252 | primitives: primitives, |
253 | } | |
254 | } | |
255 | } | |
256 | ||
257 | /// Anything with a source location and set of attributes and, optionally, a | |
258 | /// name. That is, anything that can be documented. This doesn't correspond | |
259 | /// directly to the AST's concept of an item; it's a strict superset. | |
85aaf69f | 260 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
261 | pub struct Item { |
262 | /// Stringified span | |
263 | pub source: Span, | |
264 | /// Not everything has a name. E.g., impls | |
265 | pub name: Option<String>, | |
476ff2be | 266 | pub attrs: Attributes, |
1a4d82fc JJ |
267 | pub inner: ItemEnum, |
268 | pub visibility: Option<Visibility>, | |
e9174d1e | 269 | pub def_id: DefId, |
1a4d82fc | 270 | pub stability: Option<Stability>, |
9cc50fc6 | 271 | pub deprecation: Option<Deprecation>, |
1a4d82fc JJ |
272 | } |
273 | ||
274 | impl Item { | |
1a4d82fc JJ |
275 | /// Finds the `doc` attribute as a NameValue and returns the corresponding |
276 | /// value found. | |
277 | pub fn doc_value<'a>(&'a self) -> Option<&'a str> { | |
476ff2be | 278 | self.attrs.doc_value() |
1a4d82fc | 279 | } |
54a0048b SL |
280 | pub fn is_crate(&self) -> bool { |
281 | match self.inner { | |
282 | StrippedItem(box ModuleItem(Module { is_crate: true, ..})) | | |
283 | ModuleItem(Module { is_crate: true, ..}) => true, | |
284 | _ => false, | |
1a4d82fc | 285 | } |
1a4d82fc | 286 | } |
1a4d82fc | 287 | pub fn is_mod(&self) -> bool { |
c30ab7b3 | 288 | self.type_() == ItemType::Module |
1a4d82fc JJ |
289 | } |
290 | pub fn is_trait(&self) -> bool { | |
c30ab7b3 | 291 | self.type_() == ItemType::Trait |
1a4d82fc JJ |
292 | } |
293 | pub fn is_struct(&self) -> bool { | |
c30ab7b3 | 294 | self.type_() == ItemType::Struct |
1a4d82fc JJ |
295 | } |
296 | pub fn is_enum(&self) -> bool { | |
cc61c64b | 297 | self.type_() == ItemType::Enum |
1a4d82fc JJ |
298 | } |
299 | pub fn is_fn(&self) -> bool { | |
c30ab7b3 | 300 | self.type_() == ItemType::Function |
54a0048b SL |
301 | } |
302 | pub fn is_associated_type(&self) -> bool { | |
c30ab7b3 | 303 | self.type_() == ItemType::AssociatedType |
54a0048b SL |
304 | } |
305 | pub fn is_associated_const(&self) -> bool { | |
c30ab7b3 | 306 | self.type_() == ItemType::AssociatedConst |
54a0048b SL |
307 | } |
308 | pub fn is_method(&self) -> bool { | |
c30ab7b3 | 309 | self.type_() == ItemType::Method |
54a0048b SL |
310 | } |
311 | pub fn is_ty_method(&self) -> bool { | |
c30ab7b3 | 312 | self.type_() == ItemType::TyMethod |
54a0048b | 313 | } |
041b39d2 XL |
314 | pub fn is_typedef(&self) -> bool { |
315 | self.type_() == ItemType::Typedef | |
316 | } | |
5bcae85e | 317 | pub fn is_primitive(&self) -> bool { |
c30ab7b3 | 318 | self.type_() == ItemType::Primitive |
5bcae85e | 319 | } |
cc61c64b XL |
320 | pub fn is_union(&self) -> bool { |
321 | self.type_() == ItemType::Union | |
322 | } | |
54a0048b SL |
323 | pub fn is_stripped(&self) -> bool { |
324 | match self.inner { StrippedItem(..) => true, _ => false } | |
325 | } | |
326 | pub fn has_stripped_fields(&self) -> Option<bool> { | |
327 | match self.inner { | |
328 | StructItem(ref _struct) => Some(_struct.fields_stripped), | |
9e0c209e | 329 | UnionItem(ref union) => Some(union.fields_stripped), |
c30ab7b3 | 330 | VariantItem(Variant { kind: VariantKind::Struct(ref vstruct)} ) => { |
54a0048b SL |
331 | Some(vstruct.fields_stripped) |
332 | }, | |
333 | _ => None, | |
334 | } | |
1a4d82fc | 335 | } |
d9579d0f | 336 | |
8bb4bdeb XL |
337 | pub fn stability_class(&self) -> Option<String> { |
338 | self.stability.as_ref().and_then(|ref s| { | |
339 | let mut classes = Vec::with_capacity(2); | |
340 | ||
341 | if s.level == stability::Unstable { | |
342 | classes.push("unstable"); | |
343 | } | |
344 | ||
54a0048b | 345 | if !s.deprecated_since.is_empty() { |
8bb4bdeb XL |
346 | classes.push("deprecated"); |
347 | } | |
348 | ||
349 | if classes.len() != 0 { | |
350 | Some(classes.join(" ")) | |
351 | } else { | |
352 | None | |
d9579d0f | 353 | } |
8bb4bdeb | 354 | }) |
d9579d0f | 355 | } |
7453a54e SL |
356 | |
357 | pub fn stable_since(&self) -> Option<&str> { | |
54a0048b | 358 | self.stability.as_ref().map(|s| &s.since[..]) |
7453a54e | 359 | } |
c30ab7b3 SL |
360 | |
361 | /// Returns a documentation-level item type from the item. | |
362 | pub fn type_(&self) -> ItemType { | |
363 | ItemType::from(self) | |
364 | } | |
1a4d82fc JJ |
365 | } |
366 | ||
85aaf69f | 367 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc | 368 | pub enum ItemEnum { |
85aaf69f SL |
369 | ExternCrateItem(String, Option<String>), |
370 | ImportItem(Import), | |
1a4d82fc | 371 | StructItem(Struct), |
9e0c209e | 372 | UnionItem(Union), |
1a4d82fc JJ |
373 | EnumItem(Enum), |
374 | FunctionItem(Function), | |
375 | ModuleItem(Module), | |
62682a34 | 376 | TypedefItem(Typedef, bool /* is associated type */), |
1a4d82fc JJ |
377 | StaticItem(Static), |
378 | ConstantItem(Constant), | |
379 | TraitItem(Trait), | |
380 | ImplItem(Impl), | |
1a4d82fc JJ |
381 | /// A method signature only. Used for required methods in traits (ie, |
382 | /// non-default-methods). | |
383 | TyMethodItem(TyMethod), | |
384 | /// A method with a body. | |
385 | MethodItem(Method), | |
54a0048b | 386 | StructFieldItem(Type), |
1a4d82fc JJ |
387 | VariantItem(Variant), |
388 | /// `fn`s from an extern block | |
389 | ForeignFunctionItem(Function), | |
390 | /// `static`s from an extern block | |
391 | ForeignStaticItem(Static), | |
392 | MacroItem(Macro), | |
393 | PrimitiveItem(PrimitiveType), | |
d9579d0f | 394 | AssociatedConstItem(Type, Option<String>), |
c34b1796 AL |
395 | AssociatedTypeItem(Vec<TyParamBound>, Option<Type>), |
396 | DefaultImplItem(DefaultImpl), | |
54a0048b SL |
397 | /// An item that has been stripped by a rustdoc pass |
398 | StrippedItem(Box<ItemEnum>), | |
1a4d82fc JJ |
399 | } |
400 | ||
9e0c209e SL |
401 | impl ItemEnum { |
402 | pub fn generics(&self) -> Option<&Generics> { | |
403 | Some(match *self { | |
404 | ItemEnum::StructItem(ref s) => &s.generics, | |
405 | ItemEnum::EnumItem(ref e) => &e.generics, | |
406 | ItemEnum::FunctionItem(ref f) => &f.generics, | |
407 | ItemEnum::TypedefItem(ref t, _) => &t.generics, | |
408 | ItemEnum::TraitItem(ref t) => &t.generics, | |
409 | ItemEnum::ImplItem(ref i) => &i.generics, | |
410 | ItemEnum::TyMethodItem(ref i) => &i.generics, | |
411 | ItemEnum::MethodItem(ref i) => &i.generics, | |
412 | ItemEnum::ForeignFunctionItem(ref f) => &f.generics, | |
413 | _ => return None, | |
414 | }) | |
415 | } | |
416 | } | |
417 | ||
85aaf69f | 418 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
419 | pub struct Module { |
420 | pub items: Vec<Item>, | |
421 | pub is_crate: bool, | |
422 | } | |
423 | ||
424 | impl Clean<Item> for doctree::Module { | |
425 | fn clean(&self, cx: &DocContext) -> Item { | |
426 | let name = if self.name.is_some() { | |
427 | self.name.unwrap().clean(cx) | |
428 | } else { | |
429 | "".to_string() | |
430 | }; | |
85aaf69f SL |
431 | |
432 | let mut items: Vec<Item> = vec![]; | |
433 | items.extend(self.extern_crates.iter().map(|x| x.clean(cx))); | |
62682a34 | 434 | items.extend(self.imports.iter().flat_map(|x| x.clean(cx))); |
85aaf69f | 435 | items.extend(self.structs.iter().map(|x| x.clean(cx))); |
9e0c209e | 436 | items.extend(self.unions.iter().map(|x| x.clean(cx))); |
85aaf69f SL |
437 | items.extend(self.enums.iter().map(|x| x.clean(cx))); |
438 | items.extend(self.fns.iter().map(|x| x.clean(cx))); | |
62682a34 | 439 | items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx))); |
85aaf69f SL |
440 | items.extend(self.mods.iter().map(|x| x.clean(cx))); |
441 | items.extend(self.typedefs.iter().map(|x| x.clean(cx))); | |
442 | items.extend(self.statics.iter().map(|x| x.clean(cx))); | |
443 | items.extend(self.constants.iter().map(|x| x.clean(cx))); | |
444 | items.extend(self.traits.iter().map(|x| x.clean(cx))); | |
62682a34 | 445 | items.extend(self.impls.iter().flat_map(|x| x.clean(cx))); |
85aaf69f | 446 | items.extend(self.macros.iter().map(|x| x.clean(cx))); |
c34b1796 | 447 | items.extend(self.def_traits.iter().map(|x| x.clean(cx))); |
1a4d82fc JJ |
448 | |
449 | // determine if we should display the inner contents or | |
450 | // the outer `mod` item for the source code. | |
451 | let whence = { | |
452 | let cm = cx.sess().codemap(); | |
453 | let outer = cm.lookup_char_pos(self.where_outer.lo); | |
454 | let inner = cm.lookup_char_pos(self.where_inner.lo); | |
455 | if outer.file.start_pos == inner.file.start_pos { | |
456 | // mod foo { ... } | |
457 | self.where_outer | |
458 | } else { | |
459 | // mod foo; (and a separate FileMap for the contents) | |
460 | self.where_inner | |
461 | } | |
462 | }; | |
463 | ||
464 | Item { | |
465 | name: Some(name), | |
466 | attrs: self.attrs.clean(cx), | |
467 | source: whence.clean(cx), | |
468 | visibility: self.vis.clean(cx), | |
469 | stability: self.stab.clean(cx), | |
9cc50fc6 | 470 | deprecation: self.depr.clean(cx), |
32a655c1 | 471 | def_id: cx.tcx.hir.local_def_id(self.id), |
1a4d82fc JJ |
472 | inner: ModuleItem(Module { |
473 | is_crate: self.is_crate, | |
85aaf69f | 474 | items: items |
1a4d82fc JJ |
475 | }) |
476 | } | |
477 | } | |
478 | } | |
479 | ||
476ff2be SL |
480 | pub struct ListAttributesIter<'a> { |
481 | attrs: slice::Iter<'a, ast::Attribute>, | |
cc61c64b | 482 | current_list: vec::IntoIter<ast::NestedMetaItem>, |
476ff2be | 483 | name: &'a str |
54a0048b SL |
484 | } |
485 | ||
476ff2be | 486 | impl<'a> Iterator for ListAttributesIter<'a> { |
cc61c64b | 487 | type Item = ast::NestedMetaItem; |
476ff2be SL |
488 | |
489 | fn next(&mut self) -> Option<Self::Item> { | |
490 | if let Some(nested) = self.current_list.next() { | |
491 | return Some(nested); | |
54a0048b | 492 | } |
54a0048b | 493 | |
476ff2be | 494 | for attr in &mut self.attrs { |
cc61c64b | 495 | if let Some(list) = attr.meta_item_list() { |
476ff2be | 496 | if attr.check_name(self.name) { |
cc61c64b | 497 | self.current_list = list.into_iter(); |
476ff2be SL |
498 | if let Some(nested) = self.current_list.next() { |
499 | return Some(nested); | |
500 | } | |
54a0048b SL |
501 | } |
502 | } | |
503 | } | |
476ff2be | 504 | |
54a0048b SL |
505 | None |
506 | } | |
476ff2be | 507 | } |
54a0048b | 508 | |
476ff2be | 509 | pub trait AttributesExt { |
54a0048b | 510 | /// Finds an attribute as List and returns the list of attributes nested inside. |
7cac9316 | 511 | fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a>; |
476ff2be SL |
512 | } |
513 | ||
514 | impl AttributesExt for [ast::Attribute] { | |
515 | fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> { | |
516 | ListAttributesIter { | |
517 | attrs: self.iter(), | |
cc61c64b | 518 | current_list: Vec::new().into_iter(), |
476ff2be | 519 | name: name |
54a0048b | 520 | } |
54a0048b SL |
521 | } |
522 | } | |
523 | ||
476ff2be SL |
524 | pub trait NestedAttributesExt { |
525 | /// Returns whether the attribute list contains a specific `Word` | |
7cac9316 | 526 | fn has_word(self, word: &str) -> bool; |
476ff2be SL |
527 | } |
528 | ||
cc61c64b | 529 | impl<I: IntoIterator<Item=ast::NestedMetaItem>> NestedAttributesExt for I { |
476ff2be SL |
530 | fn has_word(self, word: &str) -> bool { |
531 | self.into_iter().any(|attr| attr.is_word() && attr.check_name(word)) | |
532 | } | |
533 | } | |
534 | ||
535 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug, Default)] | |
536 | pub struct Attributes { | |
537 | pub doc_strings: Vec<String>, | |
8bb4bdeb XL |
538 | pub other_attrs: Vec<ast::Attribute>, |
539 | pub span: Option<syntax_pos::Span>, | |
9e0c209e SL |
540 | } |
541 | ||
476ff2be SL |
542 | impl Attributes { |
543 | pub fn from_ast(attrs: &[ast::Attribute]) -> Attributes { | |
544 | let mut doc_strings = vec![]; | |
8bb4bdeb | 545 | let mut sp = None; |
476ff2be SL |
546 | let other_attrs = attrs.iter().filter_map(|attr| { |
547 | attr.with_desugared_doc(|attr| { | |
548 | if let Some(value) = attr.value_str() { | |
549 | if attr.check_name("doc") { | |
550 | doc_strings.push(value.to_string()); | |
8bb4bdeb XL |
551 | if sp.is_none() { |
552 | sp = Some(attr.span); | |
553 | } | |
476ff2be SL |
554 | return None; |
555 | } | |
556 | } | |
557 | ||
558 | Some(attr.clone()) | |
559 | }) | |
560 | }).collect(); | |
561 | Attributes { | |
562 | doc_strings: doc_strings, | |
8bb4bdeb XL |
563 | other_attrs: other_attrs, |
564 | span: sp, | |
9e0c209e SL |
565 | } |
566 | } | |
476ff2be SL |
567 | |
568 | /// Finds the `doc` attribute as a NameValue and returns the corresponding | |
569 | /// value found. | |
570 | pub fn doc_value<'a>(&'a self) -> Option<&'a str> { | |
571 | self.doc_strings.first().map(|s| &s[..]) | |
572 | } | |
1a4d82fc JJ |
573 | } |
574 | ||
476ff2be SL |
575 | impl AttributesExt for Attributes { |
576 | fn lists<'a>(&'a self, name: &'a str) -> ListAttributesIter<'a> { | |
577 | self.other_attrs.lists(name) | |
1a4d82fc JJ |
578 | } |
579 | } | |
580 | ||
476ff2be SL |
581 | impl Clean<Attributes> for [ast::Attribute] { |
582 | fn clean(&self, _cx: &DocContext) -> Attributes { | |
583 | Attributes::from_ast(self) | |
1a4d82fc JJ |
584 | } |
585 | } | |
586 | ||
85aaf69f | 587 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
588 | pub struct TyParam { |
589 | pub name: String, | |
e9174d1e | 590 | pub did: DefId, |
1a4d82fc JJ |
591 | pub bounds: Vec<TyParamBound>, |
592 | pub default: Option<Type>, | |
593 | } | |
594 | ||
e9174d1e | 595 | impl Clean<TyParam> for hir::TyParam { |
1a4d82fc JJ |
596 | fn clean(&self, cx: &DocContext) -> TyParam { |
597 | TyParam { | |
b039eaaf | 598 | name: self.name.clean(cx), |
32a655c1 | 599 | did: cx.tcx.hir.local_def_id(self.id), |
1a4d82fc JJ |
600 | bounds: self.bounds.clean(cx), |
601 | default: self.default.clean(cx), | |
602 | } | |
603 | } | |
604 | } | |
605 | ||
8bb4bdeb | 606 | impl<'tcx> Clean<TyParam> for ty::TypeParameterDef { |
1a4d82fc | 607 | fn clean(&self, cx: &DocContext) -> TyParam { |
a7813a04 | 608 | cx.renderinfo.borrow_mut().external_typarams.insert(self.def_id, self.name.clean(cx)); |
1a4d82fc JJ |
609 | TyParam { |
610 | name: self.name.clean(cx), | |
611 | did: self.def_id, | |
c34b1796 | 612 | bounds: vec![], // these are filled in from the where-clauses |
8bb4bdeb | 613 | default: if self.has_default { |
7cac9316 | 614 | Some(cx.tcx.type_of(self.def_id).clean(cx)) |
8bb4bdeb XL |
615 | } else { |
616 | None | |
617 | } | |
1a4d82fc JJ |
618 | } |
619 | } | |
620 | } | |
621 | ||
85aaf69f | 622 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
623 | pub enum TyParamBound { |
624 | RegionBound(Lifetime), | |
e9174d1e | 625 | TraitBound(PolyTrait, hir::TraitBoundModifier) |
1a4d82fc JJ |
626 | } |
627 | ||
9346a6ac AL |
628 | impl TyParamBound { |
629 | fn maybe_sized(cx: &DocContext) -> TyParamBound { | |
476ff2be SL |
630 | let did = cx.tcx.require_lang_item(lang_items::SizedTraitLangItem); |
631 | let empty = cx.tcx.intern_substs(&[]); | |
632 | let path = external_path(cx, &cx.tcx.item_name(did).as_str(), | |
633 | Some(did), false, vec![], empty); | |
634 | inline::record_extern_fqn(cx, did, TypeKind::Trait); | |
635 | TraitBound(PolyTrait { | |
636 | trait_: ResolvedPath { | |
637 | path: path, | |
638 | typarams: None, | |
639 | did: did, | |
640 | is_generic: false, | |
641 | }, | |
642 | lifetimes: vec![] | |
643 | }, hir::TraitBoundModifier::Maybe) | |
9346a6ac AL |
644 | } |
645 | ||
646 | fn is_sized_bound(&self, cx: &DocContext) -> bool { | |
54a0048b | 647 | use rustc::hir::TraitBoundModifier as TBM; |
476ff2be SL |
648 | if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, TBM::None) = *self { |
649 | if trait_.def_id() == cx.tcx.lang_items.sized_trait() { | |
650 | return true; | |
9346a6ac AL |
651 | } |
652 | } | |
653 | false | |
654 | } | |
655 | } | |
656 | ||
e9174d1e | 657 | impl Clean<TyParamBound> for hir::TyParamBound { |
1a4d82fc JJ |
658 | fn clean(&self, cx: &DocContext) -> TyParamBound { |
659 | match *self { | |
e9174d1e SL |
660 | hir::RegionTyParamBound(lt) => RegionBound(lt.clean(cx)), |
661 | hir::TraitTyParamBound(ref t, modifier) => TraitBound(t.clean(cx), modifier), | |
1a4d82fc JJ |
662 | } |
663 | } | |
664 | } | |
665 | ||
9e0c209e SL |
666 | fn external_path_params(cx: &DocContext, trait_did: Option<DefId>, has_self: bool, |
667 | bindings: Vec<TypeBinding>, substs: &Substs) -> PathParameters { | |
668 | let lifetimes = substs.regions().filter_map(|v| v.clean(cx)).collect(); | |
669 | let types = substs.types().skip(has_self as usize).collect::<Vec<_>>(); | |
1a4d82fc | 670 | |
476ff2be | 671 | match trait_did { |
1a4d82fc | 672 | // Attempt to sugar an external path like Fn<(A, B,), C> to Fn(A, B) -> C |
476ff2be | 673 | Some(did) if cx.tcx.lang_items.fn_trait_kind(did).is_some() => { |
85aaf69f | 674 | assert_eq!(types.len(), 1); |
1a4d82fc | 675 | let inputs = match types[0].sty { |
8bb4bdeb | 676 | ty::TyTuple(ref tys, _) => tys.iter().map(|t| t.clean(cx)).collect(), |
1a4d82fc JJ |
677 | _ => { |
678 | return PathParameters::AngleBracketed { | |
679 | lifetimes: lifetimes, | |
680 | types: types.clean(cx), | |
85aaf69f | 681 | bindings: bindings |
1a4d82fc JJ |
682 | } |
683 | } | |
684 | }; | |
85aaf69f SL |
685 | let output = None; |
686 | // FIXME(#20299) return type comes from a projection now | |
687 | // match types[1].sty { | |
8bb4bdeb | 688 | // ty::TyTuple(ref v, _) if v.is_empty() => None, // -> () |
85aaf69f SL |
689 | // _ => Some(types[1].clean(cx)) |
690 | // }; | |
1a4d82fc JJ |
691 | PathParameters::Parenthesized { |
692 | inputs: inputs, | |
693 | output: output | |
694 | } | |
695 | }, | |
476ff2be | 696 | _ => { |
1a4d82fc JJ |
697 | PathParameters::AngleBracketed { |
698 | lifetimes: lifetimes, | |
699 | types: types.clean(cx), | |
85aaf69f | 700 | bindings: bindings |
1a4d82fc JJ |
701 | } |
702 | } | |
703 | } | |
704 | } | |
705 | ||
706 | // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar | |
707 | // from Fn<(A, B,), C> to Fn(A, B) -> C | |
9e0c209e SL |
708 | fn external_path(cx: &DocContext, name: &str, trait_did: Option<DefId>, has_self: bool, |
709 | bindings: Vec<TypeBinding>, substs: &Substs) -> Path { | |
1a4d82fc JJ |
710 | Path { |
711 | global: false, | |
476ff2be | 712 | def: Def::Err, |
1a4d82fc JJ |
713 | segments: vec![PathSegment { |
714 | name: name.to_string(), | |
9e0c209e | 715 | params: external_path_params(cx, trait_did, has_self, bindings, substs) |
1a4d82fc JJ |
716 | }], |
717 | } | |
718 | } | |
719 | ||
1a4d82fc JJ |
720 | impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> { |
721 | fn clean(&self, cx: &DocContext) -> TyParamBound { | |
c30ab7b3 | 722 | inline::record_extern_fqn(cx, self.def_id, TypeKind::Trait); |
476ff2be | 723 | let path = external_path(cx, &cx.tcx.item_name(self.def_id).as_str(), |
9e0c209e | 724 | Some(self.def_id), true, vec![], self.substs); |
1a4d82fc | 725 | |
9e0c209e | 726 | debug!("ty::TraitRef\n subst: {:?}\n", self.substs); |
1a4d82fc JJ |
727 | |
728 | // collect any late bound regions | |
729 | let mut late_bounds = vec![]; | |
9e0c209e | 730 | for ty_s in self.input_types().skip(1) { |
8bb4bdeb | 731 | if let ty::TyTuple(ts, _) = ty_s.sty { |
85aaf69f | 732 | for &ty_s in ts { |
62682a34 | 733 | if let ty::TyRef(ref reg, _) = ty_s.sty { |
7cac9316 | 734 | if let &ty::RegionKind::ReLateBound(..) = *reg { |
1a4d82fc JJ |
735 | debug!(" hit an ReLateBound {:?}", reg); |
736 | if let Some(lt) = reg.clean(cx) { | |
54a0048b | 737 | late_bounds.push(lt); |
1a4d82fc JJ |
738 | } |
739 | } | |
740 | } | |
741 | } | |
742 | } | |
743 | } | |
744 | ||
54a0048b SL |
745 | TraitBound( |
746 | PolyTrait { | |
747 | trait_: ResolvedPath { | |
748 | path: path, | |
749 | typarams: None, | |
750 | did: self.def_id, | |
751 | is_generic: false, | |
752 | }, | |
753 | lifetimes: late_bounds, | |
62682a34 | 754 | }, |
54a0048b SL |
755 | hir::TraitBoundModifier::None |
756 | ) | |
1a4d82fc JJ |
757 | } |
758 | } | |
759 | ||
9e0c209e | 760 | impl<'tcx> Clean<Option<Vec<TyParamBound>>> for Substs<'tcx> { |
1a4d82fc JJ |
761 | fn clean(&self, cx: &DocContext) -> Option<Vec<TyParamBound>> { |
762 | let mut v = Vec::new(); | |
9e0c209e SL |
763 | v.extend(self.regions().filter_map(|r| r.clean(cx)) |
764 | .map(RegionBound)); | |
765 | v.extend(self.types().map(|t| TraitBound(PolyTrait { | |
1a4d82fc JJ |
766 | trait_: t.clean(cx), |
767 | lifetimes: vec![] | |
e9174d1e | 768 | }, hir::TraitBoundModifier::None))); |
9346a6ac | 769 | if !v.is_empty() {Some(v)} else {None} |
1a4d82fc JJ |
770 | } |
771 | } | |
772 | ||
85aaf69f | 773 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
774 | pub struct Lifetime(String); |
775 | ||
776 | impl Lifetime { | |
777 | pub fn get_ref<'a>(&'a self) -> &'a str { | |
778 | let Lifetime(ref s) = *self; | |
85aaf69f | 779 | let s: &'a str = s; |
c30ab7b3 | 780 | s |
1a4d82fc JJ |
781 | } |
782 | ||
783 | pub fn statik() -> Lifetime { | |
784 | Lifetime("'static".to_string()) | |
785 | } | |
786 | } | |
787 | ||
e9174d1e | 788 | impl Clean<Lifetime> for hir::Lifetime { |
9e0c209e | 789 | fn clean(&self, cx: &DocContext) -> Lifetime { |
476ff2be SL |
790 | let def = cx.tcx.named_region_map.defs.get(&self.id).cloned(); |
791 | match def { | |
32a655c1 SL |
792 | Some(rl::Region::EarlyBound(_, node_id)) | |
793 | Some(rl::Region::LateBound(_, node_id)) | | |
794 | Some(rl::Region::Free(_, node_id)) => { | |
476ff2be SL |
795 | if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() { |
796 | return lt; | |
9e0c209e | 797 | } |
9e0c209e | 798 | } |
476ff2be | 799 | _ => {} |
9e0c209e | 800 | } |
c1a9b12d | 801 | Lifetime(self.name.to_string()) |
1a4d82fc JJ |
802 | } |
803 | } | |
804 | ||
e9174d1e | 805 | impl Clean<Lifetime> for hir::LifetimeDef { |
1a4d82fc | 806 | fn clean(&self, _: &DocContext) -> Lifetime { |
a7813a04 XL |
807 | if self.bounds.len() > 0 { |
808 | let mut s = format!("{}: {}", | |
809 | self.lifetime.name.to_string(), | |
810 | self.bounds[0].name.to_string()); | |
811 | for bound in self.bounds.iter().skip(1) { | |
812 | s.push_str(&format!(" + {}", bound.name.to_string())); | |
813 | } | |
814 | Lifetime(s) | |
815 | } else { | |
816 | Lifetime(self.lifetime.name.to_string()) | |
817 | } | |
1a4d82fc JJ |
818 | } |
819 | } | |
820 | ||
32a655c1 | 821 | impl Clean<Lifetime> for ty::RegionParameterDef { |
1a4d82fc | 822 | fn clean(&self, _: &DocContext) -> Lifetime { |
c1a9b12d | 823 | Lifetime(self.name.to_string()) |
1a4d82fc JJ |
824 | } |
825 | } | |
826 | ||
7cac9316 | 827 | impl Clean<Option<Lifetime>> for ty::RegionKind { |
1a4d82fc JJ |
828 | fn clean(&self, cx: &DocContext) -> Option<Lifetime> { |
829 | match *self { | |
830 | ty::ReStatic => Some(Lifetime::statik()), | |
8bb4bdeb | 831 | ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())), |
9346a6ac | 832 | ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))), |
1a4d82fc JJ |
833 | |
834 | ty::ReLateBound(..) | | |
835 | ty::ReFree(..) | | |
836 | ty::ReScope(..) | | |
e9174d1e SL |
837 | ty::ReVar(..) | |
838 | ty::ReSkolemized(..) | | |
3157f602 XL |
839 | ty::ReEmpty | |
840 | ty::ReErased => None | |
1a4d82fc JJ |
841 | } |
842 | } | |
843 | } | |
844 | ||
85aaf69f | 845 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
846 | pub enum WherePredicate { |
847 | BoundPredicate { ty: Type, bounds: Vec<TyParamBound> }, | |
848 | RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>}, | |
cc61c64b | 849 | EqPredicate { lhs: Type, rhs: Type }, |
1a4d82fc JJ |
850 | } |
851 | ||
e9174d1e | 852 | impl Clean<WherePredicate> for hir::WherePredicate { |
1a4d82fc JJ |
853 | fn clean(&self, cx: &DocContext) -> WherePredicate { |
854 | match *self { | |
e9174d1e | 855 | hir::WherePredicate::BoundPredicate(ref wbp) => { |
1a4d82fc JJ |
856 | WherePredicate::BoundPredicate { |
857 | ty: wbp.bounded_ty.clean(cx), | |
858 | bounds: wbp.bounds.clean(cx) | |
859 | } | |
860 | } | |
861 | ||
e9174d1e | 862 | hir::WherePredicate::RegionPredicate(ref wrp) => { |
1a4d82fc JJ |
863 | WherePredicate::RegionPredicate { |
864 | lifetime: wrp.lifetime.clean(cx), | |
865 | bounds: wrp.bounds.clean(cx) | |
866 | } | |
867 | } | |
868 | ||
32a655c1 SL |
869 | hir::WherePredicate::EqPredicate(ref wrp) => { |
870 | WherePredicate::EqPredicate { | |
871 | lhs: wrp.lhs_ty.clean(cx), | |
872 | rhs: wrp.rhs_ty.clean(cx) | |
873 | } | |
1a4d82fc JJ |
874 | } |
875 | } | |
876 | } | |
877 | } | |
878 | ||
85aaf69f SL |
879 | impl<'a> Clean<WherePredicate> for ty::Predicate<'a> { |
880 | fn clean(&self, cx: &DocContext) -> WherePredicate { | |
54a0048b | 881 | use rustc::ty::Predicate; |
85aaf69f SL |
882 | |
883 | match *self { | |
884 | Predicate::Trait(ref pred) => pred.clean(cx), | |
885 | Predicate::Equate(ref pred) => pred.clean(cx), | |
cc61c64b | 886 | Predicate::Subtype(ref pred) => pred.clean(cx), |
85aaf69f SL |
887 | Predicate::RegionOutlives(ref pred) => pred.clean(cx), |
888 | Predicate::TypeOutlives(ref pred) => pred.clean(cx), | |
e9174d1e SL |
889 | Predicate::Projection(ref pred) => pred.clean(cx), |
890 | Predicate::WellFormed(_) => panic!("not user writable"), | |
891 | Predicate::ObjectSafe(_) => panic!("not user writable"), | |
a7813a04 | 892 | Predicate::ClosureKind(..) => panic!("not user writable"), |
85aaf69f SL |
893 | } |
894 | } | |
895 | } | |
896 | ||
897 | impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> { | |
898 | fn clean(&self, cx: &DocContext) -> WherePredicate { | |
899 | WherePredicate::BoundPredicate { | |
9e0c209e | 900 | ty: self.trait_ref.self_ty().clean(cx), |
85aaf69f SL |
901 | bounds: vec![self.trait_ref.clean(cx)] |
902 | } | |
903 | } | |
904 | } | |
905 | ||
906 | impl<'tcx> Clean<WherePredicate> for ty::EquatePredicate<'tcx> { | |
907 | fn clean(&self, cx: &DocContext) -> WherePredicate { | |
908 | let ty::EquatePredicate(ref lhs, ref rhs) = *self; | |
909 | WherePredicate::EqPredicate { | |
910 | lhs: lhs.clean(cx), | |
911 | rhs: rhs.clean(cx) | |
912 | } | |
913 | } | |
914 | } | |
915 | ||
cc61c64b XL |
916 | impl<'tcx> Clean<WherePredicate> for ty::SubtypePredicate<'tcx> { |
917 | fn clean(&self, _cx: &DocContext) -> WherePredicate { | |
918 | panic!("subtype predicates are an internal rustc artifact \ | |
919 | and should not be seen by rustdoc") | |
920 | } | |
921 | } | |
922 | ||
7cac9316 | 923 | impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>> { |
85aaf69f SL |
924 | fn clean(&self, cx: &DocContext) -> WherePredicate { |
925 | let ty::OutlivesPredicate(ref a, ref b) = *self; | |
926 | WherePredicate::RegionPredicate { | |
927 | lifetime: a.clean(cx).unwrap(), | |
928 | bounds: vec![b.clean(cx).unwrap()] | |
929 | } | |
930 | } | |
931 | } | |
932 | ||
7cac9316 | 933 | impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<ty::Ty<'tcx>, ty::Region<'tcx>> { |
85aaf69f SL |
934 | fn clean(&self, cx: &DocContext) -> WherePredicate { |
935 | let ty::OutlivesPredicate(ref ty, ref lt) = *self; | |
936 | ||
937 | WherePredicate::BoundPredicate { | |
938 | ty: ty.clean(cx), | |
939 | bounds: vec![TyParamBound::RegionBound(lt.clean(cx).unwrap())] | |
940 | } | |
941 | } | |
942 | } | |
943 | ||
944 | impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> { | |
945 | fn clean(&self, cx: &DocContext) -> WherePredicate { | |
946 | WherePredicate::EqPredicate { | |
947 | lhs: self.projection_ty.clean(cx), | |
948 | rhs: self.ty.clean(cx) | |
949 | } | |
950 | } | |
951 | } | |
952 | ||
953 | impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> { | |
954 | fn clean(&self, cx: &DocContext) -> Type { | |
041b39d2 | 955 | let trait_ = match self.trait_ref(cx.tcx).clean(cx) { |
85aaf69f | 956 | TyParamBound::TraitBound(t, _) => t.trait_, |
9346a6ac AL |
957 | TyParamBound::RegionBound(_) => { |
958 | panic!("cleaning a trait got a region") | |
959 | } | |
85aaf69f SL |
960 | }; |
961 | Type::QPath { | |
041b39d2 XL |
962 | name: cx.tcx.associated_item(self.item_def_id).name.clean(cx), |
963 | self_type: box self.self_ty().clean(cx), | |
85aaf69f SL |
964 | trait_: box trait_ |
965 | } | |
966 | } | |
967 | } | |
968 | ||
d9579d0f | 969 | // maybe use a Generic enum and use Vec<Generic>? |
85aaf69f | 970 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
971 | pub struct Generics { |
972 | pub lifetimes: Vec<Lifetime>, | |
973 | pub type_params: Vec<TyParam>, | |
974 | pub where_predicates: Vec<WherePredicate> | |
975 | } | |
976 | ||
e9174d1e | 977 | impl Clean<Generics> for hir::Generics { |
1a4d82fc JJ |
978 | fn clean(&self, cx: &DocContext) -> Generics { |
979 | Generics { | |
980 | lifetimes: self.lifetimes.clean(cx), | |
981 | type_params: self.ty_params.clean(cx), | |
982 | where_predicates: self.where_clause.predicates.clean(cx) | |
983 | } | |
984 | } | |
985 | } | |
986 | ||
8bb4bdeb | 987 | impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, |
9e0c209e | 988 | &'a ty::GenericPredicates<'tcx>) { |
1a4d82fc | 989 | fn clean(&self, cx: &DocContext) -> Generics { |
85aaf69f SL |
990 | use self::WherePredicate as WP; |
991 | ||
9e0c209e | 992 | let (gens, preds) = *self; |
85aaf69f | 993 | |
9346a6ac AL |
994 | // Bounds in the type_params and lifetimes fields are repeated in the |
995 | // predicates field (see rustc_typeck::collect::ty_generics), so remove | |
996 | // them. | |
9e0c209e SL |
997 | let stripped_typarams = gens.types.iter().filter_map(|tp| { |
998 | if tp.name == keywords::SelfType.name() { | |
999 | assert_eq!(tp.index, 0); | |
1000 | None | |
1001 | } else { | |
1002 | Some(tp.clean(cx)) | |
1003 | } | |
85aaf69f | 1004 | }).collect::<Vec<_>>(); |
85aaf69f | 1005 | |
9e0c209e | 1006 | let mut where_predicates = preds.predicates.to_vec().clean(cx); |
85aaf69f | 1007 | |
9346a6ac AL |
1008 | // Type parameters and have a Sized bound by default unless removed with |
1009 | // ?Sized. Scan through the predicates and mark any type parameter with | |
1010 | // a Sized bound, removing the bounds as we find them. | |
1011 | // | |
1012 | // Note that associated types also have a sized bound by default, but we | |
d9579d0f | 1013 | // don't actually know the set of associated types right here so that's |
9346a6ac | 1014 | // handled in cleaning associated types |
476ff2be | 1015 | let mut sized_params = FxHashSet(); |
9346a6ac AL |
1016 | where_predicates.retain(|pred| { |
1017 | match *pred { | |
1018 | WP::BoundPredicate { ty: Generic(ref g), ref bounds } => { | |
1019 | if bounds.iter().any(|b| b.is_sized_bound(cx)) { | |
1020 | sized_params.insert(g.clone()); | |
1021 | false | |
1022 | } else { | |
1023 | true | |
1024 | } | |
85aaf69f | 1025 | } |
9346a6ac | 1026 | _ => true, |
85aaf69f | 1027 | } |
9346a6ac | 1028 | }); |
85aaf69f | 1029 | |
9346a6ac AL |
1030 | // Run through the type parameters again and insert a ?Sized |
1031 | // unbound for any we didn't find to be Sized. | |
85aaf69f SL |
1032 | for tp in &stripped_typarams { |
1033 | if !sized_params.contains(&tp.name) { | |
85aaf69f SL |
1034 | where_predicates.push(WP::BoundPredicate { |
1035 | ty: Type::Generic(tp.name.clone()), | |
9346a6ac | 1036 | bounds: vec![TyParamBound::maybe_sized(cx)], |
85aaf69f SL |
1037 | }) |
1038 | } | |
1039 | } | |
1040 | ||
1041 | // It would be nice to collect all of the bounds on a type and recombine | |
1042 | // them if possible, to avoid e.g. `where T: Foo, T: Bar, T: Sized, T: 'a` | |
1043 | // and instead see `where T: Foo + Bar + Sized + 'a` | |
1044 | ||
1a4d82fc | 1045 | Generics { |
9346a6ac | 1046 | type_params: simplify::ty_params(stripped_typarams), |
32a655c1 | 1047 | lifetimes: gens.regions.clean(cx), |
9346a6ac | 1048 | where_predicates: simplify::where_clauses(cx, where_predicates), |
1a4d82fc JJ |
1049 | } |
1050 | } | |
1051 | } | |
1052 | ||
85aaf69f | 1053 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
1054 | pub struct Method { |
1055 | pub generics: Generics, | |
e9174d1e SL |
1056 | pub unsafety: hir::Unsafety, |
1057 | pub constness: hir::Constness, | |
1a4d82fc | 1058 | pub decl: FnDecl, |
7453a54e | 1059 | pub abi: Abi, |
1a4d82fc JJ |
1060 | } |
1061 | ||
32a655c1 | 1062 | impl<'a> Clean<Method> for (&'a hir::MethodSig, hir::BodyId) { |
c34b1796 | 1063 | fn clean(&self, cx: &DocContext) -> Method { |
c34b1796 | 1064 | Method { |
32a655c1 SL |
1065 | generics: self.0.generics.clean(cx), |
1066 | unsafety: self.0.unsafety, | |
1067 | constness: self.0.constness, | |
1068 | decl: (&*self.0.decl, self.1).clean(cx), | |
1069 | abi: self.0.abi | |
1a4d82fc JJ |
1070 | } |
1071 | } | |
1072 | } | |
1073 | ||
85aaf69f | 1074 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc | 1075 | pub struct TyMethod { |
e9174d1e | 1076 | pub unsafety: hir::Unsafety, |
1a4d82fc JJ |
1077 | pub decl: FnDecl, |
1078 | pub generics: Generics, | |
7453a54e | 1079 | pub abi: Abi, |
1a4d82fc JJ |
1080 | } |
1081 | ||
85aaf69f | 1082 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
1083 | pub struct Function { |
1084 | pub decl: FnDecl, | |
1085 | pub generics: Generics, | |
e9174d1e SL |
1086 | pub unsafety: hir::Unsafety, |
1087 | pub constness: hir::Constness, | |
7453a54e | 1088 | pub abi: Abi, |
1a4d82fc JJ |
1089 | } |
1090 | ||
1091 | impl Clean<Item> for doctree::Function { | |
1092 | fn clean(&self, cx: &DocContext) -> Item { | |
1093 | Item { | |
1094 | name: Some(self.name.clean(cx)), | |
1095 | attrs: self.attrs.clean(cx), | |
1096 | source: self.whence.clean(cx), | |
1097 | visibility: self.vis.clean(cx), | |
1098 | stability: self.stab.clean(cx), | |
9cc50fc6 | 1099 | deprecation: self.depr.clean(cx), |
32a655c1 | 1100 | def_id: cx.tcx.hir.local_def_id(self.id), |
1a4d82fc | 1101 | inner: FunctionItem(Function { |
32a655c1 | 1102 | decl: (&self.decl, self.body).clean(cx), |
1a4d82fc JJ |
1103 | generics: self.generics.clean(cx), |
1104 | unsafety: self.unsafety, | |
62682a34 | 1105 | constness: self.constness, |
9346a6ac | 1106 | abi: self.abi, |
1a4d82fc JJ |
1107 | }), |
1108 | } | |
1109 | } | |
1110 | } | |
1111 | ||
85aaf69f | 1112 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
1113 | pub struct FnDecl { |
1114 | pub inputs: Arguments, | |
1115 | pub output: FunctionRetTy, | |
e9174d1e | 1116 | pub variadic: bool, |
476ff2be | 1117 | pub attrs: Attributes, |
1a4d82fc JJ |
1118 | } |
1119 | ||
a7813a04 XL |
1120 | impl FnDecl { |
1121 | pub fn has_self(&self) -> bool { | |
c30ab7b3 | 1122 | self.inputs.values.len() > 0 && self.inputs.values[0].name == "self" |
a7813a04 | 1123 | } |
9e0c209e SL |
1124 | |
1125 | pub fn self_type(&self) -> Option<SelfTy> { | |
1126 | self.inputs.values.get(0).and_then(|v| v.to_self()) | |
1127 | } | |
a7813a04 XL |
1128 | } |
1129 | ||
85aaf69f | 1130 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
1131 | pub struct Arguments { |
1132 | pub values: Vec<Argument>, | |
1133 | } | |
1134 | ||
32a655c1 SL |
1135 | impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], &'a [Spanned<ast::Name>]) { |
1136 | fn clean(&self, cx: &DocContext) -> Arguments { | |
1137 | Arguments { | |
1138 | values: self.0.iter().enumerate().map(|(i, ty)| { | |
1139 | let mut name = self.1.get(i).map(|n| n.node.to_string()) | |
1140 | .unwrap_or(String::new()); | |
1141 | if name.is_empty() { | |
1142 | name = "_".to_string(); | |
1143 | } | |
1144 | Argument { | |
1145 | name: name, | |
1146 | type_: ty.clean(cx), | |
1147 | } | |
1148 | }).collect() | |
1149 | } | |
1150 | } | |
1151 | } | |
1152 | ||
1153 | impl<'a> Clean<Arguments> for (&'a [P<hir::Ty>], hir::BodyId) { | |
1154 | fn clean(&self, cx: &DocContext) -> Arguments { | |
1155 | let body = cx.tcx.hir.body(self.1); | |
1156 | ||
1157 | Arguments { | |
1158 | values: self.0.iter().enumerate().map(|(i, ty)| { | |
1159 | Argument { | |
1160 | name: name_from_pat(&body.arguments[i].pat), | |
1161 | type_: ty.clean(cx), | |
1162 | } | |
1163 | }).collect() | |
1164 | } | |
1165 | } | |
1166 | } | |
1167 | ||
1168 | impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl, A) | |
1169 | where (&'a [P<hir::Ty>], A): Clean<Arguments> | |
1170 | { | |
1a4d82fc JJ |
1171 | fn clean(&self, cx: &DocContext) -> FnDecl { |
1172 | FnDecl { | |
32a655c1 SL |
1173 | inputs: (&self.0.inputs[..], self.1).clean(cx), |
1174 | output: self.0.output.clean(cx), | |
1175 | variadic: self.0.variadic, | |
476ff2be | 1176 | attrs: Attributes::default() |
1a4d82fc JJ |
1177 | } |
1178 | } | |
1179 | } | |
1180 | ||
8bb4bdeb | 1181 | impl<'a, 'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) { |
1a4d82fc JJ |
1182 | fn clean(&self, cx: &DocContext) -> FnDecl { |
1183 | let (did, sig) = *self; | |
32a655c1 | 1184 | let mut names = if cx.tcx.hir.as_local_node_id(did).is_some() { |
b039eaaf | 1185 | vec![].into_iter() |
1a4d82fc | 1186 | } else { |
7cac9316 | 1187 | cx.tcx.fn_arg_names(did).into_iter() |
1a4d82fc | 1188 | }.peekable(); |
1a4d82fc | 1189 | FnDecl { |
476ff2be SL |
1190 | output: Return(sig.skip_binder().output().clean(cx)), |
1191 | attrs: Attributes::default(), | |
1192 | variadic: sig.skip_binder().variadic, | |
1a4d82fc | 1193 | inputs: Arguments { |
476ff2be | 1194 | values: sig.skip_binder().inputs().iter().map(|t| { |
1a4d82fc JJ |
1195 | Argument { |
1196 | type_: t.clean(cx), | |
9e0c209e | 1197 | name: names.next().map_or("".to_string(), |name| name.to_string()), |
1a4d82fc JJ |
1198 | } |
1199 | }).collect(), | |
1200 | }, | |
1201 | } | |
1202 | } | |
1203 | } | |
1204 | ||
85aaf69f | 1205 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
1206 | pub struct Argument { |
1207 | pub type_: Type, | |
1208 | pub name: String, | |
1a4d82fc JJ |
1209 | } |
1210 | ||
a7813a04 XL |
1211 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1212 | pub enum SelfTy { | |
1213 | SelfValue, | |
1214 | SelfBorrowed(Option<Lifetime>, Mutability), | |
1215 | SelfExplicit(Type), | |
1216 | } | |
1217 | ||
1218 | impl Argument { | |
1219 | pub fn to_self(&self) -> Option<SelfTy> { | |
32a655c1 SL |
1220 | if self.name != "self" { |
1221 | return None; | |
a7813a04 | 1222 | } |
32a655c1 SL |
1223 | if self.type_.is_self_type() { |
1224 | return Some(SelfValue); | |
1225 | } | |
1226 | match self.type_ { | |
1227 | BorrowedRef{ref lifetime, mutability, ref type_} if type_.is_self_type() => { | |
1228 | Some(SelfBorrowed(lifetime.clone(), mutability)) | |
1229 | } | |
1230 | _ => Some(SelfExplicit(self.type_.clone())) | |
1a4d82fc JJ |
1231 | } |
1232 | } | |
1233 | } | |
1234 | ||
85aaf69f | 1235 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
1236 | pub enum FunctionRetTy { |
1237 | Return(Type), | |
85aaf69f | 1238 | DefaultReturn, |
1a4d82fc JJ |
1239 | } |
1240 | ||
e9174d1e | 1241 | impl Clean<FunctionRetTy> for hir::FunctionRetTy { |
1a4d82fc JJ |
1242 | fn clean(&self, cx: &DocContext) -> FunctionRetTy { |
1243 | match *self { | |
e9174d1e SL |
1244 | hir::Return(ref typ) => Return(typ.clean(cx)), |
1245 | hir::DefaultReturn(..) => DefaultReturn, | |
1a4d82fc JJ |
1246 | } |
1247 | } | |
1248 | } | |
1249 | ||
85aaf69f | 1250 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc | 1251 | pub struct Trait { |
e9174d1e | 1252 | pub unsafety: hir::Unsafety, |
c34b1796 | 1253 | pub items: Vec<Item>, |
1a4d82fc JJ |
1254 | pub generics: Generics, |
1255 | pub bounds: Vec<TyParamBound>, | |
1256 | } | |
1257 | ||
1258 | impl Clean<Item> for doctree::Trait { | |
1259 | fn clean(&self, cx: &DocContext) -> Item { | |
1260 | Item { | |
1261 | name: Some(self.name.clean(cx)), | |
1262 | attrs: self.attrs.clean(cx), | |
1263 | source: self.whence.clean(cx), | |
32a655c1 | 1264 | def_id: cx.tcx.hir.local_def_id(self.id), |
1a4d82fc JJ |
1265 | visibility: self.vis.clean(cx), |
1266 | stability: self.stab.clean(cx), | |
9cc50fc6 | 1267 | deprecation: self.depr.clean(cx), |
1a4d82fc JJ |
1268 | inner: TraitItem(Trait { |
1269 | unsafety: self.unsafety, | |
1270 | items: self.items.clean(cx), | |
1271 | generics: self.generics.clean(cx), | |
1272 | bounds: self.bounds.clean(cx), | |
1273 | }), | |
1274 | } | |
1275 | } | |
1276 | } | |
1277 | ||
e9174d1e | 1278 | impl Clean<Type> for hir::TraitRef { |
1a4d82fc JJ |
1279 | fn clean(&self, cx: &DocContext) -> Type { |
1280 | resolve_type(cx, self.path.clean(cx), self.ref_id) | |
1281 | } | |
1282 | } | |
1283 | ||
e9174d1e | 1284 | impl Clean<PolyTrait> for hir::PolyTraitRef { |
1a4d82fc JJ |
1285 | fn clean(&self, cx: &DocContext) -> PolyTrait { |
1286 | PolyTrait { | |
1287 | trait_: self.trait_ref.clean(cx), | |
1288 | lifetimes: self.bound_lifetimes.clean(cx) | |
1289 | } | |
1290 | } | |
1291 | } | |
1292 | ||
e9174d1e | 1293 | impl Clean<Item> for hir::TraitItem { |
c34b1796 AL |
1294 | fn clean(&self, cx: &DocContext) -> Item { |
1295 | let inner = match self.node { | |
32a655c1 | 1296 | hir::TraitItemKind::Const(ref ty, default) => { |
d9579d0f | 1297 | AssociatedConstItem(ty.clean(cx), |
32a655c1 | 1298 | default.map(|e| print_const_expr(cx, e))) |
d9579d0f | 1299 | } |
32a655c1 SL |
1300 | hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => { |
1301 | MethodItem((sig, body).clean(cx)) | |
c34b1796 | 1302 | } |
32a655c1 SL |
1303 | hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Required(ref names)) => { |
1304 | TyMethodItem(TyMethod { | |
1305 | unsafety: sig.unsafety.clone(), | |
1306 | decl: (&*sig.decl, &names[..]).clean(cx), | |
1307 | generics: sig.generics.clean(cx), | |
1308 | abi: sig.abi | |
1309 | }) | |
c34b1796 | 1310 | } |
32a655c1 | 1311 | hir::TraitItemKind::Type(ref bounds, ref default) => { |
c34b1796 AL |
1312 | AssociatedTypeItem(bounds.clean(cx), default.clean(cx)) |
1313 | } | |
1314 | }; | |
1315 | Item { | |
b039eaaf | 1316 | name: Some(self.name.clean(cx)), |
c34b1796 AL |
1317 | attrs: self.attrs.clean(cx), |
1318 | source: self.span.clean(cx), | |
32a655c1 | 1319 | def_id: cx.tcx.hir.local_def_id(self.id), |
c34b1796 | 1320 | visibility: None, |
32a655c1 SL |
1321 | stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)), |
1322 | deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)), | |
c34b1796 | 1323 | inner: inner |
1a4d82fc JJ |
1324 | } |
1325 | } | |
1326 | } | |
1327 | ||
e9174d1e | 1328 | impl Clean<Item> for hir::ImplItem { |
c34b1796 AL |
1329 | fn clean(&self, cx: &DocContext) -> Item { |
1330 | let inner = match self.node { | |
32a655c1 | 1331 | hir::ImplItemKind::Const(ref ty, expr) => { |
7453a54e | 1332 | AssociatedConstItem(ty.clean(cx), |
32a655c1 | 1333 | Some(print_const_expr(cx, expr))) |
d9579d0f | 1334 | } |
32a655c1 SL |
1335 | hir::ImplItemKind::Method(ref sig, body) => { |
1336 | MethodItem((sig, body).clean(cx)) | |
c34b1796 | 1337 | } |
92a42be0 | 1338 | hir::ImplItemKind::Type(ref ty) => TypedefItem(Typedef { |
c34b1796 AL |
1339 | type_: ty.clean(cx), |
1340 | generics: Generics { | |
1341 | lifetimes: Vec::new(), | |
1342 | type_params: Vec::new(), | |
1343 | where_predicates: Vec::new() | |
1344 | }, | |
62682a34 | 1345 | }, true), |
c34b1796 AL |
1346 | }; |
1347 | Item { | |
b039eaaf | 1348 | name: Some(self.name.clean(cx)), |
c34b1796 AL |
1349 | source: self.span.clean(cx), |
1350 | attrs: self.attrs.clean(cx), | |
32a655c1 | 1351 | def_id: cx.tcx.hir.local_def_id(self.id), |
c34b1796 | 1352 | visibility: self.vis.clean(cx), |
32a655c1 SL |
1353 | stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)), |
1354 | deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)), | |
c34b1796 | 1355 | inner: inner |
1a4d82fc JJ |
1356 | } |
1357 | } | |
1358 | } | |
1359 | ||
476ff2be | 1360 | impl<'tcx> Clean<Item> for ty::AssociatedItem { |
1a4d82fc | 1361 | fn clean(&self, cx: &DocContext) -> Item { |
476ff2be SL |
1362 | let inner = match self.kind { |
1363 | ty::AssociatedKind::Const => { | |
7cac9316 | 1364 | let ty = cx.tcx.type_of(self.def_id); |
476ff2be | 1365 | AssociatedConstItem(ty.clean(cx), None) |
a7813a04 | 1366 | } |
476ff2be | 1367 | ty::AssociatedKind::Method => { |
7cac9316 XL |
1368 | let generics = (cx.tcx.generics_of(self.def_id), |
1369 | &cx.tcx.predicates_of(self.def_id)).clean(cx); | |
041b39d2 | 1370 | let sig = cx.tcx.fn_sig(self.def_id); |
8bb4bdeb | 1371 | let mut decl = (self.def_id, sig).clean(cx); |
476ff2be SL |
1372 | |
1373 | if self.method_has_self_argument { | |
1374 | let self_ty = match self.container { | |
1375 | ty::ImplContainer(def_id) => { | |
7cac9316 | 1376 | cx.tcx.type_of(def_id) |
476ff2be SL |
1377 | } |
1378 | ty::TraitContainer(_) => cx.tcx.mk_self_type() | |
1379 | }; | |
8bb4bdeb | 1380 | let self_arg_ty = *sig.input(0).skip_binder(); |
476ff2be | 1381 | if self_arg_ty == self_ty { |
32a655c1 | 1382 | decl.inputs.values[0].type_ = Generic(String::from("Self")); |
476ff2be SL |
1383 | } else if let ty::TyRef(_, mt) = self_arg_ty.sty { |
1384 | if mt.ty == self_ty { | |
1385 | match decl.inputs.values[0].type_ { | |
32a655c1 SL |
1386 | BorrowedRef{ref mut type_, ..} => { |
1387 | **type_ = Generic(String::from("Self")) | |
1388 | } | |
476ff2be SL |
1389 | _ => unreachable!(), |
1390 | } | |
1391 | } | |
1392 | } | |
1393 | } | |
1394 | ||
1395 | let provided = match self.container { | |
1396 | ty::ImplContainer(_) => false, | |
1397 | ty::TraitContainer(_) => self.defaultness.has_value() | |
1398 | }; | |
1399 | if provided { | |
1400 | MethodItem(Method { | |
8bb4bdeb | 1401 | unsafety: sig.unsafety(), |
476ff2be SL |
1402 | generics: generics, |
1403 | decl: decl, | |
8bb4bdeb | 1404 | abi: sig.abi(), |
476ff2be | 1405 | |
cc61c64b | 1406 | // trait methods cannot (currently, at least) be const |
476ff2be SL |
1407 | constness: hir::Constness::NotConst, |
1408 | }) | |
1409 | } else { | |
1410 | TyMethodItem(TyMethod { | |
8bb4bdeb | 1411 | unsafety: sig.unsafety(), |
476ff2be SL |
1412 | generics: generics, |
1413 | decl: decl, | |
8bb4bdeb | 1414 | abi: sig.abi(), |
476ff2be | 1415 | }) |
a7813a04 XL |
1416 | } |
1417 | } | |
476ff2be SL |
1418 | ty::AssociatedKind::Type => { |
1419 | let my_name = self.name.clean(cx); | |
1420 | ||
1421 | let mut bounds = if let ty::TraitContainer(did) = self.container { | |
1422 | // When loading a cross-crate associated type, the bounds for this type | |
1423 | // are actually located on the trait/impl itself, so we need to load | |
1424 | // all of the generics from there and then look for bounds that are | |
1425 | // applied to this associated type in question. | |
7cac9316 XL |
1426 | let predicates = cx.tcx.predicates_of(did); |
1427 | let generics = (cx.tcx.generics_of(did), &predicates).clean(cx); | |
476ff2be SL |
1428 | generics.where_predicates.iter().filter_map(|pred| { |
1429 | let (name, self_type, trait_, bounds) = match *pred { | |
1430 | WherePredicate::BoundPredicate { | |
1431 | ty: QPath { ref name, ref self_type, ref trait_ }, | |
1432 | ref bounds | |
1433 | } => (name, self_type, trait_, bounds), | |
1434 | _ => return None, | |
1435 | }; | |
1436 | if *name != my_name { return None } | |
1437 | match **trait_ { | |
1438 | ResolvedPath { did, .. } if did == self.container.id() => {} | |
1439 | _ => return None, | |
1440 | } | |
1441 | match **self_type { | |
1442 | Generic(ref s) if *s == "Self" => {} | |
1443 | _ => return None, | |
1444 | } | |
1445 | Some(bounds) | |
1446 | }).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>() | |
1447 | } else { | |
1448 | vec![] | |
1449 | }; | |
1450 | ||
1451 | // Our Sized/?Sized bound didn't get handled when creating the generics | |
1452 | // because we didn't actually get our whole set of bounds until just now | |
1453 | // (some of them may have come from the trait). If we do have a sized | |
1454 | // bound, we remove it, and if we don't then we add the `?Sized` bound | |
1455 | // at the end. | |
1456 | match bounds.iter().position(|b| b.is_sized_bound(cx)) { | |
1457 | Some(i) => { bounds.remove(i); } | |
1458 | None => bounds.push(TyParamBound::maybe_sized(cx)), | |
1459 | } | |
1460 | ||
1461 | let ty = if self.defaultness.has_value() { | |
7cac9316 | 1462 | Some(cx.tcx.type_of(self.def_id)) |
476ff2be SL |
1463 | } else { |
1464 | None | |
1465 | }; | |
1466 | ||
1467 | AssociatedTypeItem(bounds, ty.clean(cx)) | |
9346a6ac AL |
1468 | } |
1469 | }; | |
9346a6ac | 1470 | |
1a4d82fc JJ |
1471 | Item { |
1472 | name: Some(self.name.clean(cx)), | |
a7813a04 | 1473 | visibility: Some(Inherited), |
1a4d82fc | 1474 | stability: get_stability(cx, self.def_id), |
9cc50fc6 | 1475 | deprecation: get_deprecation(cx, self.def_id), |
1a4d82fc | 1476 | def_id: self.def_id, |
476ff2be SL |
1477 | attrs: inline::load_attrs(cx, self.def_id), |
1478 | source: cx.tcx.def_span(self.def_id).clean(cx), | |
9346a6ac | 1479 | inner: inner, |
1a4d82fc JJ |
1480 | } |
1481 | } | |
1482 | } | |
1483 | ||
1a4d82fc | 1484 | /// A trait reference, which may have higher ranked lifetimes. |
85aaf69f | 1485 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
1486 | pub struct PolyTrait { |
1487 | pub trait_: Type, | |
1488 | pub lifetimes: Vec<Lifetime> | |
1489 | } | |
1490 | ||
1491 | /// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original | |
54a0048b | 1492 | /// type out of the AST/TyCtxt given one of these, if more information is needed. Most importantly |
1a4d82fc | 1493 | /// it does not preserve mutability or boxes. |
7cac9316 | 1494 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc | 1495 | pub enum Type { |
e9174d1e | 1496 | /// structs/enums/traits (most that'd be an hir::TyPath) |
1a4d82fc JJ |
1497 | ResolvedPath { |
1498 | path: Path, | |
1499 | typarams: Option<Vec<TyParamBound>>, | |
e9174d1e | 1500 | did: DefId, |
62682a34 SL |
1501 | /// true if is a `T::Name` path for associated types |
1502 | is_generic: bool, | |
1a4d82fc | 1503 | }, |
1a4d82fc JJ |
1504 | /// For parameterized types, so the consumer of the JSON don't go |
1505 | /// looking for types which don't exist anywhere. | |
1506 | Generic(String), | |
c34b1796 AL |
1507 | /// Primitives are the fixed-size numeric types (plus int/usize/float), char, |
1508 | /// arrays, slices, and tuples. | |
1a4d82fc | 1509 | Primitive(PrimitiveType), |
1a4d82fc JJ |
1510 | /// extern "ABI" fn |
1511 | BareFunction(Box<BareFunctionDecl>), | |
1512 | Tuple(Vec<Type>), | |
7cac9316 XL |
1513 | Slice(Box<Type>), |
1514 | Array(Box<Type>, usize), | |
5bcae85e | 1515 | Never, |
1a4d82fc JJ |
1516 | Unique(Box<Type>), |
1517 | RawPointer(Mutability, Box<Type>), | |
1518 | BorrowedRef { | |
1519 | lifetime: Option<Lifetime>, | |
1520 | mutability: Mutability, | |
1521 | type_: Box<Type>, | |
1522 | }, | |
1523 | ||
1524 | // <Type as Trait>::Name | |
1525 | QPath { | |
1526 | name: String, | |
1527 | self_type: Box<Type>, | |
1528 | trait_: Box<Type> | |
1529 | }, | |
1530 | ||
1531 | // _ | |
1532 | Infer, | |
1533 | ||
5bcae85e SL |
1534 | // impl TraitA+TraitB |
1535 | ImplTrait(Vec<TyParamBound>), | |
1a4d82fc JJ |
1536 | } |
1537 | ||
85aaf69f | 1538 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Copy, Debug)] |
1a4d82fc | 1539 | pub enum PrimitiveType { |
32a655c1 SL |
1540 | Isize, I8, I16, I32, I64, I128, |
1541 | Usize, U8, U16, U32, U64, U128, | |
1a4d82fc JJ |
1542 | F32, F64, |
1543 | Char, | |
1544 | Bool, | |
1545 | Str, | |
1546 | Slice, | |
c34b1796 | 1547 | Array, |
9e0c209e SL |
1548 | Tuple, |
1549 | RawPointer, | |
1a4d82fc JJ |
1550 | } |
1551 | ||
85aaf69f | 1552 | #[derive(Clone, RustcEncodable, RustcDecodable, Copy, Debug)] |
1a4d82fc | 1553 | pub enum TypeKind { |
c30ab7b3 SL |
1554 | Enum, |
1555 | Function, | |
1556 | Module, | |
1557 | Const, | |
1558 | Static, | |
1559 | Struct, | |
1560 | Union, | |
1561 | Trait, | |
1562 | Variant, | |
1563 | Typedef, | |
1a4d82fc JJ |
1564 | } |
1565 | ||
54a0048b SL |
1566 | pub trait GetDefId { |
1567 | fn def_id(&self) -> Option<DefId>; | |
1568 | } | |
1569 | ||
1570 | impl<T: GetDefId> GetDefId for Option<T> { | |
1571 | fn def_id(&self) -> Option<DefId> { | |
1572 | self.as_ref().and_then(|d| d.def_id()) | |
1573 | } | |
1574 | } | |
1575 | ||
9346a6ac AL |
1576 | impl Type { |
1577 | pub fn primitive_type(&self) -> Option<PrimitiveType> { | |
1578 | match *self { | |
1579 | Primitive(p) | BorrowedRef { type_: box Primitive(p), ..} => Some(p), | |
7cac9316 XL |
1580 | Slice(..) | BorrowedRef { type_: box Slice(..), .. } => Some(PrimitiveType::Slice), |
1581 | Array(..) | BorrowedRef { type_: box Array(..), .. } => Some(PrimitiveType::Array), | |
9e0c209e SL |
1582 | Tuple(..) => Some(PrimitiveType::Tuple), |
1583 | RawPointer(..) => Some(PrimitiveType::RawPointer), | |
9346a6ac AL |
1584 | _ => None, |
1585 | } | |
1586 | } | |
a7813a04 XL |
1587 | |
1588 | pub fn is_generic(&self) -> bool { | |
1589 | match *self { | |
1590 | ResolvedPath { is_generic, .. } => is_generic, | |
1591 | _ => false, | |
1592 | } | |
1593 | } | |
32a655c1 SL |
1594 | |
1595 | pub fn is_self_type(&self) -> bool { | |
1596 | match *self { | |
1597 | Generic(ref name) => name == "Self", | |
1598 | _ => false | |
1599 | } | |
1600 | } | |
9346a6ac AL |
1601 | } |
1602 | ||
54a0048b SL |
1603 | impl GetDefId for Type { |
1604 | fn def_id(&self) -> Option<DefId> { | |
1605 | match *self { | |
1606 | ResolvedPath { did, .. } => Some(did), | |
1607 | _ => None, | |
1608 | } | |
1609 | } | |
1610 | } | |
1611 | ||
1a4d82fc JJ |
1612 | impl PrimitiveType { |
1613 | fn from_str(s: &str) -> Option<PrimitiveType> { | |
85aaf69f | 1614 | match s { |
9e0c209e SL |
1615 | "isize" => Some(PrimitiveType::Isize), |
1616 | "i8" => Some(PrimitiveType::I8), | |
1617 | "i16" => Some(PrimitiveType::I16), | |
1618 | "i32" => Some(PrimitiveType::I32), | |
1619 | "i64" => Some(PrimitiveType::I64), | |
32a655c1 | 1620 | "i128" => Some(PrimitiveType::I128), |
9e0c209e SL |
1621 | "usize" => Some(PrimitiveType::Usize), |
1622 | "u8" => Some(PrimitiveType::U8), | |
1623 | "u16" => Some(PrimitiveType::U16), | |
1624 | "u32" => Some(PrimitiveType::U32), | |
1625 | "u64" => Some(PrimitiveType::U64), | |
32a655c1 | 1626 | "u128" => Some(PrimitiveType::U128), |
9e0c209e SL |
1627 | "bool" => Some(PrimitiveType::Bool), |
1628 | "char" => Some(PrimitiveType::Char), | |
1629 | "str" => Some(PrimitiveType::Str), | |
1630 | "f32" => Some(PrimitiveType::F32), | |
1631 | "f64" => Some(PrimitiveType::F64), | |
1632 | "array" => Some(PrimitiveType::Array), | |
1633 | "slice" => Some(PrimitiveType::Slice), | |
1634 | "tuple" => Some(PrimitiveType::Tuple), | |
1635 | "pointer" => Some(PrimitiveType::RawPointer), | |
1a4d82fc JJ |
1636 | _ => None, |
1637 | } | |
1638 | } | |
1639 | ||
c30ab7b3 | 1640 | pub fn as_str(&self) -> &'static str { |
32a655c1 | 1641 | use self::PrimitiveType::*; |
1a4d82fc | 1642 | match *self { |
32a655c1 SL |
1643 | Isize => "isize", |
1644 | I8 => "i8", | |
1645 | I16 => "i16", | |
1646 | I32 => "i32", | |
1647 | I64 => "i64", | |
1648 | I128 => "i128", | |
1649 | Usize => "usize", | |
1650 | U8 => "u8", | |
1651 | U16 => "u16", | |
1652 | U32 => "u32", | |
1653 | U64 => "u64", | |
1654 | U128 => "u128", | |
1655 | F32 => "f32", | |
1656 | F64 => "f64", | |
1657 | Str => "str", | |
1658 | Bool => "bool", | |
1659 | Char => "char", | |
1660 | Array => "array", | |
1661 | Slice => "slice", | |
1662 | Tuple => "tuple", | |
1663 | RawPointer => "pointer", | |
1a4d82fc JJ |
1664 | } |
1665 | } | |
1666 | ||
1667 | pub fn to_url_str(&self) -> &'static str { | |
c30ab7b3 | 1668 | self.as_str() |
1a4d82fc | 1669 | } |
1a4d82fc JJ |
1670 | } |
1671 | ||
9e0c209e SL |
1672 | impl From<ast::IntTy> for PrimitiveType { |
1673 | fn from(int_ty: ast::IntTy) -> PrimitiveType { | |
1674 | match int_ty { | |
1675 | ast::IntTy::Is => PrimitiveType::Isize, | |
1676 | ast::IntTy::I8 => PrimitiveType::I8, | |
1677 | ast::IntTy::I16 => PrimitiveType::I16, | |
1678 | ast::IntTy::I32 => PrimitiveType::I32, | |
1679 | ast::IntTy::I64 => PrimitiveType::I64, | |
32a655c1 | 1680 | ast::IntTy::I128 => PrimitiveType::I128, |
9e0c209e SL |
1681 | } |
1682 | } | |
5bcae85e SL |
1683 | } |
1684 | ||
9e0c209e SL |
1685 | impl From<ast::UintTy> for PrimitiveType { |
1686 | fn from(uint_ty: ast::UintTy) -> PrimitiveType { | |
1687 | match uint_ty { | |
1688 | ast::UintTy::Us => PrimitiveType::Usize, | |
1689 | ast::UintTy::U8 => PrimitiveType::U8, | |
1690 | ast::UintTy::U16 => PrimitiveType::U16, | |
1691 | ast::UintTy::U32 => PrimitiveType::U32, | |
1692 | ast::UintTy::U64 => PrimitiveType::U64, | |
32a655c1 | 1693 | ast::UintTy::U128 => PrimitiveType::U128, |
5bcae85e | 1694 | } |
5bcae85e | 1695 | } |
9e0c209e SL |
1696 | } |
1697 | ||
1698 | impl From<ast::FloatTy> for PrimitiveType { | |
1699 | fn from(float_ty: ast::FloatTy) -> PrimitiveType { | |
1700 | match float_ty { | |
1701 | ast::FloatTy::F32 => PrimitiveType::F32, | |
1702 | ast::FloatTy::F64 => PrimitiveType::F64, | |
5bcae85e | 1703 | } |
5bcae85e SL |
1704 | } |
1705 | } | |
1706 | ||
e9174d1e | 1707 | impl Clean<Type> for hir::Ty { |
1a4d82fc | 1708 | fn clean(&self, cx: &DocContext) -> Type { |
54a0048b | 1709 | use rustc::hir::*; |
1a4d82fc | 1710 | match self.node { |
5bcae85e | 1711 | TyNever => Never, |
1a4d82fc | 1712 | TyPtr(ref m) => RawPointer(m.mutbl.clean(cx), box m.ty.clean(cx)), |
32a655c1 SL |
1713 | TyRptr(ref l, ref m) => { |
1714 | let lifetime = if l.is_elided() { | |
1715 | None | |
1716 | } else { | |
1717 | Some(l.clean(cx)) | |
5bcae85e | 1718 | }; |
32a655c1 SL |
1719 | BorrowedRef {lifetime: lifetime, mutability: m.mutbl.clean(cx), |
1720 | type_: box m.ty.clean(cx)} | |
1721 | } | |
7cac9316 | 1722 | TySlice(ref ty) => Slice(box ty.clean(cx)), |
32a655c1 | 1723 | TyArray(ref ty, length) => { |
cc61c64b | 1724 | use rustc::middle::const_val::eval_length; |
32a655c1 | 1725 | let n = eval_length(cx.tcx, length, "array length").unwrap(); |
7cac9316 | 1726 | Array(box ty.clean(cx), n) |
5bcae85e | 1727 | }, |
1a4d82fc | 1728 | TyTup(ref tys) => Tuple(tys.clean(cx)), |
476ff2be SL |
1729 | TyPath(hir::QPath::Resolved(None, ref path)) => { |
1730 | if let Some(new_ty) = cx.ty_substs.borrow().get(&path.def).cloned() { | |
1731 | return new_ty; | |
9e0c209e SL |
1732 | } |
1733 | ||
476ff2be SL |
1734 | let mut alias = None; |
1735 | if let Def::TyAlias(def_id) = path.def { | |
1736 | // Substitute private type aliases | |
32a655c1 | 1737 | if let Some(node_id) = cx.tcx.hir.as_local_node_id(def_id) { |
476ff2be | 1738 | if !cx.access_levels.borrow().is_exported(def_id) { |
32a655c1 | 1739 | alias = Some(&cx.tcx.hir.expect_item(node_id).node); |
476ff2be | 1740 | } |
9e0c209e | 1741 | } |
476ff2be SL |
1742 | }; |
1743 | ||
1744 | if let Some(&hir::ItemTy(ref ty, ref generics)) = alias { | |
9e0c209e | 1745 | let provided_params = &path.segments.last().unwrap().parameters; |
476ff2be SL |
1746 | let mut ty_substs = FxHashMap(); |
1747 | let mut lt_substs = FxHashMap(); | |
9e0c209e | 1748 | for (i, ty_param) in generics.ty_params.iter().enumerate() { |
32a655c1 | 1749 | let ty_param_def = Def::TyParam(cx.tcx.hir.local_def_id(ty_param.id)); |
9e0c209e SL |
1750 | if let Some(ty) = provided_params.types().get(i).cloned() |
1751 | .cloned() { | |
1752 | ty_substs.insert(ty_param_def, ty.unwrap().clean(cx)); | |
1753 | } else if let Some(default) = ty_param.default.clone() { | |
1754 | ty_substs.insert(ty_param_def, default.unwrap().clean(cx)); | |
5bcae85e SL |
1755 | } |
1756 | } | |
9e0c209e SL |
1757 | for (i, lt_param) in generics.lifetimes.iter().enumerate() { |
1758 | if let Some(lt) = provided_params.lifetimes().get(i).cloned() | |
1759 | .cloned() { | |
32a655c1 SL |
1760 | if !lt.is_elided() { |
1761 | lt_substs.insert(lt_param.lifetime.id, lt.clean(cx)); | |
1762 | } | |
9e0c209e SL |
1763 | } |
1764 | } | |
1765 | return cx.enter_alias(ty_substs, lt_substs, || ty.clean(cx)); | |
5bcae85e SL |
1766 | } |
1767 | resolve_type(cx, path.clean(cx), self.id) | |
c34b1796 | 1768 | } |
476ff2be | 1769 | TyPath(hir::QPath::Resolved(Some(ref qself), ref p)) => { |
9cc50fc6 SL |
1770 | let mut segments: Vec<_> = p.segments.clone().into(); |
1771 | segments.pop(); | |
1772 | let trait_path = hir::Path { | |
1773 | span: p.span, | |
476ff2be | 1774 | def: Def::Trait(cx.tcx.associated_item(p.def.def_id()).container.id()), |
9cc50fc6 SL |
1775 | segments: segments.into(), |
1776 | }; | |
c34b1796 | 1777 | Type::QPath { |
a7813a04 | 1778 | name: p.segments.last().unwrap().name.clean(cx), |
476ff2be SL |
1779 | self_type: box qself.clean(cx), |
1780 | trait_: box resolve_type(cx, trait_path.clean(cx), self.id) | |
1781 | } | |
1782 | } | |
1783 | TyPath(hir::QPath::TypeRelative(ref qself, ref segment)) => { | |
1784 | let mut def = Def::Err; | |
7cac9316 XL |
1785 | let ty = hir_ty_to_ty(cx.tcx, self); |
1786 | if let ty::TyProjection(proj) = ty.sty { | |
041b39d2 | 1787 | def = Def::Trait(proj.trait_ref(cx.tcx).def_id); |
476ff2be SL |
1788 | } |
1789 | let trait_path = hir::Path { | |
1790 | span: self.span, | |
476ff2be SL |
1791 | def: def, |
1792 | segments: vec![].into(), | |
1793 | }; | |
1794 | Type::QPath { | |
1795 | name: segment.name.clean(cx), | |
1796 | self_type: box qself.clean(cx), | |
c34b1796 AL |
1797 | trait_: box resolve_type(cx, trait_path.clean(cx), self.id) |
1798 | } | |
1a4d82fc | 1799 | } |
32a655c1 SL |
1800 | TyTraitObject(ref bounds, ref lifetime) => { |
1801 | match bounds[0].clean(cx).trait_ { | |
62682a34 | 1802 | ResolvedPath { path, typarams: None, did, is_generic } => { |
32a655c1 SL |
1803 | let mut bounds: Vec<_> = bounds[1..].iter().map(|bound| { |
1804 | TraitBound(bound.clean(cx), hir::TraitBoundModifier::None) | |
1805 | }).collect(); | |
1806 | if !lifetime.is_elided() { | |
1807 | bounds.push(RegionBound(lifetime.clean(cx))); | |
1808 | } | |
62682a34 SL |
1809 | ResolvedPath { |
1810 | path: path, | |
32a655c1 | 1811 | typarams: Some(bounds), |
62682a34 SL |
1812 | did: did, |
1813 | is_generic: is_generic, | |
1814 | } | |
1a4d82fc | 1815 | } |
32a655c1 | 1816 | _ => Infer // shouldn't happen |
1a4d82fc JJ |
1817 | } |
1818 | } | |
1819 | TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)), | |
5bcae85e | 1820 | TyImplTrait(ref bounds) => ImplTrait(bounds.clean(cx)), |
cc61c64b | 1821 | TyInfer | TyErr => Infer, |
54a0048b | 1822 | TyTypeof(..) => panic!("Unimplemented type {:?}", self.node), |
1a4d82fc JJ |
1823 | } |
1824 | } | |
1825 | } | |
1826 | ||
1827 | impl<'tcx> Clean<Type> for ty::Ty<'tcx> { | |
1828 | fn clean(&self, cx: &DocContext) -> Type { | |
1829 | match self.sty { | |
5bcae85e | 1830 | ty::TyNever => Never, |
9e0c209e SL |
1831 | ty::TyBool => Primitive(PrimitiveType::Bool), |
1832 | ty::TyChar => Primitive(PrimitiveType::Char), | |
1833 | ty::TyInt(int_ty) => Primitive(int_ty.into()), | |
1834 | ty::TyUint(uint_ty) => Primitive(uint_ty.into()), | |
1835 | ty::TyFloat(float_ty) => Primitive(float_ty.into()), | |
1836 | ty::TyStr => Primitive(PrimitiveType::Str), | |
7cac9316 XL |
1837 | ty::TySlice(ty) => Slice(box ty.clean(cx)), |
1838 | ty::TyArray(ty, n) => Array(box ty.clean(cx), n), | |
62682a34 SL |
1839 | ty::TyRawPtr(mt) => RawPointer(mt.mutbl.clean(cx), box mt.ty.clean(cx)), |
1840 | ty::TyRef(r, mt) => BorrowedRef { | |
1a4d82fc JJ |
1841 | lifetime: r.clean(cx), |
1842 | mutability: mt.mutbl.clean(cx), | |
1843 | type_: box mt.ty.clean(cx), | |
1844 | }, | |
041b39d2 XL |
1845 | ty::TyFnDef(..) | |
1846 | ty::TyFnPtr(_) => { | |
1847 | let ty = cx.tcx.lift(self).unwrap(); | |
1848 | let sig = ty.fn_sig(cx.tcx); | |
1849 | BareFunction(box BareFunctionDecl { | |
1850 | unsafety: sig.unsafety(), | |
1851 | generics: Generics { | |
1852 | lifetimes: Vec::new(), | |
1853 | type_params: Vec::new(), | |
1854 | where_predicates: Vec::new() | |
1855 | }, | |
1856 | decl: (cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), sig).clean(cx), | |
1857 | abi: sig.abi(), | |
1858 | }) | |
1859 | } | |
9e0c209e | 1860 | ty::TyAdt(def, substs) => { |
e9174d1e | 1861 | let did = def.did; |
9e0c209e | 1862 | let kind = match def.adt_kind() { |
c30ab7b3 SL |
1863 | AdtKind::Struct => TypeKind::Struct, |
1864 | AdtKind::Union => TypeKind::Union, | |
1865 | AdtKind::Enum => TypeKind::Enum, | |
1a4d82fc | 1866 | }; |
92a42be0 | 1867 | inline::record_extern_fqn(cx, did, kind); |
476ff2be | 1868 | let path = external_path(cx, &cx.tcx.item_name(did).as_str(), |
9e0c209e | 1869 | None, false, vec![], substs); |
1a4d82fc JJ |
1870 | ResolvedPath { |
1871 | path: path, | |
1872 | typarams: None, | |
1873 | did: did, | |
62682a34 | 1874 | is_generic: false, |
1a4d82fc JJ |
1875 | } |
1876 | } | |
476ff2be SL |
1877 | ty::TyDynamic(ref obj, ref reg) => { |
1878 | if let Some(principal) = obj.principal() { | |
1879 | let did = principal.def_id(); | |
1880 | inline::record_extern_fqn(cx, did, TypeKind::Trait); | |
1881 | ||
1882 | let mut typarams = vec![]; | |
1883 | reg.clean(cx).map(|b| typarams.push(RegionBound(b))); | |
1884 | for did in obj.auto_traits() { | |
1885 | let empty = cx.tcx.intern_substs(&[]); | |
1886 | let path = external_path(cx, &cx.tcx.item_name(did).as_str(), | |
1887 | Some(did), false, vec![], empty); | |
1888 | inline::record_extern_fqn(cx, did, TypeKind::Trait); | |
1889 | let bound = TraitBound(PolyTrait { | |
1890 | trait_: ResolvedPath { | |
1891 | path: path, | |
1892 | typarams: None, | |
1893 | did: did, | |
1894 | is_generic: false, | |
1895 | }, | |
1896 | lifetimes: vec![] | |
1897 | }, hir::TraitBoundModifier::None); | |
1898 | typarams.push(bound); | |
1899 | } | |
9e0c209e | 1900 | |
476ff2be SL |
1901 | let mut bindings = vec![]; |
1902 | for ty::Binder(ref pb) in obj.projection_bounds() { | |
1903 | bindings.push(TypeBinding { | |
041b39d2 | 1904 | name: cx.tcx.associated_item(pb.item_def_id).name.clean(cx), |
476ff2be SL |
1905 | ty: pb.ty.clean(cx) |
1906 | }); | |
1907 | } | |
9e0c209e | 1908 | |
476ff2be SL |
1909 | let path = external_path(cx, &cx.tcx.item_name(did).as_str(), Some(did), |
1910 | false, bindings, principal.0.substs); | |
1911 | ResolvedPath { | |
1912 | path: path, | |
1913 | typarams: Some(typarams), | |
1914 | did: did, | |
1915 | is_generic: false, | |
1916 | } | |
1917 | } else { | |
1918 | Never | |
1a4d82fc JJ |
1919 | } |
1920 | } | |
8bb4bdeb | 1921 | ty::TyTuple(ref t, _) => Tuple(t.clean(cx)), |
1a4d82fc | 1922 | |
62682a34 | 1923 | ty::TyProjection(ref data) => data.clean(cx), |
1a4d82fc | 1924 | |
c1a9b12d | 1925 | ty::TyParam(ref p) => Generic(p.name.to_string()), |
1a4d82fc | 1926 | |
5bcae85e SL |
1927 | ty::TyAnon(def_id, substs) => { |
1928 | // Grab the "TraitA + TraitB" from `impl TraitA + TraitB`, | |
1929 | // by looking up the projections associated with the def_id. | |
7cac9316 | 1930 | let predicates_of = cx.tcx.predicates_of(def_id); |
476ff2be | 1931 | let substs = cx.tcx.lift(&substs).unwrap(); |
7cac9316 | 1932 | let bounds = predicates_of.instantiate(cx.tcx, substs); |
9e0c209e | 1933 | ImplTrait(bounds.predicates.into_iter().filter_map(|predicate| { |
5bcae85e SL |
1934 | predicate.to_opt_poly_trait_ref().clean(cx) |
1935 | }).collect()) | |
1936 | } | |
1937 | ||
62682a34 | 1938 | ty::TyClosure(..) => Tuple(vec![]), // FIXME(pcwalton) |
1a4d82fc | 1939 | |
62682a34 SL |
1940 | ty::TyInfer(..) => panic!("TyInfer"), |
1941 | ty::TyError => panic!("TyError"), | |
1a4d82fc JJ |
1942 | } |
1943 | } | |
1944 | } | |
1945 | ||
e9174d1e | 1946 | impl Clean<Item> for hir::StructField { |
1a4d82fc | 1947 | fn clean(&self, cx: &DocContext) -> Item { |
1a4d82fc | 1948 | Item { |
54a0048b SL |
1949 | name: Some(self.name).clean(cx), |
1950 | attrs: self.attrs.clean(cx), | |
1a4d82fc | 1951 | source: self.span.clean(cx), |
54a0048b | 1952 | visibility: self.vis.clean(cx), |
32a655c1 SL |
1953 | stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)), |
1954 | deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)), | |
1955 | def_id: cx.tcx.hir.local_def_id(self.id), | |
54a0048b | 1956 | inner: StructFieldItem(self.ty.clean(cx)), |
1a4d82fc JJ |
1957 | } |
1958 | } | |
1959 | } | |
1960 | ||
476ff2be | 1961 | impl<'tcx> Clean<Item> for ty::FieldDef { |
1a4d82fc | 1962 | fn clean(&self, cx: &DocContext) -> Item { |
1a4d82fc | 1963 | Item { |
54a0048b | 1964 | name: Some(self.name).clean(cx), |
476ff2be SL |
1965 | attrs: cx.tcx.get_attrs(self.did).clean(cx), |
1966 | source: cx.tcx.def_span(self.did).clean(cx), | |
54a0048b | 1967 | visibility: self.vis.clean(cx), |
e9174d1e | 1968 | stability: get_stability(cx, self.did), |
9cc50fc6 | 1969 | deprecation: get_deprecation(cx, self.did), |
e9174d1e | 1970 | def_id: self.did, |
7cac9316 | 1971 | inner: StructFieldItem(cx.tcx.type_of(self.did).clean(cx)), |
1a4d82fc JJ |
1972 | } |
1973 | } | |
1974 | } | |
1975 | ||
a7813a04 XL |
1976 | #[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug)] |
1977 | pub enum Visibility { | |
1978 | Public, | |
1979 | Inherited, | |
1980 | } | |
1a4d82fc | 1981 | |
e9174d1e | 1982 | impl Clean<Option<Visibility>> for hir::Visibility { |
1a4d82fc | 1983 | fn clean(&self, _: &DocContext) -> Option<Visibility> { |
a7813a04 | 1984 | Some(if *self == hir::Visibility::Public { Public } else { Inherited }) |
54a0048b SL |
1985 | } |
1986 | } | |
1987 | ||
1988 | impl Clean<Option<Visibility>> for ty::Visibility { | |
1989 | fn clean(&self, _: &DocContext) -> Option<Visibility> { | |
a7813a04 | 1990 | Some(if *self == ty::Visibility::Public { Public } else { Inherited }) |
1a4d82fc JJ |
1991 | } |
1992 | } | |
1993 | ||
85aaf69f | 1994 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
1995 | pub struct Struct { |
1996 | pub struct_type: doctree::StructType, | |
1997 | pub generics: Generics, | |
1998 | pub fields: Vec<Item>, | |
1999 | pub fields_stripped: bool, | |
2000 | } | |
2001 | ||
9e0c209e SL |
2002 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
2003 | pub struct Union { | |
2004 | pub struct_type: doctree::StructType, | |
2005 | pub generics: Generics, | |
2006 | pub fields: Vec<Item>, | |
2007 | pub fields_stripped: bool, | |
2008 | } | |
2009 | ||
1a4d82fc JJ |
2010 | impl Clean<Item> for doctree::Struct { |
2011 | fn clean(&self, cx: &DocContext) -> Item { | |
2012 | Item { | |
2013 | name: Some(self.name.clean(cx)), | |
2014 | attrs: self.attrs.clean(cx), | |
2015 | source: self.whence.clean(cx), | |
32a655c1 | 2016 | def_id: cx.tcx.hir.local_def_id(self.id), |
1a4d82fc JJ |
2017 | visibility: self.vis.clean(cx), |
2018 | stability: self.stab.clean(cx), | |
9cc50fc6 | 2019 | deprecation: self.depr.clean(cx), |
1a4d82fc JJ |
2020 | inner: StructItem(Struct { |
2021 | struct_type: self.struct_type, | |
2022 | generics: self.generics.clean(cx), | |
2023 | fields: self.fields.clean(cx), | |
2024 | fields_stripped: false, | |
2025 | }), | |
2026 | } | |
2027 | } | |
2028 | } | |
2029 | ||
9e0c209e SL |
2030 | impl Clean<Item> for doctree::Union { |
2031 | fn clean(&self, cx: &DocContext) -> Item { | |
2032 | Item { | |
2033 | name: Some(self.name.clean(cx)), | |
2034 | attrs: self.attrs.clean(cx), | |
2035 | source: self.whence.clean(cx), | |
32a655c1 | 2036 | def_id: cx.tcx.hir.local_def_id(self.id), |
9e0c209e SL |
2037 | visibility: self.vis.clean(cx), |
2038 | stability: self.stab.clean(cx), | |
2039 | deprecation: self.depr.clean(cx), | |
2040 | inner: UnionItem(Union { | |
2041 | struct_type: self.struct_type, | |
2042 | generics: self.generics.clean(cx), | |
2043 | fields: self.fields.clean(cx), | |
2044 | fields_stripped: false, | |
2045 | }), | |
2046 | } | |
2047 | } | |
2048 | } | |
2049 | ||
1a4d82fc JJ |
2050 | /// This is a more limited form of the standard Struct, different in that |
2051 | /// it lacks the things most items have (name, id, parameterization). Found | |
2052 | /// only as a variant in an enum. | |
85aaf69f | 2053 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2054 | pub struct VariantStruct { |
2055 | pub struct_type: doctree::StructType, | |
2056 | pub fields: Vec<Item>, | |
2057 | pub fields_stripped: bool, | |
2058 | } | |
2059 | ||
54a0048b | 2060 | impl Clean<VariantStruct> for ::rustc::hir::VariantData { |
1a4d82fc JJ |
2061 | fn clean(&self, cx: &DocContext) -> VariantStruct { |
2062 | VariantStruct { | |
2063 | struct_type: doctree::struct_type_from_def(self), | |
b039eaaf | 2064 | fields: self.fields().iter().map(|x| x.clean(cx)).collect(), |
1a4d82fc JJ |
2065 | fields_stripped: false, |
2066 | } | |
2067 | } | |
2068 | } | |
2069 | ||
85aaf69f | 2070 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2071 | pub struct Enum { |
2072 | pub variants: Vec<Item>, | |
2073 | pub generics: Generics, | |
2074 | pub variants_stripped: bool, | |
2075 | } | |
2076 | ||
2077 | impl Clean<Item> for doctree::Enum { | |
2078 | fn clean(&self, cx: &DocContext) -> Item { | |
2079 | Item { | |
2080 | name: Some(self.name.clean(cx)), | |
2081 | attrs: self.attrs.clean(cx), | |
2082 | source: self.whence.clean(cx), | |
32a655c1 | 2083 | def_id: cx.tcx.hir.local_def_id(self.id), |
1a4d82fc JJ |
2084 | visibility: self.vis.clean(cx), |
2085 | stability: self.stab.clean(cx), | |
9cc50fc6 | 2086 | deprecation: self.depr.clean(cx), |
1a4d82fc JJ |
2087 | inner: EnumItem(Enum { |
2088 | variants: self.variants.clean(cx), | |
2089 | generics: self.generics.clean(cx), | |
2090 | variants_stripped: false, | |
2091 | }), | |
2092 | } | |
2093 | } | |
2094 | } | |
2095 | ||
85aaf69f | 2096 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2097 | pub struct Variant { |
2098 | pub kind: VariantKind, | |
2099 | } | |
2100 | ||
2101 | impl Clean<Item> for doctree::Variant { | |
2102 | fn clean(&self, cx: &DocContext) -> Item { | |
2103 | Item { | |
2104 | name: Some(self.name.clean(cx)), | |
2105 | attrs: self.attrs.clean(cx), | |
2106 | source: self.whence.clean(cx), | |
b039eaaf | 2107 | visibility: None, |
1a4d82fc | 2108 | stability: self.stab.clean(cx), |
9cc50fc6 | 2109 | deprecation: self.depr.clean(cx), |
32a655c1 | 2110 | def_id: cx.tcx.hir.local_def_id(self.def.id()), |
1a4d82fc | 2111 | inner: VariantItem(Variant { |
c30ab7b3 | 2112 | kind: self.def.clean(cx), |
1a4d82fc JJ |
2113 | }), |
2114 | } | |
2115 | } | |
2116 | } | |
2117 | ||
476ff2be | 2118 | impl<'tcx> Clean<Item> for ty::VariantDef { |
1a4d82fc | 2119 | fn clean(&self, cx: &DocContext) -> Item { |
c30ab7b3 SL |
2120 | let kind = match self.ctor_kind { |
2121 | CtorKind::Const => VariantKind::CLike, | |
2122 | CtorKind::Fn => { | |
2123 | VariantKind::Tuple( | |
7cac9316 | 2124 | self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect() |
e9174d1e | 2125 | ) |
1a4d82fc | 2126 | } |
c30ab7b3 SL |
2127 | CtorKind::Fictive => { |
2128 | VariantKind::Struct(VariantStruct { | |
1a4d82fc JJ |
2129 | struct_type: doctree::Plain, |
2130 | fields_stripped: false, | |
e9174d1e | 2131 | fields: self.fields.iter().map(|field| { |
1a4d82fc | 2132 | Item { |
476ff2be | 2133 | source: cx.tcx.def_span(field.did).clean(cx), |
e9174d1e | 2134 | name: Some(field.name.clean(cx)), |
476ff2be | 2135 | attrs: cx.tcx.get_attrs(field.did).clean(cx), |
54a0048b SL |
2136 | visibility: field.vis.clean(cx), |
2137 | def_id: field.did, | |
2138 | stability: get_stability(cx, field.did), | |
2139 | deprecation: get_deprecation(cx, field.did), | |
7cac9316 | 2140 | inner: StructFieldItem(cx.tcx.type_of(field.did).clean(cx)) |
1a4d82fc JJ |
2141 | } |
2142 | }).collect() | |
2143 | }) | |
2144 | } | |
2145 | }; | |
2146 | Item { | |
2147 | name: Some(self.name.clean(cx)), | |
476ff2be SL |
2148 | attrs: inline::load_attrs(cx, self.did), |
2149 | source: cx.tcx.def_span(self.did).clean(cx), | |
a7813a04 | 2150 | visibility: Some(Inherited), |
e9174d1e | 2151 | def_id: self.did, |
1a4d82fc | 2152 | inner: VariantItem(Variant { kind: kind }), |
e9174d1e | 2153 | stability: get_stability(cx, self.did), |
9cc50fc6 | 2154 | deprecation: get_deprecation(cx, self.did), |
1a4d82fc JJ |
2155 | } |
2156 | } | |
2157 | } | |
2158 | ||
85aaf69f | 2159 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc | 2160 | pub enum VariantKind { |
c30ab7b3 SL |
2161 | CLike, |
2162 | Tuple(Vec<Type>), | |
2163 | Struct(VariantStruct), | |
1a4d82fc JJ |
2164 | } |
2165 | ||
c30ab7b3 SL |
2166 | impl Clean<VariantKind> for hir::VariantData { |
2167 | fn clean(&self, cx: &DocContext) -> VariantKind { | |
2168 | if self.is_struct() { | |
2169 | VariantKind::Struct(self.clean(cx)) | |
2170 | } else if self.is_unit() { | |
2171 | VariantKind::CLike | |
2172 | } else { | |
2173 | VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect()) | |
2174 | } | |
1a4d82fc JJ |
2175 | } |
2176 | } | |
2177 | ||
85aaf69f | 2178 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2179 | pub struct Span { |
2180 | pub filename: String, | |
c34b1796 AL |
2181 | pub loline: usize, |
2182 | pub locol: usize, | |
2183 | pub hiline: usize, | |
2184 | pub hicol: usize, | |
1a4d82fc JJ |
2185 | } |
2186 | ||
2187 | impl Span { | |
2188 | fn empty() -> Span { | |
2189 | Span { | |
2190 | filename: "".to_string(), | |
2191 | loline: 0, locol: 0, | |
2192 | hiline: 0, hicol: 0, | |
2193 | } | |
2194 | } | |
2195 | } | |
2196 | ||
3157f602 | 2197 | impl Clean<Span> for syntax_pos::Span { |
1a4d82fc | 2198 | fn clean(&self, cx: &DocContext) -> Span { |
c1a9b12d SL |
2199 | if *self == DUMMY_SP { |
2200 | return Span::empty(); | |
2201 | } | |
2202 | ||
1a4d82fc JJ |
2203 | let cm = cx.sess().codemap(); |
2204 | let filename = cm.span_to_filename(*self); | |
2205 | let lo = cm.lookup_char_pos(self.lo); | |
2206 | let hi = cm.lookup_char_pos(self.hi); | |
2207 | Span { | |
2208 | filename: filename.to_string(), | |
2209 | loline: lo.line, | |
85aaf69f | 2210 | locol: lo.col.to_usize(), |
1a4d82fc | 2211 | hiline: hi.line, |
85aaf69f | 2212 | hicol: hi.col.to_usize(), |
1a4d82fc JJ |
2213 | } |
2214 | } | |
2215 | } | |
2216 | ||
85aaf69f | 2217 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
2218 | pub struct Path { |
2219 | pub global: bool, | |
476ff2be | 2220 | pub def: Def, |
1a4d82fc JJ |
2221 | pub segments: Vec<PathSegment>, |
2222 | } | |
2223 | ||
9346a6ac AL |
2224 | impl Path { |
2225 | pub fn singleton(name: String) -> Path { | |
2226 | Path { | |
2227 | global: false, | |
476ff2be | 2228 | def: Def::Err, |
9346a6ac AL |
2229 | segments: vec![PathSegment { |
2230 | name: name, | |
2231 | params: PathParameters::AngleBracketed { | |
2232 | lifetimes: Vec::new(), | |
2233 | types: Vec::new(), | |
2234 | bindings: Vec::new() | |
2235 | } | |
2236 | }] | |
2237 | } | |
2238 | } | |
a7813a04 | 2239 | |
32a655c1 SL |
2240 | pub fn last_name(&self) -> &str { |
2241 | self.segments.last().unwrap().name.as_str() | |
a7813a04 | 2242 | } |
9346a6ac AL |
2243 | } |
2244 | ||
e9174d1e | 2245 | impl Clean<Path> for hir::Path { |
1a4d82fc JJ |
2246 | fn clean(&self, cx: &DocContext) -> Path { |
2247 | Path { | |
32a655c1 | 2248 | global: self.is_global(), |
476ff2be | 2249 | def: self.def, |
32a655c1 | 2250 | segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx), |
1a4d82fc JJ |
2251 | } |
2252 | } | |
2253 | } | |
2254 | ||
85aaf69f | 2255 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
2256 | pub enum PathParameters { |
2257 | AngleBracketed { | |
2258 | lifetimes: Vec<Lifetime>, | |
2259 | types: Vec<Type>, | |
cc61c64b | 2260 | bindings: Vec<TypeBinding>, |
1a4d82fc JJ |
2261 | }, |
2262 | Parenthesized { | |
2263 | inputs: Vec<Type>, | |
cc61c64b | 2264 | output: Option<Type>, |
1a4d82fc JJ |
2265 | } |
2266 | } | |
2267 | ||
e9174d1e | 2268 | impl Clean<PathParameters> for hir::PathParameters { |
1a4d82fc JJ |
2269 | fn clean(&self, cx: &DocContext) -> PathParameters { |
2270 | match *self { | |
e9174d1e | 2271 | hir::AngleBracketedParameters(ref data) => { |
1a4d82fc | 2272 | PathParameters::AngleBracketed { |
32a655c1 SL |
2273 | lifetimes: if data.lifetimes.iter().all(|lt| lt.is_elided()) { |
2274 | vec![] | |
2275 | } else { | |
2276 | data.lifetimes.clean(cx) | |
2277 | }, | |
1a4d82fc | 2278 | types: data.types.clean(cx), |
cc61c64b | 2279 | bindings: data.bindings.clean(cx), |
1a4d82fc JJ |
2280 | } |
2281 | } | |
2282 | ||
e9174d1e | 2283 | hir::ParenthesizedParameters(ref data) => { |
1a4d82fc JJ |
2284 | PathParameters::Parenthesized { |
2285 | inputs: data.inputs.clean(cx), | |
cc61c64b | 2286 | output: data.output.clean(cx), |
1a4d82fc JJ |
2287 | } |
2288 | } | |
2289 | } | |
2290 | } | |
2291 | } | |
2292 | ||
85aaf69f | 2293 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc JJ |
2294 | pub struct PathSegment { |
2295 | pub name: String, | |
cc61c64b | 2296 | pub params: PathParameters, |
1a4d82fc JJ |
2297 | } |
2298 | ||
e9174d1e | 2299 | impl Clean<PathSegment> for hir::PathSegment { |
1a4d82fc JJ |
2300 | fn clean(&self, cx: &DocContext) -> PathSegment { |
2301 | PathSegment { | |
a7813a04 | 2302 | name: self.name.clean(cx), |
1a4d82fc JJ |
2303 | params: self.parameters.clean(cx) |
2304 | } | |
2305 | } | |
2306 | } | |
2307 | ||
476ff2be | 2308 | fn qpath_to_string(p: &hir::QPath) -> String { |
32a655c1 SL |
2309 | let segments = match *p { |
2310 | hir::QPath::Resolved(_, ref path) => &path.segments, | |
2311 | hir::QPath::TypeRelative(_, ref segment) => return segment.name.to_string(), | |
476ff2be SL |
2312 | }; |
2313 | ||
1a4d82fc | 2314 | let mut s = String::new(); |
32a655c1 SL |
2315 | for (i, seg) in segments.iter().enumerate() { |
2316 | if i > 0 { | |
1a4d82fc | 2317 | s.push_str("::"); |
1a4d82fc | 2318 | } |
32a655c1 SL |
2319 | if seg.name != keywords::CrateRoot.name() { |
2320 | s.push_str(&*seg.name.as_str()); | |
2321 | } | |
1a4d82fc JJ |
2322 | } |
2323 | s | |
2324 | } | |
2325 | ||
1a4d82fc JJ |
2326 | impl Clean<String> for ast::Name { |
2327 | fn clean(&self, _: &DocContext) -> String { | |
c1a9b12d | 2328 | self.to_string() |
1a4d82fc JJ |
2329 | } |
2330 | } | |
2331 | ||
85aaf69f | 2332 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2333 | pub struct Typedef { |
2334 | pub type_: Type, | |
2335 | pub generics: Generics, | |
2336 | } | |
2337 | ||
2338 | impl Clean<Item> for doctree::Typedef { | |
2339 | fn clean(&self, cx: &DocContext) -> Item { | |
2340 | Item { | |
2341 | name: Some(self.name.clean(cx)), | |
2342 | attrs: self.attrs.clean(cx), | |
2343 | source: self.whence.clean(cx), | |
32a655c1 | 2344 | def_id: cx.tcx.hir.local_def_id(self.id.clone()), |
1a4d82fc JJ |
2345 | visibility: self.vis.clean(cx), |
2346 | stability: self.stab.clean(cx), | |
9cc50fc6 | 2347 | deprecation: self.depr.clean(cx), |
1a4d82fc JJ |
2348 | inner: TypedefItem(Typedef { |
2349 | type_: self.ty.clean(cx), | |
2350 | generics: self.gen.clean(cx), | |
62682a34 | 2351 | }, false), |
1a4d82fc JJ |
2352 | } |
2353 | } | |
2354 | } | |
2355 | ||
85aaf69f | 2356 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)] |
1a4d82fc | 2357 | pub struct BareFunctionDecl { |
e9174d1e | 2358 | pub unsafety: hir::Unsafety, |
1a4d82fc JJ |
2359 | pub generics: Generics, |
2360 | pub decl: FnDecl, | |
a7813a04 | 2361 | pub abi: Abi, |
1a4d82fc JJ |
2362 | } |
2363 | ||
e9174d1e | 2364 | impl Clean<BareFunctionDecl> for hir::BareFnTy { |
1a4d82fc JJ |
2365 | fn clean(&self, cx: &DocContext) -> BareFunctionDecl { |
2366 | BareFunctionDecl { | |
2367 | unsafety: self.unsafety, | |
2368 | generics: Generics { | |
2369 | lifetimes: self.lifetimes.clean(cx), | |
2370 | type_params: Vec::new(), | |
2371 | where_predicates: Vec::new() | |
2372 | }, | |
32a655c1 | 2373 | decl: (&*self.decl, &[][..]).clean(cx), |
a7813a04 | 2374 | abi: self.abi, |
1a4d82fc JJ |
2375 | } |
2376 | } | |
2377 | } | |
2378 | ||
85aaf69f | 2379 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2380 | pub struct Static { |
2381 | pub type_: Type, | |
2382 | pub mutability: Mutability, | |
2383 | /// It's useful to have the value of a static documented, but I have no | |
2384 | /// desire to represent expressions (that'd basically be all of the AST, | |
2385 | /// which is huge!). So, have a string. | |
2386 | pub expr: String, | |
2387 | } | |
2388 | ||
2389 | impl Clean<Item> for doctree::Static { | |
2390 | fn clean(&self, cx: &DocContext) -> Item { | |
2391 | debug!("cleaning static {}: {:?}", self.name.clean(cx), self); | |
2392 | Item { | |
2393 | name: Some(self.name.clean(cx)), | |
2394 | attrs: self.attrs.clean(cx), | |
2395 | source: self.whence.clean(cx), | |
32a655c1 | 2396 | def_id: cx.tcx.hir.local_def_id(self.id), |
1a4d82fc JJ |
2397 | visibility: self.vis.clean(cx), |
2398 | stability: self.stab.clean(cx), | |
9cc50fc6 | 2399 | deprecation: self.depr.clean(cx), |
1a4d82fc JJ |
2400 | inner: StaticItem(Static { |
2401 | type_: self.type_.clean(cx), | |
2402 | mutability: self.mutability.clean(cx), | |
32a655c1 | 2403 | expr: print_const_expr(cx, self.expr), |
1a4d82fc JJ |
2404 | }), |
2405 | } | |
2406 | } | |
2407 | } | |
2408 | ||
85aaf69f | 2409 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2410 | pub struct Constant { |
2411 | pub type_: Type, | |
2412 | pub expr: String, | |
2413 | } | |
2414 | ||
2415 | impl Clean<Item> for doctree::Constant { | |
2416 | fn clean(&self, cx: &DocContext) -> Item { | |
2417 | Item { | |
2418 | name: Some(self.name.clean(cx)), | |
2419 | attrs: self.attrs.clean(cx), | |
2420 | source: self.whence.clean(cx), | |
32a655c1 | 2421 | def_id: cx.tcx.hir.local_def_id(self.id), |
1a4d82fc JJ |
2422 | visibility: self.vis.clean(cx), |
2423 | stability: self.stab.clean(cx), | |
9cc50fc6 | 2424 | deprecation: self.depr.clean(cx), |
1a4d82fc JJ |
2425 | inner: ConstantItem(Constant { |
2426 | type_: self.type_.clean(cx), | |
32a655c1 | 2427 | expr: print_const_expr(cx, self.expr), |
1a4d82fc JJ |
2428 | }), |
2429 | } | |
2430 | } | |
2431 | } | |
2432 | ||
85aaf69f | 2433 | #[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)] |
1a4d82fc JJ |
2434 | pub enum Mutability { |
2435 | Mutable, | |
2436 | Immutable, | |
2437 | } | |
2438 | ||
e9174d1e | 2439 | impl Clean<Mutability> for hir::Mutability { |
1a4d82fc JJ |
2440 | fn clean(&self, _: &DocContext) -> Mutability { |
2441 | match self { | |
e9174d1e SL |
2442 | &hir::MutMutable => Mutable, |
2443 | &hir::MutImmutable => Immutable, | |
1a4d82fc JJ |
2444 | } |
2445 | } | |
2446 | } | |
2447 | ||
85aaf69f SL |
2448 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)] |
2449 | pub enum ImplPolarity { | |
2450 | Positive, | |
2451 | Negative, | |
2452 | } | |
2453 | ||
e9174d1e | 2454 | impl Clean<ImplPolarity> for hir::ImplPolarity { |
85aaf69f SL |
2455 | fn clean(&self, _: &DocContext) -> ImplPolarity { |
2456 | match self { | |
e9174d1e SL |
2457 | &hir::ImplPolarity::Positive => ImplPolarity::Positive, |
2458 | &hir::ImplPolarity::Negative => ImplPolarity::Negative, | |
85aaf69f SL |
2459 | } |
2460 | } | |
2461 | } | |
2462 | ||
2463 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] | |
1a4d82fc | 2464 | pub struct Impl { |
e9174d1e | 2465 | pub unsafety: hir::Unsafety, |
1a4d82fc | 2466 | pub generics: Generics, |
476ff2be | 2467 | pub provided_trait_methods: FxHashSet<String>, |
1a4d82fc JJ |
2468 | pub trait_: Option<Type>, |
2469 | pub for_: Type, | |
2470 | pub items: Vec<Item>, | |
85aaf69f | 2471 | pub polarity: Option<ImplPolarity>, |
1a4d82fc JJ |
2472 | } |
2473 | ||
d9579d0f AL |
2474 | impl Clean<Vec<Item>> for doctree::Impl { |
2475 | fn clean(&self, cx: &DocContext) -> Vec<Item> { | |
2476 | let mut ret = Vec::new(); | |
2477 | let trait_ = self.trait_.clean(cx); | |
2478 | let items = self.items.clean(cx); | |
2479 | ||
2480 | // If this impl block is an implementation of the Deref trait, then we | |
2481 | // need to try inlining the target's inherent impl blocks as well. | |
476ff2be | 2482 | if trait_.def_id() == cx.tcx.lang_items.deref_trait() { |
54a0048b | 2483 | build_deref_target_impls(cx, &items, &mut ret); |
d9579d0f AL |
2484 | } |
2485 | ||
476ff2be SL |
2486 | let provided = trait_.def_id().map(|did| { |
2487 | cx.tcx.provided_trait_methods(did) | |
2488 | .into_iter() | |
2489 | .map(|meth| meth.name.to_string()) | |
2490 | .collect() | |
2491 | }).unwrap_or(FxHashSet()); | |
54a0048b | 2492 | |
d9579d0f | 2493 | ret.push(Item { |
1a4d82fc JJ |
2494 | name: None, |
2495 | attrs: self.attrs.clean(cx), | |
2496 | source: self.whence.clean(cx), | |
32a655c1 | 2497 | def_id: cx.tcx.hir.local_def_id(self.id), |
1a4d82fc JJ |
2498 | visibility: self.vis.clean(cx), |
2499 | stability: self.stab.clean(cx), | |
9cc50fc6 | 2500 | deprecation: self.depr.clean(cx), |
1a4d82fc | 2501 | inner: ImplItem(Impl { |
c34b1796 | 2502 | unsafety: self.unsafety, |
1a4d82fc | 2503 | generics: self.generics.clean(cx), |
54a0048b | 2504 | provided_trait_methods: provided, |
d9579d0f | 2505 | trait_: trait_, |
1a4d82fc | 2506 | for_: self.for_.clean(cx), |
d9579d0f | 2507 | items: items, |
85aaf69f | 2508 | polarity: Some(self.polarity.clean(cx)), |
1a4d82fc | 2509 | }), |
d9579d0f | 2510 | }); |
54a0048b | 2511 | ret |
d9579d0f AL |
2512 | } |
2513 | } | |
2514 | ||
2515 | fn build_deref_target_impls(cx: &DocContext, | |
2516 | items: &[Item], | |
2517 | ret: &mut Vec<Item>) { | |
32a655c1 | 2518 | use self::PrimitiveType::*; |
476ff2be | 2519 | let tcx = cx.tcx; |
d9579d0f AL |
2520 | |
2521 | for item in items { | |
2522 | let target = match item.inner { | |
62682a34 | 2523 | TypedefItem(ref t, true) => &t.type_, |
d9579d0f AL |
2524 | _ => continue, |
2525 | }; | |
2526 | let primitive = match *target { | |
e9174d1e | 2527 | ResolvedPath { did, .. } if did.is_local() => continue, |
d9579d0f | 2528 | ResolvedPath { did, .. } => { |
476ff2be | 2529 | ret.extend(inline::build_impls(cx, did)); |
d9579d0f AL |
2530 | continue |
2531 | } | |
2532 | _ => match target.primitive_type() { | |
2533 | Some(prim) => prim, | |
2534 | None => continue, | |
2535 | } | |
2536 | }; | |
2537 | let did = match primitive { | |
32a655c1 SL |
2538 | Isize => tcx.lang_items.isize_impl(), |
2539 | I8 => tcx.lang_items.i8_impl(), | |
2540 | I16 => tcx.lang_items.i16_impl(), | |
2541 | I32 => tcx.lang_items.i32_impl(), | |
2542 | I64 => tcx.lang_items.i64_impl(), | |
2543 | I128 => tcx.lang_items.i128_impl(), | |
2544 | Usize => tcx.lang_items.usize_impl(), | |
2545 | U8 => tcx.lang_items.u8_impl(), | |
2546 | U16 => tcx.lang_items.u16_impl(), | |
2547 | U32 => tcx.lang_items.u32_impl(), | |
2548 | U64 => tcx.lang_items.u64_impl(), | |
2549 | U128 => tcx.lang_items.u128_impl(), | |
2550 | F32 => tcx.lang_items.f32_impl(), | |
2551 | F64 => tcx.lang_items.f64_impl(), | |
2552 | Char => tcx.lang_items.char_impl(), | |
2553 | Bool => None, | |
2554 | Str => tcx.lang_items.str_impl(), | |
2555 | Slice => tcx.lang_items.slice_impl(), | |
2556 | Array => tcx.lang_items.slice_impl(), | |
2557 | Tuple => None, | |
2558 | RawPointer => tcx.lang_items.const_ptr_impl(), | |
d9579d0f AL |
2559 | }; |
2560 | if let Some(did) = did { | |
e9174d1e | 2561 | if !did.is_local() { |
476ff2be | 2562 | inline::build_impl(cx, did, ret); |
d9579d0f | 2563 | } |
1a4d82fc JJ |
2564 | } |
2565 | } | |
2566 | } | |
2567 | ||
c34b1796 AL |
2568 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
2569 | pub struct DefaultImpl { | |
e9174d1e | 2570 | pub unsafety: hir::Unsafety, |
c34b1796 AL |
2571 | pub trait_: Type, |
2572 | } | |
2573 | ||
2574 | impl Clean<Item> for doctree::DefaultImpl { | |
2575 | fn clean(&self, cx: &DocContext) -> Item { | |
2576 | Item { | |
2577 | name: None, | |
2578 | attrs: self.attrs.clean(cx), | |
2579 | source: self.whence.clean(cx), | |
32a655c1 | 2580 | def_id: cx.tcx.hir.local_def_id(self.id), |
a7813a04 | 2581 | visibility: Some(Public), |
c34b1796 | 2582 | stability: None, |
9cc50fc6 | 2583 | deprecation: None, |
c34b1796 AL |
2584 | inner: DefaultImplItem(DefaultImpl { |
2585 | unsafety: self.unsafety, | |
2586 | trait_: self.trait_.clean(cx), | |
2587 | }), | |
2588 | } | |
2589 | } | |
2590 | } | |
2591 | ||
85aaf69f SL |
2592 | impl Clean<Item> for doctree::ExternCrate { |
2593 | fn clean(&self, cx: &DocContext) -> Item { | |
2594 | Item { | |
2595 | name: None, | |
2596 | attrs: self.attrs.clean(cx), | |
2597 | source: self.whence.clean(cx), | |
a7813a04 | 2598 | def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX }, |
85aaf69f SL |
2599 | visibility: self.vis.clean(cx), |
2600 | stability: None, | |
9cc50fc6 | 2601 | deprecation: None, |
85aaf69f SL |
2602 | inner: ExternCrateItem(self.name.clean(cx), self.path.clone()) |
2603 | } | |
2604 | } | |
1a4d82fc JJ |
2605 | } |
2606 | ||
85aaf69f | 2607 | impl Clean<Vec<Item>> for doctree::Import { |
1a4d82fc JJ |
2608 | fn clean(&self, cx: &DocContext) -> Vec<Item> { |
2609 | // We consider inlining the documentation of `pub use` statements, but we | |
2610 | // forcefully don't inline if this is not public or if the | |
2611 | // #[doc(no_inline)] attribute is present. | |
3157f602 | 2612 | // Don't inline doc(hidden) imports so they can be stripped at a later stage. |
e9174d1e | 2613 | let denied = self.vis != hir::Public || self.attrs.iter().any(|a| { |
cc61c64b XL |
2614 | a.name().unwrap() == "doc" && match a.meta_item_list() { |
2615 | Some(l) => attr::list_contains_name(&l, "no_inline") || | |
2616 | attr::list_contains_name(&l, "hidden"), | |
1a4d82fc JJ |
2617 | None => false, |
2618 | } | |
2619 | }); | |
476ff2be SL |
2620 | let path = self.path.clean(cx); |
2621 | let inner = if self.glob { | |
2622 | Import::Glob(resolve_use_source(cx, path)) | |
2623 | } else { | |
2624 | let name = self.name; | |
2625 | if !denied { | |
7cac9316 | 2626 | if let Some(items) = inline::try_inline(cx, path.def, name) { |
476ff2be | 2627 | return items; |
85aaf69f | 2628 | } |
1a4d82fc | 2629 | } |
476ff2be | 2630 | Import::Simple(name.clean(cx), resolve_use_source(cx, path)) |
85aaf69f | 2631 | }; |
476ff2be | 2632 | vec![Item { |
85aaf69f SL |
2633 | name: None, |
2634 | attrs: self.attrs.clean(cx), | |
2635 | source: self.whence.clean(cx), | |
32a655c1 | 2636 | def_id: cx.tcx.hir.local_def_id(ast::CRATE_NODE_ID), |
85aaf69f SL |
2637 | visibility: self.vis.clean(cx), |
2638 | stability: None, | |
9cc50fc6 | 2639 | deprecation: None, |
85aaf69f | 2640 | inner: ImportItem(inner) |
476ff2be | 2641 | }] |
1a4d82fc JJ |
2642 | } |
2643 | } | |
2644 | ||
85aaf69f SL |
2645 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
2646 | pub enum Import { | |
1a4d82fc | 2647 | // use source as str; |
c30ab7b3 | 2648 | Simple(String, ImportSource), |
1a4d82fc | 2649 | // use source::*; |
476ff2be | 2650 | Glob(ImportSource) |
1a4d82fc JJ |
2651 | } |
2652 | ||
85aaf69f | 2653 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2654 | pub struct ImportSource { |
2655 | pub path: Path, | |
e9174d1e | 2656 | pub did: Option<DefId>, |
1a4d82fc JJ |
2657 | } |
2658 | ||
e9174d1e | 2659 | impl Clean<Vec<Item>> for hir::ForeignMod { |
1a4d82fc | 2660 | fn clean(&self, cx: &DocContext) -> Vec<Item> { |
9346a6ac AL |
2661 | let mut items = self.items.clean(cx); |
2662 | for item in &mut items { | |
54a0048b SL |
2663 | if let ForeignFunctionItem(ref mut f) = item.inner { |
2664 | f.abi = self.abi; | |
9346a6ac AL |
2665 | } |
2666 | } | |
2667 | items | |
1a4d82fc JJ |
2668 | } |
2669 | } | |
2670 | ||
e9174d1e | 2671 | impl Clean<Item> for hir::ForeignItem { |
1a4d82fc JJ |
2672 | fn clean(&self, cx: &DocContext) -> Item { |
2673 | let inner = match self.node { | |
32a655c1 | 2674 | hir::ForeignItemFn(ref decl, ref names, ref generics) => { |
1a4d82fc | 2675 | ForeignFunctionItem(Function { |
32a655c1 | 2676 | decl: (&**decl, &names[..]).clean(cx), |
1a4d82fc | 2677 | generics: generics.clean(cx), |
e9174d1e | 2678 | unsafety: hir::Unsafety::Unsafe, |
7453a54e | 2679 | abi: Abi::Rust, |
e9174d1e | 2680 | constness: hir::Constness::NotConst, |
1a4d82fc JJ |
2681 | }) |
2682 | } | |
e9174d1e | 2683 | hir::ForeignItemStatic(ref ty, mutbl) => { |
1a4d82fc JJ |
2684 | ForeignStaticItem(Static { |
2685 | type_: ty.clean(cx), | |
2686 | mutability: if mutbl {Mutable} else {Immutable}, | |
2687 | expr: "".to_string(), | |
2688 | }) | |
2689 | } | |
2690 | }; | |
2691 | Item { | |
b039eaaf | 2692 | name: Some(self.name.clean(cx)), |
1a4d82fc JJ |
2693 | attrs: self.attrs.clean(cx), |
2694 | source: self.span.clean(cx), | |
32a655c1 | 2695 | def_id: cx.tcx.hir.local_def_id(self.id), |
1a4d82fc | 2696 | visibility: self.vis.clean(cx), |
32a655c1 SL |
2697 | stability: get_stability(cx, cx.tcx.hir.local_def_id(self.id)), |
2698 | deprecation: get_deprecation(cx, cx.tcx.hir.local_def_id(self.id)), | |
1a4d82fc JJ |
2699 | inner: inner, |
2700 | } | |
2701 | } | |
2702 | } | |
2703 | ||
2704 | // Utilities | |
2705 | ||
2706 | trait ToSource { | |
2707 | fn to_src(&self, cx: &DocContext) -> String; | |
2708 | } | |
2709 | ||
3157f602 | 2710 | impl ToSource for syntax_pos::Span { |
1a4d82fc JJ |
2711 | fn to_src(&self, cx: &DocContext) -> String { |
2712 | debug!("converting span {:?} to snippet", self.clean(cx)); | |
2713 | let sn = match cx.sess().codemap().span_to_snippet(*self) { | |
85aaf69f SL |
2714 | Ok(x) => x.to_string(), |
2715 | Err(_) => "".to_string() | |
1a4d82fc JJ |
2716 | }; |
2717 | debug!("got snippet {}", sn); | |
2718 | sn | |
2719 | } | |
2720 | } | |
2721 | ||
e9174d1e | 2722 | fn name_from_pat(p: &hir::Pat) -> String { |
54a0048b | 2723 | use rustc::hir::*; |
1a4d82fc JJ |
2724 | debug!("Trying to get a name from pattern: {:?}", p); |
2725 | ||
2726 | match p.node { | |
7453a54e | 2727 | PatKind::Wild => "_".to_string(), |
476ff2be SL |
2728 | PatKind::Binding(_, _, ref p, _) => p.node.to_string(), |
2729 | PatKind::TupleStruct(ref p, ..) | PatKind::Path(ref p) => qpath_to_string(p), | |
7453a54e | 2730 | PatKind::Struct(ref name, ref fields, etc) => { |
476ff2be | 2731 | format!("{} {{ {}{} }}", qpath_to_string(name), |
1a4d82fc | 2732 | fields.iter().map(|&Spanned { node: ref fp, .. }| |
b039eaaf | 2733 | format!("{}: {}", fp.name, name_from_pat(&*fp.pat))) |
c1a9b12d | 2734 | .collect::<Vec<String>>().join(", "), |
1a4d82fc JJ |
2735 | if etc { ", ..." } else { "" } |
2736 | ) | |
476ff2be | 2737 | } |
3157f602 | 2738 | PatKind::Tuple(ref elts, _) => format!("({})", elts.iter().map(|p| name_from_pat(&**p)) |
c1a9b12d | 2739 | .collect::<Vec<String>>().join(", ")), |
7453a54e SL |
2740 | PatKind::Box(ref p) => name_from_pat(&**p), |
2741 | PatKind::Ref(ref p, _) => name_from_pat(&**p), | |
2742 | PatKind::Lit(..) => { | |
2743 | warn!("tried to get argument name from PatKind::Lit, \ | |
1a4d82fc JJ |
2744 | which is silly in function arguments"); |
2745 | "()".to_string() | |
2746 | }, | |
7453a54e | 2747 | PatKind::Range(..) => panic!("tried to get argument name from PatKind::Range, \ |
1a4d82fc | 2748 | which is not allowed in function arguments"), |
c30ab7b3 | 2749 | PatKind::Slice(ref begin, ref mid, ref end) => { |
1a4d82fc JJ |
2750 | let begin = begin.iter().map(|p| name_from_pat(&**p)); |
2751 | let mid = mid.as_ref().map(|p| format!("..{}", name_from_pat(&**p))).into_iter(); | |
2752 | let end = end.iter().map(|p| name_from_pat(&**p)); | |
c1a9b12d | 2753 | format!("[{}]", begin.chain(mid).chain(end).collect::<Vec<_>>().join(", ")) |
1a4d82fc | 2754 | }, |
1a4d82fc JJ |
2755 | } |
2756 | } | |
2757 | ||
32a655c1 SL |
2758 | fn print_const_expr(cx: &DocContext, body: hir::BodyId) -> String { |
2759 | cx.tcx.hir.node_to_pretty_string(body.node_id) | |
2760 | } | |
2761 | ||
476ff2be | 2762 | /// Given a type Path, resolve it to a Type using the TyCtxt |
1a4d82fc JJ |
2763 | fn resolve_type(cx: &DocContext, |
2764 | path: Path, | |
2765 | id: ast::NodeId) -> Type { | |
b039eaaf | 2766 | debug!("resolve_type({:?},{:?})", path, id); |
b039eaaf | 2767 | |
476ff2be | 2768 | let is_generic = match path.def { |
7453a54e | 2769 | Def::PrimTy(p) => match p { |
9e0c209e SL |
2770 | hir::TyStr => return Primitive(PrimitiveType::Str), |
2771 | hir::TyBool => return Primitive(PrimitiveType::Bool), | |
2772 | hir::TyChar => return Primitive(PrimitiveType::Char), | |
2773 | hir::TyInt(int_ty) => return Primitive(int_ty.into()), | |
2774 | hir::TyUint(uint_ty) => return Primitive(uint_ty.into()), | |
2775 | hir::TyFloat(float_ty) => return Primitive(float_ty.into()), | |
1a4d82fc | 2776 | }, |
7453a54e | 2777 | Def::SelfTy(..) if path.segments.len() == 1 => { |
a7813a04 | 2778 | return Generic(keywords::SelfType.name().to_string()); |
c34b1796 | 2779 | } |
5bcae85e | 2780 | Def::SelfTy(..) | Def::TyParam(..) | Def::AssociatedTy(..) => true, |
62682a34 | 2781 | _ => false, |
1a4d82fc | 2782 | }; |
476ff2be | 2783 | let did = register_def(&*cx, path.def); |
62682a34 | 2784 | ResolvedPath { path: path, typarams: None, did: did, is_generic: is_generic } |
1a4d82fc JJ |
2785 | } |
2786 | ||
7453a54e | 2787 | fn register_def(cx: &DocContext, def: Def) -> DefId { |
b039eaaf SL |
2788 | debug!("register_def({:?})", def); |
2789 | ||
1a4d82fc | 2790 | let (did, kind) = match def { |
c30ab7b3 SL |
2791 | Def::Fn(i) => (i, TypeKind::Function), |
2792 | Def::TyAlias(i) => (i, TypeKind::Typedef), | |
2793 | Def::Enum(i) => (i, TypeKind::Enum), | |
2794 | Def::Trait(i) => (i, TypeKind::Trait), | |
2795 | Def::Struct(i) => (i, TypeKind::Struct), | |
2796 | Def::Union(i) => (i, TypeKind::Union), | |
2797 | Def::Mod(i) => (i, TypeKind::Module), | |
2798 | Def::Static(i, _) => (i, TypeKind::Static), | |
476ff2be | 2799 | Def::Variant(i) => (cx.tcx.parent_def_id(i).unwrap(), TypeKind::Enum), |
c30ab7b3 | 2800 | Def::SelfTy(Some(def_id), _) => (def_id, TypeKind::Trait), |
9e0c209e SL |
2801 | Def::SelfTy(_, Some(impl_def_id)) => { |
2802 | return impl_def_id | |
5bcae85e | 2803 | } |
1a4d82fc JJ |
2804 | _ => return def.def_id() |
2805 | }; | |
e9174d1e | 2806 | if did.is_local() { return did } |
1a4d82fc | 2807 | inline::record_extern_fqn(cx, did, kind); |
c30ab7b3 | 2808 | if let TypeKind::Trait = kind { |
476ff2be | 2809 | let t = inline::build_external_trait(cx, did); |
a7813a04 | 2810 | cx.external_traits.borrow_mut().insert(did, t); |
1a4d82fc | 2811 | } |
54a0048b | 2812 | did |
1a4d82fc JJ |
2813 | } |
2814 | ||
476ff2be | 2815 | fn resolve_use_source(cx: &DocContext, path: Path) -> ImportSource { |
1a4d82fc | 2816 | ImportSource { |
476ff2be SL |
2817 | did: if path.def == Def::Err { |
2818 | None | |
2819 | } else { | |
2820 | Some(register_def(cx, path.def)) | |
2821 | }, | |
1a4d82fc | 2822 | path: path, |
1a4d82fc JJ |
2823 | } |
2824 | } | |
2825 | ||
85aaf69f | 2826 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc JJ |
2827 | pub struct Macro { |
2828 | pub source: String, | |
d9579d0f | 2829 | pub imported_from: Option<String>, |
1a4d82fc JJ |
2830 | } |
2831 | ||
2832 | impl Clean<Item> for doctree::Macro { | |
2833 | fn clean(&self, cx: &DocContext) -> Item { | |
9e0c209e | 2834 | let name = self.name.clean(cx); |
1a4d82fc | 2835 | Item { |
92a42be0 | 2836 | name: Some(name.clone()), |
1a4d82fc JJ |
2837 | attrs: self.attrs.clean(cx), |
2838 | source: self.whence.clean(cx), | |
a7813a04 | 2839 | visibility: Some(Public), |
1a4d82fc | 2840 | stability: self.stab.clean(cx), |
9cc50fc6 | 2841 | deprecation: self.depr.clean(cx), |
32a655c1 | 2842 | def_id: self.def_id, |
1a4d82fc | 2843 | inner: MacroItem(Macro { |
92a42be0 | 2844 | source: format!("macro_rules! {} {{\n{}}}", |
9e0c209e SL |
2845 | name, |
2846 | self.matchers.iter().map(|span| { | |
2847 | format!(" {} => {{ ... }};\n", span.to_src(cx)) | |
2848 | }).collect::<String>()), | |
d9579d0f | 2849 | imported_from: self.imported_from.clean(cx), |
1a4d82fc JJ |
2850 | }), |
2851 | } | |
2852 | } | |
2853 | } | |
2854 | ||
85aaf69f | 2855 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
1a4d82fc | 2856 | pub struct Stability { |
b039eaaf | 2857 | pub level: stability::StabilityLevel, |
85aaf69f SL |
2858 | pub feature: String, |
2859 | pub since: String, | |
2860 | pub deprecated_since: String, | |
476ff2be SL |
2861 | pub deprecated_reason: String, |
2862 | pub unstable_reason: String, | |
e9174d1e | 2863 | pub issue: Option<u32> |
1a4d82fc JJ |
2864 | } |
2865 | ||
9cc50fc6 SL |
2866 | #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] |
2867 | pub struct Deprecation { | |
2868 | pub since: String, | |
2869 | pub note: String, | |
2870 | } | |
2871 | ||
1a4d82fc JJ |
2872 | impl Clean<Stability> for attr::Stability { |
2873 | fn clean(&self, _: &DocContext) -> Stability { | |
2874 | Stability { | |
b039eaaf | 2875 | level: stability::StabilityLevel::from_attr_level(&self.level), |
85aaf69f | 2876 | feature: self.feature.to_string(), |
b039eaaf SL |
2877 | since: match self.level { |
2878 | attr::Stable {ref since} => since.to_string(), | |
2879 | _ => "".to_string(), | |
2880 | }, | |
9cc50fc6 SL |
2881 | deprecated_since: match self.rustc_depr { |
2882 | Some(attr::RustcDeprecation {ref since, ..}) => since.to_string(), | |
b039eaaf SL |
2883 | _=> "".to_string(), |
2884 | }, | |
476ff2be SL |
2885 | deprecated_reason: match self.rustc_depr { |
2886 | Some(ref depr) => depr.reason.to_string(), | |
2887 | _ => "".to_string(), | |
2888 | }, | |
2889 | unstable_reason: match self.level { | |
2890 | attr::Unstable { reason: Some(ref reason), .. } => reason.to_string(), | |
2891 | _ => "".to_string(), | |
b039eaaf SL |
2892 | }, |
2893 | issue: match self.level { | |
2894 | attr::Unstable {issue, ..} => Some(issue), | |
2895 | _ => None, | |
2896 | } | |
1a4d82fc JJ |
2897 | } |
2898 | } | |
2899 | } | |
2900 | ||
62682a34 | 2901 | impl<'a> Clean<Stability> for &'a attr::Stability { |
b039eaaf SL |
2902 | fn clean(&self, dc: &DocContext) -> Stability { |
2903 | (**self).clean(dc) | |
62682a34 SL |
2904 | } |
2905 | } | |
2906 | ||
9cc50fc6 SL |
2907 | impl Clean<Deprecation> for attr::Deprecation { |
2908 | fn clean(&self, _: &DocContext) -> Deprecation { | |
2909 | Deprecation { | |
2910 | since: self.since.as_ref().map_or("".to_string(), |s| s.to_string()), | |
2911 | note: self.note.as_ref().map_or("".to_string(), |s| s.to_string()), | |
2912 | } | |
2913 | } | |
2914 | } | |
2915 | ||
1a4d82fc | 2916 | /// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>` |
85aaf69f | 2917 | #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)] |
1a4d82fc JJ |
2918 | pub struct TypeBinding { |
2919 | pub name: String, | |
2920 | pub ty: Type | |
2921 | } | |
2922 | ||
e9174d1e | 2923 | impl Clean<TypeBinding> for hir::TypeBinding { |
1a4d82fc JJ |
2924 | fn clean(&self, cx: &DocContext) -> TypeBinding { |
2925 | TypeBinding { | |
b039eaaf | 2926 | name: self.name.clean(cx), |
1a4d82fc JJ |
2927 | ty: self.ty.clean(cx) |
2928 | } | |
2929 | } | |
2930 | } |