rust/src/librustdoc/clean/mod.rs

2422 lines
94 KiB
Rust
Raw Normal View History

2013-08-15 16:28:54 -04:00
//! This module contains the "cleaned" pieces of the AST, and the functions
//! that clean them.
mod auto_trait;
mod blanket_impl;
2019-12-22 17:42:04 -05:00
pub mod cfg;
pub mod inline;
mod simplify;
pub mod types;
2019-12-22 17:42:04 -05:00
pub mod utils;
2019-12-22 17:42:04 -05:00
use rustc::middle::lang_items;
use rustc::middle::resolve_lifetime as rl;
use rustc::middle::stability;
use rustc::ty::fold::TypeFolder;
2019-12-22 17:42:04 -05:00
use rustc::ty::subst::InternalSubsts;
use rustc::ty::{self, AdtKind, Lift, Ty, TyCtxt};
use rustc_ast::ast::{self, Ident};
use rustc_attr as attr;
2019-12-24 05:02:53 +01:00
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX};
2019-12-22 17:42:04 -05:00
use rustc_index::vec::{Idx, IndexVec};
2020-01-06 23:31:06 +01:00
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
use rustc_mir::const_eval::is_min_const_fn;
use rustc_span::hygiene::MacroKind;
use rustc_span::symbol::{kw, sym};
use rustc_span::{self, Pos};
2019-12-22 17:42:04 -05:00
use rustc_typeck::hir_ty_to_ty;
Generate documentation for auto-trait impls A new section is added to both both struct and trait doc pages. On struct/enum pages, a new 'Auto Trait Implementations' section displays any synthetic implementations for auto traits. Currently, this is only done for Send and Sync. On trait pages, a new 'Auto Implementors' section displays all types which automatically implement the trait. Effectively, this is a list of all public types in the standard library. Synthesized impls for a particular auto trait ('synthetic impls') take into account generic bounds. For example, a type 'struct Foo<T>(T)' will have 'impl<T> Send for Foo<T> where T: Send' generated for it. Manual implementations of auto traits are also taken into account. If we have the following types: 'struct Foo<T>(T)' 'struct Wrapper<T>(Foo<T>)' 'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes this sound somehow Then Wrapper will have the following impl generated: 'impl<T> Send for Wrapper<T>' reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send' to hold Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are taken into account by synthetic impls However, if a type can *never* implement a particular auto trait (e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be generated (in this case, 'impl<T> !Send for MyStruct<T>') All of this means that a user should be able to copy-paste a synthetic impl into their code, without any observable changes in behavior (assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
use std::collections::hash_map::Entry;
use std::default::Default;
2019-12-22 17:42:04 -05:00
use std::hash::Hash;
use std::rc::Rc;
use std::u32;
2019-12-22 17:42:04 -05:00
use std::{mem, vec};
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
use crate::core::{self, DocContext, ImplTraitParam};
2019-02-23 16:40:07 +09:00
use crate::doctree;
2019-12-09 17:53:42 +01:00
use utils::*;
pub use utils::{get_auto_trait_and_blanket_impls, krate, register_res};
2020-02-15 12:10:59 +09:00
pub use self::types::FnRetTy::*;
pub use self::types::ItemEnum::*;
pub use self::types::SelfTy::*;
2019-12-22 17:42:04 -05:00
pub use self::types::Type::*;
pub use self::types::Visibility::{Inherited, Public};
pub use self::types::*;
Generate documentation for auto-trait impls A new section is added to both both struct and trait doc pages. On struct/enum pages, a new 'Auto Trait Implementations' section displays any synthetic implementations for auto traits. Currently, this is only done for Send and Sync. On trait pages, a new 'Auto Implementors' section displays all types which automatically implement the trait. Effectively, this is a list of all public types in the standard library. Synthesized impls for a particular auto trait ('synthetic impls') take into account generic bounds. For example, a type 'struct Foo<T>(T)' will have 'impl<T> Send for Foo<T> where T: Send' generated for it. Manual implementations of auto traits are also taken into account. If we have the following types: 'struct Foo<T>(T)' 'struct Wrapper<T>(Foo<T>)' 'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes this sound somehow Then Wrapper will have the following impl generated: 'impl<T> Send for Wrapper<T>' reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send' to hold Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are taken into account by synthetic impls However, if a type can *never* implement a particular auto trait (e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be generated (in this case, 'impl<T> !Send for MyStruct<T>') All of this means that a user should be able to copy-paste a synthetic impl into their code, without any observable changes in behavior (assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
const FN_OUTPUT_NAME: &str = "Output";
2013-08-15 16:28:54 -04:00
pub trait Clean<T> {
fn clean(&self, cx: &DocContext<'_>) -> T;
2013-08-15 16:28:54 -04:00
}
impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
fn clean(&self, cx: &DocContext<'_>) -> Vec<U> {
self.iter().map(|x| x.clean(cx)).collect()
}
}
impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
fn clean(&self, cx: &DocContext<'_>) -> IndexVec<V, U> {
self.iter().map(|x| x.clean(cx)).collect()
}
}
2019-11-28 21:47:10 +01:00
impl<T: Clean<U>, U> Clean<U> for &T {
fn clean(&self, cx: &DocContext<'_>) -> U {
(**self).clean(cx)
}
}
impl<T: Clean<U>, U> Clean<U> for Rc<T> {
fn clean(&self, cx: &DocContext<'_>) -> U {
(**self).clean(cx)
}
}
2013-08-15 16:28:54 -04:00
impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
fn clean(&self, cx: &DocContext<'_>) -> Option<U> {
2016-02-28 12:11:13 +01:00
self.as_ref().map(|v| v.clean(cx))
2013-08-15 16:28:54 -04:00
}
}
2019-12-22 17:42:04 -05:00
impl<T, U> Clean<U> for ty::Binder<T>
where
T: Clean<U>,
{
fn clean(&self, cx: &DocContext<'_>) -> U {
self.skip_binder().clean(cx)
}
}
2015-11-22 21:02:04 +02:00
impl Clean<ExternalCrate> for CrateNum {
fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
let krate_span = cx.tcx.def_span(root);
2018-08-18 12:14:09 +02:00
let krate_src = cx.sess().source_map().span_to_filename(krate_span);
// Collect all inner modules which are tagged as implementations of
// primitives.
//
// Note that this loop only searches the top-level items of the crate,
// and this is intentional. If we were to search the entire crate for an
// item tagged with `#[doc(primitive)]` then we would also have to
// search the entirety of external modules for items tagged
// `#[doc(primitive)]`, which is a pretty inefficient process (decoding
// all that metadata unconditionally).
//
// In order to keep the metadata load under control, the
// `#[doc(primitive)]` feature is explicitly designed to only allow the
// primitive tags to show up as the top level items in a crate.
//
// Also note that this does not attempt to deal with modules tagged
// duplicately for the same primitive. This is handled later on when
// rendering by delegating everything to a hash map.
let as_primitive = |res: Res| {
if let Res::Def(DefKind::Mod, def_id) = res {
let attrs = cx.tcx.get_attrs(def_id).clean(cx);
let mut prim = None;
for attr in attrs.lists(sym::doc) {
if let Some(v) = attr.value_str() {
if attr.check_name(sym::primitive) {
prim = PrimitiveType::from_str(&v.as_str());
if prim.is_some() {
break;
}
// FIXME: should warn on unknown primitives?
}
}
}
return prim.map(|p| (def_id, p, attrs));
}
None
};
let primitives = if root.is_local() {
2019-12-22 17:42:04 -05:00
cx.tcx
.hir()
.krate()
2020-02-07 16:43:36 +01:00
.item
2019-12-22 17:42:04 -05:00
.module
.item_ids
.iter()
.filter_map(|&id| {
let item = cx.tcx.hir().expect_item(id.id);
match item.kind {
hir::ItemKind::Mod(_) => {
as_primitive(Res::Def(DefKind::Mod, cx.tcx.hir().local_def_id(id.id)))
}
hir::ItemKind::Use(ref path, hir::UseKind::Single)
if item.vis.node.is_pub() =>
{
as_primitive(path.res).map(|(_, prim, attrs)| {
// Pretend the primitive is local.
(cx.tcx.hir().local_def_id(id.id), prim, attrs)
})
}
_ => None,
}
2019-12-22 17:42:04 -05:00
})
.collect()
} else {
2019-12-22 17:42:04 -05:00
cx.tcx
.item_children(root)
.iter()
.map(|item| item.res)
.filter_map(as_primitive)
.collect()
};
let as_keyword = |res: Res| {
if let Res::Def(DefKind::Mod, def_id) = res {
2018-05-28 21:30:01 +02:00
let attrs = cx.tcx.get_attrs(def_id).clean(cx);
let mut keyword = None;
for attr in attrs.lists(sym::doc) {
2018-05-28 21:30:01 +02:00
if let Some(v) = attr.value_str() {
if attr.check_name(sym::keyword) {
2019-05-11 17:41:37 +03:00
if v.is_doc_keyword() {
keyword = Some(v.to_string());
break;
2018-05-28 21:30:01 +02:00
}
// FIXME: should warn on unknown keywords?
}
}
}
return keyword.map(|p| (def_id, p, attrs));
}
None
};
let keywords = if root.is_local() {
2019-12-22 17:42:04 -05:00
cx.tcx
.hir()
.krate()
2020-02-07 16:43:36 +01:00
.item
2019-12-22 17:42:04 -05:00
.module
.item_ids
.iter()
.filter_map(|&id| {
let item = cx.tcx.hir().expect_item(id.id);
match item.kind {
hir::ItemKind::Mod(_) => {
as_keyword(Res::Def(DefKind::Mod, cx.tcx.hir().local_def_id(id.id)))
}
hir::ItemKind::Use(ref path, hir::UseKind::Single)
if item.vis.node.is_pub() =>
{
as_keyword(path.res).map(|(_, prim, attrs)| {
(cx.tcx.hir().local_def_id(id.id), prim, attrs)
})
}
_ => None,
2018-05-28 21:30:01 +02:00
}
2019-12-22 17:42:04 -05:00
})
.collect()
2018-05-28 21:30:01 +02:00
} else {
2019-12-22 17:42:04 -05:00
cx.tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
2018-05-28 21:30:01 +02:00
};
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-02 15:39:32 -07:00
ExternalCrate {
name: cx.tcx.crate_name(*self).to_string(),
src: krate_src,
attrs: cx.tcx.get_attrs(root).clean(cx),
primitives,
2018-05-28 21:30:01 +02:00
keywords,
2013-08-15 16:28:54 -04:00
}
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Item> for doctree::Module<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
2013-08-15 16:28:54 -04:00
let name = if self.name.is_some() {
2018-07-29 15:39:51 +02:00
self.name.expect("No name provided").clean(cx)
2013-08-15 16:28:54 -04:00
} else {
String::new()
2013-08-15 16:28:54 -04:00
};
// maintain a stack of mod ids, for doc comment path resolution
// but we also need to resolve the module's own docs based on whether its docs were written
// inside or outside the module, so check for that
let attrs = self.attrs.clean(cx);
2018-01-01 13:01:19 +05:30
let mut items: Vec<Item> = vec![];
2019-01-10 20:27:44 -05:00
items.extend(self.extern_crates.iter().flat_map(|x| x.clean(cx)));
items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
items.extend(self.structs.iter().map(|x| x.clean(cx)));
items.extend(self.unions.iter().map(|x| x.clean(cx)));
items.extend(self.enums.iter().map(|x| x.clean(cx)));
items.extend(self.fns.iter().map(|x| x.clean(cx)));
2019-06-12 11:43:15 +03:00
items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
items.extend(self.mods.iter().map(|x| x.clean(cx)));
items.extend(self.typedefs.iter().map(|x| x.clean(cx)));
2019-08-01 00:41:54 +01:00
items.extend(self.opaque_tys.iter().map(|x| x.clean(cx)));
items.extend(self.statics.iter().map(|x| x.clean(cx)));
items.extend(self.constants.iter().map(|x| x.clean(cx)));
items.extend(self.traits.iter().map(|x| x.clean(cx)));
items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
items.extend(self.macros.iter().map(|x| x.clean(cx)));
items.extend(self.proc_macros.iter().map(|x| x.clean(cx)));
2019-02-05 14:27:09 +01:00
items.extend(self.trait_aliases.iter().map(|x| x.clean(cx)));
// determine if we should display the inner contents or
// the outer `mod` item for the source code.
let whence = {
2020-02-22 16:07:05 +02:00
let sm = cx.sess().source_map();
let outer = sm.lookup_char_pos(self.where_outer.lo());
let inner = sm.lookup_char_pos(self.where_inner.lo());
if outer.file.start_pos == inner.file.start_pos {
// mod foo { ... }
self.where_outer
} else {
2018-08-18 12:13:52 +02:00
// mod foo; (and a separate SourceFile for the contents)
self.where_inner
}
};
2013-08-15 16:28:54 -04:00
Item {
name: Some(name),
attrs,
source: whence.clean(cx),
visibility: self.vis.clean(cx),
2019-07-24 16:28:51 -04:00
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id),
2019-12-22 17:42:04 -05:00
inner: ModuleItem(Module { is_crate: self.is_crate, items }),
2013-08-15 16:28:54 -04:00
}
}
}
impl Clean<Attributes> for [ast::Attribute] {
fn clean(&self, cx: &DocContext<'_>) -> Attributes {
Attributes::from_ast(cx.sess().diagnostic(), self)
2013-08-15 16:28:54 -04:00
}
}
2019-12-01 16:08:58 +01:00
impl Clean<GenericBound> for hir::GenericBound<'_> {
fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
2013-08-15 16:28:54 -04:00
match *self {
2018-06-14 12:23:46 +01:00
hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
hir::GenericBound::Trait(ref t, modifier) => {
GenericBound::TraitBound(t.clean(cx), modifier)
}
2013-08-15 16:28:54 -04:00
}
}
}
impl<'a, 'tcx> Clean<GenericBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>) {
fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
let (trait_ref, ref bounds) = *self;
inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
2019-12-22 17:42:04 -05:00
let path = external_path(
cx,
cx.tcx.item_name(trait_ref.def_id),
Some(trait_ref.def_id),
true,
bounds.clone(),
trait_ref.substs,
);
debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
// collect any late bound regions
let mut late_bounds = vec![];
for ty_s in trait_ref.input_types().skip(1) {
2019-09-16 19:08:35 +01:00
if let ty::Tuple(ts) = ty_s.kind {
2015-01-31 12:20:46 -05:00
for &ty_s in ts {
2019-09-16 19:08:35 +01:00
if let ty::Ref(ref reg, _, _) = ty_s.expect_ty().kind {
if let &ty::RegionKind::ReLateBound(..) = *reg {
debug!(" hit an ReLateBound {:?}", reg);
if let Some(Lifetime(name)) = reg.clean(cx) {
late_bounds.push(GenericParamDef {
name,
kind: GenericParamDefKind::Lifetime,
});
}
}
}
}
}
}
2018-06-14 12:23:46 +01:00
GenericBound::TraitBound(
PolyTrait {
trait_: ResolvedPath {
path,
param_names: None,
did: trait_ref.def_id,
is_generic: false,
},
generic_params: late_bounds,
},
2019-12-22 17:42:04 -05:00
hir::TraitBoundModifier::None,
)
}
}
impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> {
fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
(self, vec![]).clean(cx)
}
}
impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
fn clean(&self, cx: &DocContext<'_>) -> Option<Vec<GenericBound>> {
let mut v = Vec::new();
2018-06-14 12:23:46 +01:00
v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
2019-12-22 17:42:04 -05:00
v.extend(self.types().map(|t| {
GenericBound::TraitBound(
PolyTrait { trait_: t.clean(cx), generic_params: Vec::new() },
hir::TraitBoundModifier::None,
)
}));
if !v.is_empty() { Some(v) } else { None }
}
}
2015-07-31 00:04:06 -07:00
impl Clean<Lifetime> for hir::Lifetime {
fn clean(&self, cx: &DocContext<'_>) -> Lifetime {
if self.hir_id != hir::DUMMY_HIR_ID {
let def = cx.tcx.named_region(self.hir_id);
Generate documentation for auto-trait impls A new section is added to both both struct and trait doc pages. On struct/enum pages, a new 'Auto Trait Implementations' section displays any synthetic implementations for auto traits. Currently, this is only done for Send and Sync. On trait pages, a new 'Auto Implementors' section displays all types which automatically implement the trait. Effectively, this is a list of all public types in the standard library. Synthesized impls for a particular auto trait ('synthetic impls') take into account generic bounds. For example, a type 'struct Foo<T>(T)' will have 'impl<T> Send for Foo<T> where T: Send' generated for it. Manual implementations of auto traits are also taken into account. If we have the following types: 'struct Foo<T>(T)' 'struct Wrapper<T>(Foo<T>)' 'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes this sound somehow Then Wrapper will have the following impl generated: 'impl<T> Send for Wrapper<T>' reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send' to hold Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are taken into account by synthetic impls However, if a type can *never* implement a particular auto trait (e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be generated (in this case, 'impl<T> !Send for MyStruct<T>') All of this means that a user should be able to copy-paste a synthetic impl into their code, without any observable changes in behavior (assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
match def {
2019-12-22 17:42:04 -05:00
Some(rl::Region::EarlyBound(_, node_id, _))
| Some(rl::Region::LateBound(_, node_id, _))
| Some(rl::Region::Free(_, node_id)) => {
Generate documentation for auto-trait impls A new section is added to both both struct and trait doc pages. On struct/enum pages, a new 'Auto Trait Implementations' section displays any synthetic implementations for auto traits. Currently, this is only done for Send and Sync. On trait pages, a new 'Auto Implementors' section displays all types which automatically implement the trait. Effectively, this is a list of all public types in the standard library. Synthesized impls for a particular auto trait ('synthetic impls') take into account generic bounds. For example, a type 'struct Foo<T>(T)' will have 'impl<T> Send for Foo<T> where T: Send' generated for it. Manual implementations of auto traits are also taken into account. If we have the following types: 'struct Foo<T>(T)' 'struct Wrapper<T>(Foo<T>)' 'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes this sound somehow Then Wrapper will have the following impl generated: 'impl<T> Send for Wrapper<T>' reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send' to hold Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are taken into account by synthetic impls However, if a type can *never* implement a particular auto trait (e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be generated (in this case, 'impl<T> !Send for MyStruct<T>') All of this means that a user should be able to copy-paste a synthetic impl into their code, without any observable changes in behavior (assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() {
return lt;
}
2016-09-01 10:21:12 +03:00
}
Generate documentation for auto-trait impls A new section is added to both both struct and trait doc pages. On struct/enum pages, a new 'Auto Trait Implementations' section displays any synthetic implementations for auto traits. Currently, this is only done for Send and Sync. On trait pages, a new 'Auto Implementors' section displays all types which automatically implement the trait. Effectively, this is a list of all public types in the standard library. Synthesized impls for a particular auto trait ('synthetic impls') take into account generic bounds. For example, a type 'struct Foo<T>(T)' will have 'impl<T> Send for Foo<T> where T: Send' generated for it. Manual implementations of auto traits are also taken into account. If we have the following types: 'struct Foo<T>(T)' 'struct Wrapper<T>(Foo<T>)' 'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes this sound somehow Then Wrapper will have the following impl generated: 'impl<T> Send for Wrapper<T>' reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send' to hold Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are taken into account by synthetic impls However, if a type can *never* implement a particular auto trait (e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be generated (in this case, 'impl<T> !Send for MyStruct<T>') All of this means that a user should be able to copy-paste a synthetic impl into their code, without any observable changes in behavior (assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
_ => {}
2016-09-01 10:21:12 +03:00
}
}
2018-06-09 23:25:33 +03:00
Lifetime(self.name.ident().to_string())
2013-08-15 16:28:54 -04:00
}
}
2019-12-01 16:08:58 +01:00
impl Clean<Lifetime> for hir::GenericParam<'_> {
fn clean(&self, _: &DocContext<'_>) -> Lifetime {
2018-05-26 00:27:54 +01:00
match self.kind {
2018-05-28 13:33:28 +01:00
hir::GenericParamKind::Lifetime { .. } => {
if !self.bounds.is_empty() {
2018-05-28 13:33:28 +01:00
let mut bounds = self.bounds.iter().map(|bound| match bound {
hir::GenericBound::Outlives(lt) => lt,
2018-05-28 13:33:28 +01:00
_ => panic!(),
});
2018-07-29 15:39:51 +02:00
let name = bounds.next().expect("no more bounds").name.ident();
2018-06-09 23:25:33 +03:00
let mut s = format!("{}: {}", self.name.ident(), name);
2018-05-28 13:33:28 +01:00
for bound in bounds {
2018-06-09 23:25:33 +03:00
s.push_str(&format!(" + {}", bound.name.ident()));
2018-05-26 00:27:54 +01:00
}
Lifetime(s)
} else {
2018-06-09 23:25:33 +03:00
Lifetime(self.name.ident().to_string())
2018-05-26 00:27:54 +01:00
}
}
2018-05-26 00:27:54 +01:00
_ => panic!(),
}
}
}
impl Clean<Constant> for hir::ConstArg {
fn clean(&self, cx: &DocContext<'_>) -> Constant {
Constant {
type_: cx.tcx.type_of(cx.tcx.hir().body_owner_def_id(self.value.body)).clean(cx),
expr: print_const_expr(cx, self.value.body),
value: None,
is_literal: is_literal_expr(cx, self.value.body.hir_id),
}
}
}
2019-06-11 12:50:17 +03:00
impl Clean<Lifetime> for ty::GenericParamDef {
fn clean(&self, _cx: &DocContext<'_>) -> Lifetime {
Lifetime(self.name.to_string())
}
}
impl Clean<Option<Lifetime>> for ty::RegionKind {
fn clean(&self, cx: &DocContext<'_>) -> Option<Lifetime> {
match *self {
ty::ReStatic => Some(Lifetime::statik()),
ty::ReLateBound(_, ty::BrNamed(_, name)) => Some(Lifetime(name.to_string())),
2015-04-17 10:05:25 -04:00
ty::ReEarlyBound(ref data) => Some(Lifetime(data.name.clean(cx))),
2019-12-22 17:42:04 -05:00
ty::ReLateBound(..)
| ty::ReFree(..)
| ty::ReScope(..)
| ty::ReVar(..)
| ty::RePlaceholder(..)
| ty::ReEmpty(_)
2019-12-22 17:42:04 -05:00
| ty::ReClosureBound(_)
| ty::ReErased => {
debug!("cannot clean region {:?}", self);
None
}
}
}
}
2019-12-01 16:08:58 +01:00
impl Clean<WherePredicate> for hir::WherePredicate<'_> {
fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
2014-12-02 15:03:02 -08:00
match *self {
2019-12-22 17:42:04 -05:00
hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate {
ty: wbp.bounded_ty.clean(cx),
bounds: wbp.bounds.clean(cx),
},
2019-12-22 17:42:04 -05:00
hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
lifetime: wrp.lifetime.clean(cx),
bounds: wrp.bounds.clean(cx),
},
hir::WherePredicate::EqPredicate(ref wrp) => {
2019-12-22 17:42:04 -05:00
WherePredicate::EqPredicate { lhs: wrp.lhs_ty.clean(cx), rhs: wrp.rhs_ty.clean(cx) }
2014-12-02 15:03:02 -08:00
}
}
}
}
impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
use rustc::ty::Predicate;
match *self {
Predicate::Trait(ref pred, _) => Some(pred.clean(cx)),
Predicate::Subtype(ref pred) => Some(pred.clean(cx)),
Predicate::RegionOutlives(ref pred) => pred.clean(cx),
Predicate::TypeOutlives(ref pred) => pred.clean(cx),
Predicate::Projection(ref pred) => Some(pred.clean(cx)),
2019-12-22 17:42:04 -05:00
Predicate::WellFormed(..)
| Predicate::ObjectSafe(..)
| Predicate::ClosureKind(..)
| Predicate::ConstEvaluatable(..) => panic!("not user writable"),
}
}
}
impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> {
fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
WherePredicate::BoundPredicate {
ty: self.trait_ref.self_ty().clean(cx),
2019-12-22 17:42:04 -05:00
bounds: vec![self.trait_ref.clean(cx)],
}
}
}
2017-03-09 21:47:09 -05:00
impl<'tcx> Clean<WherePredicate> for ty::SubtypePredicate<'tcx> {
fn clean(&self, _cx: &DocContext<'_>) -> WherePredicate {
2019-12-22 17:42:04 -05:00
panic!(
"subtype predicates are an internal rustc artifact \
and should not be seen by rustdoc"
)
2017-03-09 21:47:09 -05:00
}
}
2019-12-22 17:42:04 -05:00
impl<'tcx> Clean<Option<WherePredicate>>
for ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
{
fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
let ty::OutlivesPredicate(ref a, ref b) = *self;
match (a, b) {
(ty::ReEmpty(_), ty::ReEmpty(_)) => {
return None;
2019-12-22 17:42:04 -05:00
}
_ => {}
}
Some(WherePredicate::RegionPredicate {
2018-07-29 15:39:51 +02:00
lifetime: a.clean(cx).expect("failed to clean lifetime"),
2019-12-22 17:42:04 -05:00
bounds: vec![GenericBound::Outlives(b.clean(cx).expect("failed to clean bounds"))],
})
}
}
impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
let ty::OutlivesPredicate(ref ty, ref lt) = *self;
match lt {
ty::ReEmpty(_) => return None,
_ => {}
}
Some(WherePredicate::BoundPredicate {
ty: ty.clean(cx),
2019-12-22 17:42:04 -05:00
bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))],
})
}
}
impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
2019-12-22 17:42:04 -05:00
WherePredicate::EqPredicate { lhs: self.projection_ty.clean(cx), rhs: self.ty.clean(cx) }
}
}
impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
fn clean(&self, cx: &DocContext<'_>) -> Type {
2019-12-08 22:02:33 +00:00
let lifted = self.lift_to_tcx(cx.tcx).unwrap();
let trait_ = match lifted.trait_ref(cx.tcx).clean(cx) {
GenericBound::TraitBound(t, _) => t.trait_,
GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
};
Type::QPath {
name: cx.tcx.associated_item(self.item_def_id).ident.name.clean(cx),
self_type: box self.self_ty().clean(cx),
2019-12-22 17:42:04 -05:00
trait_: box trait_,
}
}
}
impl Clean<GenericParamDef> for ty::GenericParamDef {
fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
let (name, kind) = match self.kind {
ty::GenericParamDefKind::Lifetime => {
(self.name.to_string(), GenericParamDefKind::Lifetime)
}
ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
2019-12-22 17:42:04 -05:00
let default =
if has_default { Some(cx.tcx.type_of(self.def_id).clean(cx)) } else { None };
(
self.name.clean(cx),
GenericParamDefKind::Type {
did: self.def_id,
bounds: vec![], // These are filled in from the where-clauses.
default,
synthetic,
},
)
}
2019-12-22 17:42:04 -05:00
ty::GenericParamDefKind::Const { .. } => (
self.name.clean(cx),
GenericParamDefKind::Const {
did: self.def_id,
ty: cx.tcx.type_of(self.def_id).clean(cx),
2019-12-22 17:42:04 -05:00
},
),
};
2019-12-22 17:42:04 -05:00
GenericParamDef { name, kind }
2018-03-24 11:03:06 +09:00
}
}
2019-12-01 16:08:58 +01:00
impl Clean<GenericParamDef> for hir::GenericParam<'_> {
fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
let (name, kind) = match self.kind {
2018-05-28 13:33:28 +01:00
hir::GenericParamKind::Lifetime { .. } => {
let name = if !self.bounds.is_empty() {
2018-05-28 13:33:28 +01:00
let mut bounds = self.bounds.iter().map(|bound| match bound {
hir::GenericBound::Outlives(lt) => lt,
2018-05-28 13:33:28 +01:00
_ => panic!(),
});
2018-07-29 15:39:51 +02:00
let name = bounds.next().expect("no more bounds").name.ident();
2018-06-28 00:12:17 +03:00
let mut s = format!("{}: {}", self.name.ident(), name);
2018-05-28 13:33:28 +01:00
for bound in bounds {
2018-06-28 00:12:17 +03:00
s.push_str(&format!(" + {}", bound.name.ident()));
}
s
} else {
2018-06-28 00:12:17 +03:00
self.name.ident().to_string()
};
(name, GenericParamDefKind::Lifetime)
}
2019-12-22 17:42:04 -05:00
hir::GenericParamKind::Type { ref default, synthetic } => (
self.name.ident().name.clean(cx),
GenericParamDefKind::Type {
did: cx.tcx.hir().local_def_id(self.hir_id),
2018-05-28 13:33:28 +01:00
bounds: self.bounds.clean(cx),
default: default.clean(cx),
synthetic,
2019-12-22 17:42:04 -05:00
},
),
hir::GenericParamKind::Const { ref ty } => (
self.name.ident().name.clean(cx),
GenericParamDefKind::Const {
did: cx.tcx.hir().local_def_id(self.hir_id),
ty: ty.clean(cx),
2019-12-22 17:42:04 -05:00
},
),
};
2019-12-22 17:42:04 -05:00
GenericParamDef { name, kind }
}
}
2019-12-01 16:08:58 +01:00
impl Clean<Generics> for hir::Generics<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Generics {
// Synthetic type-parameters are inserted after normal ones.
// In order for normal parameters to be able to refer to synthetic ones,
// scans them first.
2019-12-01 16:08:58 +01:00
fn is_impl_trait(param: &hir::GenericParam<'_>) -> bool {
2018-05-26 00:27:54 +01:00
match param.kind {
hir::GenericParamKind::Type { synthetic, .. } => {
synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
}
_ => false,
}
}
2019-12-22 17:42:04 -05:00
let impl_trait_params = self
.params
.iter()
.filter(|param| is_impl_trait(param))
.map(|param| {
let param: GenericParamDef = param.clean(cx);
match param.kind {
GenericParamDefKind::Lifetime => unreachable!(),
GenericParamDefKind::Type { did, ref bounds, .. } => {
cx.impl_trait_bounds.borrow_mut().insert(did.into(), bounds.clone());
}
GenericParamDefKind::Const { .. } => unreachable!(),
}
param
})
.collect::<Vec<_>>();
2018-05-03 22:24:50 +09:00
let mut params = Vec::with_capacity(self.params.len());
for p in self.params.iter().filter(|p| !is_impl_trait(p)) {
2018-05-03 22:24:50 +09:00
let p = p.clean(cx);
params.push(p);
}
params.extend(impl_trait_params);
2019-12-22 17:42:04 -05:00
let mut generics =
Generics { params, where_predicates: self.where_clause.predicates.clean(cx) };
// Some duplicates are generated for ?Sized bounds between type params and where
// predicates. The point in here is to move the bounds definitions from type params
// to where predicates when such cases occur.
for where_pred in &mut generics.where_predicates {
match *where_pred {
WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
if bounds.is_empty() {
for param in &mut generics.params {
match param.kind {
GenericParamDefKind::Lifetime => {}
GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
if &param.name == name {
mem::swap(bounds, ty_bounds);
2019-12-22 17:42:04 -05:00
break;
}
}
GenericParamDefKind::Const { .. } => {}
}
}
}
}
_ => continue,
}
2013-08-15 16:28:54 -04:00
}
generics
2013-08-15 16:28:54 -04:00
}
}
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx>) {
fn clean(&self, cx: &DocContext<'_>) -> Generics {
use self::WherePredicate as WP;
use std::collections::BTreeMap;
let (gens, preds) = *self;
// Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
// since `Clean for ty::Predicate` would consume them.
let mut impl_trait = BTreeMap::<ImplTraitParam, Vec<GenericBound>>::default();
// Bounds in the type_params and lifetimes fields are repeated in the
// predicates field (see rustc_typeck::collect::ty_generics), so remove
// them.
2019-12-22 17:42:04 -05:00
let stripped_typarams = gens
.params
.iter()
.filter_map(|param| match param.kind {
ty::GenericParamDefKind::Lifetime => None,
ty::GenericParamDefKind::Type { synthetic, .. } => {
if param.name == kw::SelfUpper {
assert_eq!(param.index, 0);
return None;
}
if synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
impl_trait.insert(param.index.into(), vec![]);
return None;
}
Some(param.clean(cx))
}
ty::GenericParamDefKind::Const { .. } => None,
2019-12-22 17:42:04 -05:00
})
.collect::<Vec<GenericParamDef>>();
2019-07-08 20:42:45 +09:00
// param index -> [(DefId of trait, associated type name, type)]
2019-12-22 17:42:04 -05:00
let mut impl_trait_proj = FxHashMap::<u32, Vec<(DefId, String, Ty<'tcx>)>>::default();
2019-12-22 17:42:04 -05:00
let where_predicates = preds
.predicates
.iter()
.flat_map(|(p, _)| {
2019-07-08 20:42:45 +09:00
let mut projection = None;
let param_idx = (|| {
if let Some(trait_ref) = p.to_opt_poly_trait_ref() {
2019-09-16 19:08:35 +01:00
if let ty::Param(param) = trait_ref.self_ty().kind {
return Some(param.index);
}
} else if let Some(outlives) = p.to_opt_type_outlives() {
2019-09-16 19:08:35 +01:00
if let ty::Param(param) = outlives.skip_binder().0.kind {
return Some(param.index);
}
2019-07-08 20:42:45 +09:00
} else if let ty::Predicate::Projection(p) = p {
2019-09-16 19:08:35 +01:00
if let ty::Param(param) = p.skip_binder().projection_ty.self_ty().kind {
2019-07-08 20:42:45 +09:00
projection = Some(p);
return Some(param.index);
}
}
None
})();
if let Some(param_idx) = param_idx {
if let Some(b) = impl_trait.get_mut(&param_idx.into()) {
let p = p.clean(cx)?;
b.extend(
p.get_bounds()
.into_iter()
.flatten()
.cloned()
2019-12-22 17:42:04 -05:00
.filter(|b| !b.is_sized_bound(cx)),
);
2019-07-08 20:42:45 +09:00
let proj = projection
.map(|p| (p.skip_binder().projection_ty.clean(cx), p.skip_binder().ty));
if let Some(((_, trait_did, name), rhs)) =
proj.as_ref().and_then(|(lhs, rhs)| Some((lhs.projection()?, rhs)))
{
2019-12-22 17:42:04 -05:00
impl_trait_proj.entry(param_idx).or_default().push((
trait_did,
name.to_string(),
rhs,
));
}
return None;
}
}
Some(p)
})
.collect::<Vec<_>>();
for (param, mut bounds) in impl_trait {
// Move trait bounds to the front.
2019-12-22 17:42:04 -05:00
bounds.sort_by_key(|b| if let GenericBound::TraitBound(..) = b { false } else { true });
2019-07-08 20:42:45 +09:00
if let crate::core::ImplTraitParam::ParamIndex(idx) = param {
if let Some(proj) = impl_trait_proj.remove(&idx) {
for (trait_did, name, rhs) in proj {
2019-12-22 17:42:04 -05:00
simplify::merge_bounds(cx, &mut bounds, trait_did, &name, &rhs.clean(cx));
2019-07-08 20:42:45 +09:00
}
}
} else {
unreachable!();
}
cx.impl_trait_bounds.borrow_mut().insert(param, bounds);
}
// Now that `cx.impl_trait_bounds` is populated, we can process
// remaining predicates which could contain `impl Trait`.
2019-12-22 17:42:04 -05:00
let mut where_predicates =
where_predicates.into_iter().flat_map(|p| p.clean(cx)).collect::<Vec<_>>();
// Type parameters and have a Sized bound by default unless removed with
// ?Sized. Scan through the predicates and mark any type parameter with
// a Sized bound, removing the bounds as we find them.
//
// Note that associated types also have a sized bound by default, but we
2015-05-06 01:49:07 +02:00
// don't actually know the set of associated types right here so that's
// handled in cleaning associated types
let mut sized_params = FxHashSet::default();
2019-12-22 17:42:04 -05:00
where_predicates.retain(|pred| match *pred {
WP::BoundPredicate { ty: Generic(ref g), ref bounds } => {
if bounds.iter().any(|b| b.is_sized_bound(cx)) {
sized_params.insert(g.clone());
false
} else {
true
}
}
2019-12-22 17:42:04 -05:00
_ => true,
});
// Run through the type parameters again and insert a ?Sized
// unbound for any we didn't find to be Sized.
2015-01-31 12:20:46 -05:00
for tp in &stripped_typarams {
if !sized_params.contains(&tp.name) {
where_predicates.push(WP::BoundPredicate {
ty: Type::Generic(tp.name.clone()),
bounds: vec![GenericBound::maybe_sized(cx)],
})
}
}
// It would be nice to collect all of the bounds on a type and recombine
// them if possible, to avoid e.g., `where T: Foo, T: Bar, T: Sized, T: 'a`
// and instead see `where T: Foo + Bar + Sized + 'a`
Generics {
2019-12-22 17:42:04 -05:00
params: gens
.params
.iter()
.flat_map(|param| match param.kind {
ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
ty::GenericParamDefKind::Type { .. } => None,
ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
})
.chain(simplify::ty_params(stripped_typarams).into_iter())
.collect(),
where_predicates: simplify::where_clauses(cx, where_predicates),
}
}
}
2019-12-22 17:42:04 -05:00
impl<'a> Clean<Method>
2019-12-01 16:08:58 +01:00
for (&'a hir::FnSig<'a>, &'a hir::Generics<'a>, hir::BodyId, Option<hir::Defaultness>)
2019-12-22 17:42:04 -05:00
{
fn clean(&self, cx: &DocContext<'_>) -> Method {
2019-12-22 17:42:04 -05:00
let (generics, decl) =
enter_impl_trait(cx, || (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx)));
2019-03-07 16:47:40 +01:00
let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
2019-12-22 17:42:04 -05:00
Method { decl, generics, header: self.0.header, defaultness: self.3, all_types, ret_types }
2013-08-15 16:28:54 -04:00
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Item> for doctree::Function<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
2019-12-22 17:42:04 -05:00
let (generics, decl) =
enter_impl_trait(cx, || (self.generics.clean(cx), (self.decl, self.body).clean(cx)));
2018-07-12 22:00:57 +02:00
let did = cx.tcx.hir().local_def_id(self.id);
let constness = if is_min_const_fn(cx.tcx, did) {
2018-12-18 22:24:20 +01:00
hir::Constness::Const
} else {
hir::Constness::NotConst
};
2019-03-07 16:47:40 +01:00
let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
2013-08-15 16:28:54 -04:00
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
2018-12-18 22:24:20 +01:00
def_id: did,
2013-08-15 16:28:54 -04:00
inner: FunctionItem(Function {
decl,
generics,
2018-12-18 22:24:20 +01:00
header: hir::FnHeader { constness, ..self.header },
all_types,
2019-03-07 16:47:40 +01:00
ret_types,
2013-08-15 16:28:54 -04:00
}),
}
}
}
2019-12-01 16:08:58 +01:00
impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], &'a [ast::Ident]) {
fn clean(&self, cx: &DocContext<'_>) -> Arguments {
Arguments {
2019-12-22 17:42:04 -05:00
values: self
.0
.iter()
.enumerate()
.map(|(i, ty)| {
let mut name =
self.1.get(i).map(|ident| ident.to_string()).unwrap_or(String::new());
if name.is_empty() {
name = "_".to_string();
}
Argument { name, type_: ty.clean(cx) }
})
.collect(),
}
}
}
2019-12-01 16:08:58 +01:00
impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], hir::BodyId) {
fn clean(&self, cx: &DocContext<'_>) -> Arguments {
let body = cx.tcx.hir().body(self.1);
Arguments {
2019-12-22 17:42:04 -05:00
values: self
.0
.iter()
.enumerate()
.map(|(i, ty)| Argument {
name: name_from_pat(&body.params[i].pat),
type_: ty.clean(cx),
2019-12-22 17:42:04 -05:00
})
.collect(),
}
}
}
2019-12-01 16:08:58 +01:00
impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl<'a>, A)
2019-12-22 17:42:04 -05:00
where
2019-12-01 16:08:58 +01:00
(&'a [hir::Ty<'a>], A): Clean<Arguments>,
{
fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
2013-08-15 16:28:54 -04:00
FnDecl {
inputs: (&self.0.inputs[..], self.1).clean(cx),
output: self.0.output.clean(cx),
c_variadic: self.0.c_variadic,
attrs: Attributes::default(),
2013-08-15 16:28:54 -04:00
}
}
}
2019-06-11 12:50:17 +03:00
impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
let (did, sig) = *self;
let mut names = if cx.tcx.hir().as_local_hir_id(did).is_some() {
vec![].into_iter()
} else {
2017-05-03 09:01:49 -05:00
cx.tcx.fn_arg_names(did).into_iter()
2018-03-23 22:06:28 +09:00
};
FnDecl {
output: Return(sig.skip_binder().output().clean(cx)),
attrs: Attributes::default(),
c_variadic: sig.skip_binder().c_variadic,
inputs: Arguments {
2019-12-22 17:42:04 -05:00
values: sig
.skip_binder()
.inputs()
.iter()
.map(|t| Argument {
type_: t.clean(cx),
name: names.next().map_or(String::new(), |name| name.to_string()),
2019-12-22 17:42:04 -05:00
})
.collect(),
},
}
}
}
2020-02-15 12:10:59 +09:00
impl Clean<FnRetTy> for hir::FnRetTy<'_> {
fn clean(&self, cx: &DocContext<'_>) -> FnRetTy {
2013-08-15 16:28:54 -04:00
match *self {
2020-01-05 01:50:05 +01:00
Self::Return(ref typ) => Return(typ.clean(cx)),
Self::DefaultReturn(..) => DefaultReturn,
2013-08-15 16:28:54 -04:00
}
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Item> for doctree::Trait<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
let attrs = self.attrs.clean(cx);
2013-08-15 16:28:54 -04:00
Item {
name: Some(self.name.clean(cx)),
attrs,
source: self.whence.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
2013-08-15 16:28:54 -04:00
inner: TraitItem(Trait {
Generate documentation for auto-trait impls A new section is added to both both struct and trait doc pages. On struct/enum pages, a new 'Auto Trait Implementations' section displays any synthetic implementations for auto traits. Currently, this is only done for Send and Sync. On trait pages, a new 'Auto Implementors' section displays all types which automatically implement the trait. Effectively, this is a list of all public types in the standard library. Synthesized impls for a particular auto trait ('synthetic impls') take into account generic bounds. For example, a type 'struct Foo<T>(T)' will have 'impl<T> Send for Foo<T> where T: Send' generated for it. Manual implementations of auto traits are also taken into account. If we have the following types: 'struct Foo<T>(T)' 'struct Wrapper<T>(Foo<T>)' 'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes this sound somehow Then Wrapper will have the following impl generated: 'impl<T> Send for Wrapper<T>' reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send' to hold Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are taken into account by synthetic impls However, if a type can *never* implement a particular auto trait (e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be generated (in this case, 'impl<T> !Send for MyStruct<T>') All of this means that a user should be able to copy-paste a synthetic impl into their code, without any observable changes in behavior (assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
auto: self.is_auto.clean(cx),
unsafety: self.unsafety,
2019-06-12 11:43:15 +03:00
items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
generics: self.generics.clean(cx),
bounds: self.bounds.clean(cx),
is_auto: self.is_auto.clean(cx),
2013-08-15 16:28:54 -04:00
}),
}
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Item> for doctree::TraitAlias<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
2019-02-05 14:27:09 +01:00
let attrs = self.attrs.clean(cx);
Item {
name: Some(self.name.clean(cx)),
attrs,
source: self.whence.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id),
2019-02-05 14:27:09 +01:00
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
2019-02-05 14:27:09 +01:00
inner: TraitAliasItem(TraitAlias {
generics: self.generics.clean(cx),
bounds: self.bounds.clean(cx),
}),
}
}
}
impl Clean<bool> for hir::IsAuto {
fn clean(&self, _: &DocContext<'_>) -> bool {
match *self {
hir::IsAuto::Yes => true,
hir::IsAuto::No => false,
}
}
}
2019-12-01 16:08:58 +01:00
impl Clean<Type> for hir::TraitRef<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Type {
resolve_type(cx, self.path.clean(cx), self.hir_ref_id)
2013-08-15 16:28:54 -04:00
}
}
2019-12-01 16:08:58 +01:00
impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
fn clean(&self, cx: &DocContext<'_>) -> PolyTrait {
PolyTrait {
trait_: self.trait_ref.clean(cx),
2019-12-22 17:42:04 -05:00
generic_params: self.bound_generic_params.clean(cx),
}
2014-11-07 06:53:45 -05:00
}
}
2019-11-28 21:47:10 +01:00
impl Clean<Item> for hir::TraitItem<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
let inner = match self.kind {
hir::TraitItemKind::Const(ref ty, default) => {
2019-12-22 17:42:04 -05:00
AssocConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx, e)))
}
2020-03-05 09:57:34 -06:00
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
MethodItem((sig, &self.generics, body, None).clean(cx))
}
2020-03-05 09:57:34 -06:00
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref names)) => {
2018-05-03 22:24:50 +09:00
let (generics, decl) = enter_impl_trait(cx, || {
(self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
});
2019-03-07 16:47:40 +01:00
let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
2019-12-22 17:42:04 -05:00
TyMethodItem(TyMethod { header: sig.header, decl, generics, all_types, ret_types })
}
hir::TraitItemKind::Type(ref bounds, ref default) => {
AssocTypeItem(bounds.clean(cx), default.clean(cx))
}
};
let local_did = cx.tcx.hir().local_def_id(self.hir_id);
Item {
name: Some(self.ident.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.span.clean(cx),
2019-02-26 11:04:58 +01:00
def_id: local_did,
visibility: Visibility::Inherited,
2019-02-26 11:04:58 +01:00
stability: get_stability(cx, local_did),
deprecation: get_deprecation(cx, local_did),
inner,
}
}
}
2019-11-28 22:16:44 +01:00
impl Clean<Item> for hir::ImplItem<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
let inner = match self.kind {
hir::ImplItemKind::Const(ref ty, expr) => {
2019-12-22 17:42:04 -05:00
AssocConstItem(ty.clean(cx), Some(print_const_expr(cx, expr)))
}
2020-03-05 09:57:34 -06:00
hir::ImplItemKind::Fn(ref sig, body) => {
MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
}
2019-12-22 17:42:04 -05:00
hir::ImplItemKind::TyAlias(ref ty) => {
2020-01-10 02:07:13 +01:00
let type_ = ty.clean(cx);
let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
2020-01-10 14:46:28 +01:00
TypedefItem(Typedef { type_, generics: Generics::default(), item_type }, true)
2019-12-22 17:42:04 -05:00
}
hir::ImplItemKind::OpaqueTy(ref bounds) => OpaqueTyItem(
OpaqueTy { bounds: bounds.clean(cx), generics: Generics::default() },
true,
),
};
let local_did = cx.tcx.hir().local_def_id(self.hir_id);
Item {
name: Some(self.ident.name.clean(cx)),
source: self.span.clean(cx),
attrs: self.attrs.clean(cx),
2019-02-26 15:11:59 +01:00
def_id: local_did,
visibility: self.vis.clean(cx),
2019-02-26 15:11:59 +01:00
stability: get_stability(cx, local_did),
deprecation: get_deprecation(cx, local_did),
inner,
2013-08-15 16:28:54 -04:00
}
}
}
2019-06-11 12:50:17 +03:00
impl Clean<Item> for ty::AssocItem {
fn clean(&self, cx: &DocContext<'_>) -> Item {
let inner = match self.kind {
ty::AssocKind::Const => {
let ty = cx.tcx.type_of(self.def_id);
let default = if self.defaultness.has_value() {
Some(inline::print_inlined_const(cx, self.def_id))
} else {
None
};
AssocConstItem(ty.clean(cx), default)
2016-05-08 21:19:29 +03:00
}
ty::AssocKind::Method => {
2019-12-22 17:42:04 -05:00
let generics =
(cx.tcx.generics_of(self.def_id), cx.tcx.explicit_predicates_of(self.def_id))
.clean(cx);
let sig = cx.tcx.fn_sig(self.def_id);
let mut decl = (self.def_id, sig).clean(cx);
if self.method_has_self_argument {
let self_ty = match self.container {
2019-12-22 17:42:04 -05:00
ty::ImplContainer(def_id) => cx.tcx.type_of(def_id),
ty::TraitContainer(_) => cx.tcx.types.self_param,
};
let self_arg_ty = *sig.input(0).skip_binder();
if self_arg_ty == self_ty {
decl.inputs.values[0].type_ = Generic(String::from("Self"));
2019-09-16 19:08:35 +01:00
} else if let ty::Ref(_, ty, _) = self_arg_ty.kind {
if ty == self_ty {
match decl.inputs.values[0].type_ {
2019-12-22 17:42:04 -05:00
BorrowedRef { ref mut type_, .. } => {
**type_ = Generic(String::from("Self"))
}
_ => unreachable!(),
}
}
}
}
let provided = match self.container {
ty::ImplContainer(_) => true,
2019-12-22 17:42:04 -05:00
ty::TraitContainer(_) => self.defaultness.has_value(),
};
2019-03-07 16:47:40 +01:00
let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
if provided {
let constness = if is_min_const_fn(cx.tcx, self.def_id) {
hir::Constness::Const
} else {
hir::Constness::NotConst
};
2019-09-21 03:17:57 +00:00
let asyncness = cx.tcx.asyncness(self.def_id);
let defaultness = match self.container {
ty::ImplContainer(_) => Some(self.defaultness),
ty::TraitContainer(_) => None,
};
MethodItem(Method {
generics,
decl,
header: hir::FnHeader {
unsafety: sig.unsafety(),
abi: sig.abi(),
constness,
2019-09-19 03:21:11 +00:00
asyncness,
},
defaultness,
all_types,
2019-03-07 16:47:40 +01:00
ret_types,
})
} else {
TyMethodItem(TyMethod {
generics,
decl,
header: hir::FnHeader {
unsafety: sig.unsafety(),
abi: sig.abi(),
constness: hir::Constness::NotConst,
asyncness: hir::IsAsync::NotAsync,
},
all_types,
2019-03-07 16:47:40 +01:00
ret_types,
})
2016-05-08 21:19:29 +03:00
}
}
ty::AssocKind::Type => {
let my_name = self.ident.name.clean(cx);
if let ty::TraitContainer(did) = self.container {
// When loading a cross-crate associated type, the bounds for this type
// are actually located on the trait/impl itself, so we need to load
// all of the generics from there and then look for bounds that are
// applied to this associated type in question.
let predicates = cx.tcx.explicit_predicates_of(did);
let generics = (cx.tcx.generics_of(did), predicates).clean(cx);
2019-12-22 17:42:04 -05:00
let mut bounds = generics
.where_predicates
.iter()
.filter_map(|pred| {
let (name, self_type, trait_, bounds) = match *pred {
WherePredicate::BoundPredicate {
ty: QPath { ref name, ref self_type, ref trait_ },
ref bounds,
} => (name, self_type, trait_, bounds),
_ => return None,
};
if *name != my_name {
return None;
}
match **trait_ {
ResolvedPath { did, .. } if did == self.container.id() => {}
_ => return None,
}
match **self_type {
Generic(ref s) if *s == "Self" => {}
_ => return None,
}
Some(bounds)
})
.flat_map(|i| i.iter().cloned())
.collect::<Vec<_>>();
// Our Sized/?Sized bound didn't get handled when creating the generics
// because we didn't actually get our whole set of bounds until just now
// (some of them may have come from the trait). If we do have a sized
// bound, we remove it, and if we don't then we add the `?Sized` bound
// at the end.
match bounds.iter().position(|b| b.is_sized_bound(cx)) {
2019-12-22 17:42:04 -05:00
Some(i) => {
bounds.remove(i);
}
None => bounds.push(GenericBound::maybe_sized(cx)),
}
let ty = if self.defaultness.has_value() {
Some(cx.tcx.type_of(self.def_id))
} else {
None
};
AssocTypeItem(bounds, ty.clean(cx))
} else {
2020-01-10 02:07:13 +01:00
let type_ = cx.tcx.type_of(self.def_id).clean(cx);
let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
2019-12-22 17:42:04 -05:00
TypedefItem(
Typedef {
2020-01-10 02:07:13 +01:00
type_,
2019-12-22 17:42:04 -05:00
generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
2020-01-10 02:07:13 +01:00
item_type,
},
2019-12-22 17:42:04 -05:00
true,
)
}
}
2019-08-01 00:41:54 +01:00
ty::AssocKind::OpaqueTy => unimplemented!(),
};
let visibility = match self.container {
ty::ImplContainer(_) => self.vis.clean(cx),
ty::TraitContainer(_) => Inherited,
};
Item {
name: Some(self.ident.name.clean(cx)),
visibility,
stability: get_stability(cx, self.def_id),
2015-12-12 23:01:27 +03:00
deprecation: get_deprecation(cx, self.def_id),
def_id: self.def_id,
attrs: inline::load_attrs(cx, self.def_id).clean(cx),
source: cx.tcx.def_span(self.def_id).clean(cx),
inner,
}
}
}
2019-12-01 16:08:58 +01:00
impl Clean<Type> for hir::Ty<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Type {
use rustc_hir::*;
2019-09-26 17:25:31 +01:00
match self.kind {
2018-07-11 23:36:06 +08:00
TyKind::Never => Never,
2019-12-21 15:29:46 +01:00
TyKind::Ptr(ref m) => RawPointer(m.mutbl, box m.ty.clean(cx)),
2018-07-11 23:36:06 +08:00
TyKind::Rptr(ref l, ref m) => {
2019-12-22 17:42:04 -05:00
let lifetime = if l.is_elided() { None } else { Some(l.clean(cx)) };
BorrowedRef { lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx) }
}
2018-07-11 23:36:06 +08:00
TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
TyKind::Array(ref ty, ref length) => {
let def_id = cx.tcx.hir().local_def_id(length.hir_id);
let length = match cx.tcx.const_eval_poly(def_id) {
Ok(length) => {
2020-02-16 09:59:01 +13:00
print_const(cx, ty::Const::from_value(cx.tcx, length, cx.tcx.types.usize))
}
2019-12-22 17:42:04 -05:00
Err(_) => cx
.sess()
.source_map()
.span_to_snippet(cx.tcx.def_span(def_id))
.unwrap_or_else(|_| "_".to_string()),
};
Array(box ty.clean(cx), length)
2019-12-22 17:42:04 -05:00
}
2018-07-11 23:36:06 +08:00
TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
2018-10-02 12:31:05 +02:00
TyKind::Def(item_id, _) => {
let item = cx.tcx.hir().expect_item(item_id.id);
2019-09-26 17:51:36 +01:00
if let hir::ItemKind::OpaqueTy(ref ty) = item.kind {
2018-10-02 12:31:05 +02:00
ImplTrait(ty.bounds.clean(cx))
} else {
unreachable!()
}
}
2018-07-11 23:36:06 +08:00
TyKind::Path(hir::QPath::Resolved(None, ref path)) => {
if let Res::Def(DefKind::TyParam, did) = path.res {
if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() {
return new_ty;
}
if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did.into()) {
return ImplTrait(bounds);
}
}
let mut alias = None;
if let Res::Def(DefKind::TyAlias, def_id) = path.res {
// Substitute private type aliases
if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
if !cx.renderinfo.borrow().access_levels.is_exported(def_id) {
2019-09-26 17:51:36 +01:00
alias = Some(&cx.tcx.hir().expect_item(hir_id).kind);
}
2016-09-01 10:21:12 +03:00
}
};
if let Some(&hir::ItemKind::TyAlias(ref ty, ref generics)) = alias {
2018-07-29 15:39:51 +02:00
let provided_params = &path.segments.last().expect("segments were empty");
let mut ty_substs = FxHashMap::default();
let mut lt_substs = FxHashMap::default();
let mut ct_substs = FxHashMap::default();
let generic_args = provided_params.generic_args();
{
2018-08-07 17:44:30 +01:00
let mut indices: GenericParamCount = Default::default();
for param in generics.params.iter() {
2018-05-26 00:27:54 +01:00
match param.kind {
hir::GenericParamKind::Lifetime { .. } => {
let mut j = 0;
2019-12-22 17:42:04 -05:00
let lifetime =
generic_args.args.iter().find_map(|arg| match arg {
hir::GenericArg::Lifetime(lt) => {
if indices.lifetimes == j {
return Some(lt);
}
j += 1;
None
}
_ => None,
2019-12-22 17:42:04 -05:00
});
if let Some(lt) = lifetime.cloned() {
if !lt.is_elided() {
2019-12-22 17:42:04 -05:00
let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
lt_substs.insert(lt_def_id, lt.clean(cx));
}
}
indices.lifetimes += 1;
}
2018-05-26 00:27:54 +01:00
hir::GenericParamKind::Type { ref default, .. } => {
2019-12-22 17:42:04 -05:00
let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
let mut j = 0;
2019-12-22 17:42:04 -05:00
let type_ =
generic_args.args.iter().find_map(|arg| match arg {
hir::GenericArg::Type(ty) => {
if indices.types == j {
return Some(ty);
}
j += 1;
None
}
_ => None,
2019-12-22 17:42:04 -05:00
});
2019-06-12 11:43:15 +03:00
if let Some(ty) = type_ {
ty_substs.insert(ty_param_def_id, ty.clean(cx));
} else if let Some(default) = *default {
2019-12-22 17:42:04 -05:00
ty_substs.insert(ty_param_def_id, default.clean(cx));
}
indices.types += 1;
}
hir::GenericParamKind::Const { .. } => {
let const_param_def_id =
cx.tcx.hir().local_def_id(param.hir_id);
let mut j = 0;
2019-12-22 17:42:04 -05:00
let const_ =
generic_args.args.iter().find_map(|arg| match arg {
hir::GenericArg::Const(ct) => {
if indices.consts == j {
return Some(ct);
}
j += 1;
None
}
_ => None,
2019-12-22 17:42:04 -05:00
});
2019-06-12 11:43:15 +03:00
if let Some(ct) = const_ {
ct_substs.insert(const_param_def_id, ct.clean(cx));
}
// FIXME(const_generics:defaults)
indices.consts += 1;
}
}
}
}
return cx.enter_alias(ty_substs, lt_substs, ct_substs, || ty.clean(cx));
}
resolve_type(cx, path.clean(cx), self.hir_id)
2014-11-20 19:44:49 -05:00
}
2018-07-11 23:36:06 +08:00
TyKind::Path(hir::QPath::Resolved(Some(ref qself), ref p)) => {
2019-06-12 11:43:15 +03:00
let segments = if p.is_global() { &p.segments[1..] } else { &p.segments };
let trait_segments = &segments[..segments.len() - 1];
let trait_path = self::Path {
global: p.is_global(),
res: Res::Def(
DefKind::Trait,
cx.tcx.associated_item(p.res.def_id()).container.id(),
),
2019-06-12 11:43:15 +03:00
segments: trait_segments.clean(cx),
};
Type::QPath {
2018-07-29 15:39:51 +02:00
name: p.segments.last().expect("segments were empty").ident.name.clean(cx),
self_type: box qself.clean(cx),
2019-12-22 17:42:04 -05:00
trait_: box resolve_type(cx, trait_path, self.hir_id),
}
}
2018-07-11 23:36:06 +08:00
TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
let mut res = Res::Err;
let ty = hir_ty_to_ty(cx.tcx, self);
2019-09-16 19:08:35 +01:00
if let ty::Projection(proj) = ty.kind {
res = Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id);
}
2019-12-01 16:08:58 +01:00
let trait_path = hir::Path { span: self.span, res, segments: &[] };
Type::QPath {
2018-06-10 17:40:45 +03:00
name: segment.ident.name.clean(cx),
self_type: box qself.clean(cx),
2019-12-22 17:42:04 -05:00
trait_: box resolve_type(cx, trait_path.clean(cx), self.hir_id),
}
}
2018-07-11 23:36:06 +08:00
TyKind::TraitObject(ref bounds, ref lifetime) => {
match bounds[0].clean(cx).trait_ {
ResolvedPath { path, param_names: None, did, is_generic } => {
2019-12-22 17:42:04 -05:00
let mut bounds: Vec<self::GenericBound> = bounds[1..]
.iter()
.map(|bound| {
self::GenericBound::TraitBound(
bound.clean(cx),
hir::TraitBoundModifier::None,
)
})
.collect();
if !lifetime.is_elided() {
2018-06-14 12:23:46 +01:00
bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
}
2019-12-22 17:42:04 -05:00
ResolvedPath { path, param_names: Some(bounds), did, is_generic }
2014-11-20 19:44:49 -05:00
}
_ => Infer, // shouldn't happen
2014-11-20 19:44:49 -05:00
}
}
2018-07-11 23:36:06 +08:00
TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
TyKind::Infer | TyKind::Err => Infer,
2019-09-26 17:25:31 +01:00
TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind),
}
2013-08-15 16:28:54 -04:00
}
}
2017-09-14 21:44:23 -04:00
impl<'tcx> Clean<Type> for Ty<'tcx> {
fn clean(&self, cx: &DocContext<'_>) -> Type {
debug!("cleaning type: {:?}", self);
2019-09-16 19:08:35 +01:00
match self.kind {
ty::Never => Never,
ty::Bool => Primitive(PrimitiveType::Bool),
ty::Char => Primitive(PrimitiveType::Char),
ty::Int(int_ty) => Primitive(int_ty.into()),
ty::Uint(uint_ty) => Primitive(uint_ty.into()),
ty::Float(float_ty) => Primitive(float_ty.into()),
ty::Str => Primitive(PrimitiveType::Str),
ty::Slice(ty) => Slice(box ty.clean(cx)),
ty::Array(ty, n) => {
let mut n = cx.tcx.lift(&n).expect("array lift failed");
n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
2018-01-29 10:32:11 +01:00
let n = print_const(cx, n);
Array(box ty.clean(cx), n)
}
2019-12-21 15:29:46 +01:00
ty::RawPtr(mt) => RawPointer(mt.mutbl, box mt.ty.clean(cx)),
2019-12-22 17:42:04 -05:00
ty::Ref(r, ty, mutbl) => {
BorrowedRef { lifetime: r.clean(cx), mutability: mutbl, type_: box ty.clean(cx) }
}
ty::FnDef(..) | ty::FnPtr(_) => {
let ty = cx.tcx.lift(self).expect("FnPtr lift failed");
let sig = ty.fn_sig(cx.tcx);
let local_def_id = cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID);
BareFunction(box BareFunctionDecl {
unsafety: sig.unsafety(),
generic_params: Vec::new(),
decl: (local_def_id, sig).clean(cx),
abi: sig.abi(),
})
}
ty::Adt(def, substs) => {
let did = def.did;
let kind = match def.adt_kind() {
AdtKind::Struct => TypeKind::Struct,
AdtKind::Union => TypeKind::Union,
AdtKind::Enum => TypeKind::Enum,
};
inline::record_extern_fqn(cx, did, kind);
2019-09-05 11:43:05 +10:00
let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs);
2019-12-22 17:42:04 -05:00
ResolvedPath { path, param_names: None, did, is_generic: false }
}
ty::Foreign(did) => {
2017-09-03 19:53:58 +01:00
inline::record_extern_fqn(cx, did, TypeKind::Foreign);
2019-12-22 17:42:04 -05:00
let path = external_path(
cx,
cx.tcx.item_name(did),
None,
false,
vec![],
InternalSubsts::empty(),
);
ResolvedPath { path, param_names: None, did, is_generic: false }
2017-09-03 19:53:58 +01:00
}
ty::Dynamic(ref obj, ref reg) => {
2018-12-15 17:35:55 +02:00
// HACK: pick the first `did` as the `did` of the trait object. Someone
// might want to implement "native" support for marker-trait-only
// trait objects.
let mut dids = obj.principal_def_id().into_iter().chain(obj.auto_traits());
2019-12-22 17:42:04 -05:00
let did = dids
.next()
.unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", self));
2018-12-15 17:35:55 +02:00
let substs = match obj.principal() {
Some(principal) => principal.skip_binder().substs,
// marker traits have no substs.
2019-12-22 17:42:04 -05:00
_ => cx.tcx.intern_substs(&[]),
2018-12-15 17:35:55 +02:00
};
inline::record_extern_fqn(cx, did, TypeKind::Trait);
let mut param_names = vec![];
reg.clean(cx).map(|b| param_names.push(GenericBound::Outlives(b)));
2018-12-15 17:35:55 +02:00
for did in dids {
let empty = cx.tcx.intern_substs(&[]);
2019-12-22 17:42:04 -05:00
let path =
external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
inline::record_extern_fqn(cx, did, TypeKind::Trait);
2019-12-22 17:42:04 -05:00
let bound = GenericBound::TraitBound(
PolyTrait {
trait_: ResolvedPath {
path,
param_names: None,
did,
is_generic: false,
},
generic_params: Vec::new(),
},
2019-12-22 17:42:04 -05:00
hir::TraitBoundModifier::None,
);
param_names.push(bound);
}
let mut bindings = vec![];
for pb in obj.projection_bounds() {
bindings.push(TypeBinding {
name: cx.tcx.associated_item(pb.item_def_id()).ident.name.clean(cx),
2019-12-22 17:42:04 -05:00
kind: TypeBindingKind::Equality { ty: pb.skip_binder().ty.clean(cx) },
});
}
2019-12-22 17:42:04 -05:00
let path =
external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs);
ResolvedPath { path, param_names: Some(param_names), did, is_generic: false }
}
2019-04-26 00:27:33 +01:00
ty::Tuple(ref t) => {
Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx))
}
ty::Projection(ref data) => data.clean(cx),
ty::Param(ref p) => {
if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&p.index.into()) {
ImplTrait(bounds)
} else {
Generic(p.name.to_string())
}
}
ty::Opaque(def_id, substs) => {
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
// by looking up the projections associated with the def_id.
let predicates_of = cx.tcx.explicit_predicates_of(def_id);
let substs = cx.tcx.lift(&substs).expect("Opaque lift failed");
let bounds = predicates_of.instantiate(cx.tcx, substs);
let mut regions = vec![];
let mut has_sized = false;
2019-12-22 17:42:04 -05:00
let mut bounds = bounds
.predicates
.iter()
.filter_map(|predicate| {
let trait_ref = if let Some(tr) = predicate.to_opt_poly_trait_ref() {
tr
} else if let ty::Predicate::TypeOutlives(pred) = *predicate {
// these should turn up at the end
pred.skip_binder()
.1
.clean(cx)
.map(|r| regions.push(GenericBound::Outlives(r)));
return None;
2019-12-22 17:42:04 -05:00
} else {
return None;
};
2019-12-22 17:42:04 -05:00
if let Some(sized) = cx.tcx.lang_items().sized_trait() {
if trait_ref.def_id() == sized {
has_sized = true;
return None;
}
}
2019-12-22 17:42:04 -05:00
let bounds = bounds
.predicates
.iter()
.filter_map(|pred| {
if let ty::Predicate::Projection(proj) = *pred {
let proj = proj.skip_binder();
if proj.projection_ty.trait_ref(cx.tcx)
== *trait_ref.skip_binder()
{
Some(TypeBinding {
name: cx
.tcx
.associated_item(proj.projection_ty.item_def_id)
.ident
.name
.clean(cx),
kind: TypeBindingKind::Equality {
ty: proj.ty.clean(cx),
},
})
} else {
None
}
} else {
None
}
})
.collect();
Some((trait_ref.skip_binder(), bounds).clean(cx))
})
.collect::<Vec<_>>();
bounds.extend(regions);
if !has_sized && !bounds.is_empty() {
bounds.insert(0, GenericBound::maybe_sized(cx));
}
ImplTrait(bounds)
}
ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
2018-10-22 20:37:56 +02:00
ty::Bound(..) => panic!("Bound"),
ty::Placeholder(..) => panic!("Placeholder"),
ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
ty::Infer(..) => panic!("Infer"),
ty::Error => panic!("Error"),
}
}
}
impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
fn clean(&self, cx: &DocContext<'_>) -> Constant {
Constant {
type_: self.ty.clean(cx),
expr: format!("{}", self),
value: None,
is_literal: false,
}
}
}
2019-11-29 09:40:33 +01:00
impl Clean<Item> for hir::StructField<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
let local_did = cx.tcx.hir().local_def_id(self.hir_id);
2019-02-27 15:56:59 +01:00
2013-08-15 16:28:54 -04:00
Item {
2018-05-26 02:50:15 +03:00
name: Some(self.ident.name).clean(cx),
attrs: self.attrs.clean(cx),
source: self.span.clean(cx),
visibility: self.vis.clean(cx),
2019-02-27 15:56:59 +01:00
stability: get_stability(cx, local_did),
deprecation: get_deprecation(cx, local_did),
def_id: local_did,
inner: StructFieldItem(self.ty.clean(cx)),
2013-08-15 16:28:54 -04:00
}
}
}
2019-06-11 12:50:17 +03:00
impl Clean<Item> for ty::FieldDef {
fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
2018-05-26 02:50:15 +03:00
name: Some(self.ident.name).clean(cx),
attrs: cx.tcx.get_attrs(self.did).clean(cx),
source: cx.tcx.def_span(self.did).clean(cx),
visibility: self.vis.clean(cx),
stability: get_stability(cx, self.did),
2015-12-12 23:01:27 +03:00
deprecation: get_deprecation(cx, self.did),
def_id: self.did,
inner: StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
}
}
}
2019-12-01 16:08:58 +01:00
impl Clean<Visibility> for hir::Visibility<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Visibility {
match self.node {
hir::VisibilityKind::Public => Visibility::Public,
hir::VisibilityKind::Inherited => Visibility::Inherited,
hir::VisibilityKind::Crate(_) => Visibility::Crate,
hir::VisibilityKind::Restricted { ref path, .. } => {
let path = path.clean(cx);
let did = register_res(cx, path.res);
Visibility::Restricted(did, path)
}
}
}
}
impl Clean<Visibility> for ty::Visibility {
fn clean(&self, _: &DocContext<'_>) -> Visibility {
if *self == ty::Visibility::Public { Public } else { Inherited }
2013-08-15 16:28:54 -04:00
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Item> for doctree::Struct<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
2013-08-15 16:28:54 -04:00
inner: StructItem(Struct {
struct_type: self.struct_type,
generics: self.generics.clean(cx),
fields: self.fields.clean(cx),
fields_stripped: false,
2013-08-15 16:28:54 -04:00
}),
}
2013-08-15 16:28:54 -04:00
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Item> for doctree::Union<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
2016-08-10 21:00:17 +03:00
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id),
2016-08-10 21:00:17 +03:00
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
2016-08-10 21:00:17 +03:00
inner: UnionItem(Union {
struct_type: self.struct_type,
generics: self.generics.clean(cx),
fields: self.fields.clean(cx),
fields_stripped: false,
}),
}
2016-08-10 21:00:17 +03:00
}
}
impl Clean<VariantStruct> for rustc_hir::VariantData<'_> {
fn clean(&self, cx: &DocContext<'_>) -> VariantStruct {
2013-08-15 16:28:54 -04:00
VariantStruct {
struct_type: doctree::struct_type_from_def(self),
fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
fields_stripped: false,
2013-08-15 16:28:54 -04:00
}
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Item> for doctree::Enum<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
2013-08-15 16:28:54 -04:00
inner: EnumItem(Enum {
variants: self.variants.iter().map(|v| v.clean(cx)).collect(),
generics: self.generics.clean(cx),
variants_stripped: false,
2013-08-15 16:28:54 -04:00
}),
}
2013-08-15 16:28:54 -04:00
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Item> for doctree::Variant<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
2013-08-15 16:28:54 -04:00
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
visibility: Inherited,
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id),
2019-12-22 17:42:04 -05:00
inner: VariantItem(Variant { kind: self.def.clean(cx) }),
2013-08-15 16:28:54 -04:00
}
}
}
2019-06-11 12:50:17 +03:00
impl Clean<Item> for ty::VariantDef {
fn clean(&self, cx: &DocContext<'_>) -> Item {
let kind = match self.ctor_kind {
CtorKind::Const => VariantKind::CLike,
2019-12-22 17:42:04 -05:00
CtorKind::Fn => VariantKind::Tuple(
self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect(),
),
CtorKind::Fictive => VariantKind::Struct(VariantStruct {
struct_type: doctree::Plain,
fields_stripped: false,
fields: self
.fields
.iter()
.map(|field| Item {
source: cx.tcx.def_span(field.did).clean(cx),
name: Some(field.ident.name.clean(cx)),
attrs: cx.tcx.get_attrs(field.did).clean(cx),
visibility: field.vis.clean(cx),
def_id: field.did,
stability: get_stability(cx, field.did),
deprecation: get_deprecation(cx, field.did),
inner: StructFieldItem(cx.tcx.type_of(field.did).clean(cx)),
})
.collect(),
}),
2014-05-23 16:14:54 -07:00
};
Item {
name: Some(self.ident.clean(cx)),
attrs: inline::load_attrs(cx, self.def_id).clean(cx),
2019-03-24 12:09:44 +03:00
source: cx.tcx.def_span(self.def_id).clean(cx),
visibility: Inherited,
2019-03-24 12:09:44 +03:00
def_id: self.def_id,
2018-11-06 15:05:44 -05:00
inner: VariantItem(Variant { kind }),
2019-03-24 12:09:44 +03:00
stability: get_stability(cx, self.def_id),
deprecation: get_deprecation(cx, self.def_id),
2014-05-23 16:14:54 -07:00
}
}
}
2019-11-29 09:26:18 +01:00
impl Clean<VariantKind> for hir::VariantData<'_> {
fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
match self {
hir::VariantData::Struct(..) => VariantKind::Struct(self.clean(cx)),
2019-12-22 17:42:04 -05:00
hir::VariantData::Tuple(..) => {
VariantKind::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
}
hir::VariantData::Unit(..) => VariantKind::CLike,
}
}
}
impl Clean<Span> for rustc_span::Span {
fn clean(&self, cx: &DocContext<'_>) -> Span {
2018-06-25 01:00:21 +03:00
if self.is_dummy() {
return Span::empty();
}
2020-02-22 16:07:05 +02:00
let sm = cx.sess().source_map();
let filename = sm.span_to_filename(*self);
let lo = sm.lookup_char_pos(self.lo());
let hi = sm.lookup_char_pos(self.hi());
Span {
filename,
loline: lo.line,
locol: lo.col.to_usize(),
hiline: hi.line,
hicol: hi.col.to_usize(),
2019-05-16 18:31:53 +02:00
original: *self,
}
2013-08-15 16:28:54 -04:00
}
}
2019-12-01 16:08:58 +01:00
impl Clean<Path> for hir::Path<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Path {
2013-08-15 16:28:54 -04:00
Path {
global: self.is_global(),
res: self.res,
segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
}
}
}
2019-12-01 16:08:58 +01:00
impl Clean<GenericArgs> for hir::GenericArgs<'_> {
fn clean(&self, cx: &DocContext<'_>) -> GenericArgs {
if self.parenthesized {
2019-05-08 15:57:06 -04:00
let output = self.bindings[0].ty().clean(cx);
GenericArgs::Parenthesized {
inputs: self.inputs().clean(cx),
2019-12-22 17:42:04 -05:00
output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None },
}
} else {
let elide_lifetimes = self.args.iter().all(|arg| match arg {
hir::GenericArg::Lifetime(lt) => lt.is_elided(),
_ => true,
});
GenericArgs::AngleBracketed {
2019-12-22 17:42:04 -05:00
args: self
.args
.iter()
.filter_map(|arg| match arg {
hir::GenericArg::Lifetime(lt) if !elide_lifetimes => {
Some(GenericArg::Lifetime(lt.clean(cx)))
}
hir::GenericArg::Lifetime(_) => None,
hir::GenericArg::Type(ty) => Some(GenericArg::Type(ty.clean(cx))),
hir::GenericArg::Const(ct) => Some(GenericArg::Const(ct.clean(cx))),
})
.collect(),
bindings: self.bindings.clean(cx),
}
}
}
}
2019-12-01 16:08:58 +01:00
impl Clean<PathSegment> for hir::PathSegment<'_> {
fn clean(&self, cx: &DocContext<'_>) -> PathSegment {
2019-12-22 17:42:04 -05:00
PathSegment { name: self.ident.name.clean(cx), args: self.generic_args().clean(cx) }
2013-08-15 16:28:54 -04:00
}
}
impl Clean<String> for Ident {
#[inline]
fn clean(&self, cx: &DocContext<'_>) -> String {
self.name.clean(cx)
}
}
impl Clean<String> for ast::Name {
#[inline]
fn clean(&self, _: &DocContext<'_>) -> String {
self.to_string()
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Item> for doctree::Typedef<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
2020-01-10 02:07:13 +01:00
let type_ = self.ty.clean(cx);
let item_type = type_.def_id().and_then(|did| inline::build_ty(cx, did));
2013-08-15 16:28:54 -04:00
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
2020-01-10 14:46:28 +01:00
inner: TypedefItem(Typedef { type_, generics: self.gen.clean(cx), item_type }, false),
2013-08-15 16:28:54 -04:00
}
}
}
2019-08-01 00:41:54 +01:00
impl Clean<Item> for doctree::OpaqueTy<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
2018-07-03 19:38:14 +02:00
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id),
2018-07-03 19:38:14 +02:00
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
2019-12-22 17:42:04 -05:00
inner: OpaqueTyItem(
OpaqueTy {
bounds: self.opaque_ty.bounds.clean(cx),
generics: self.opaque_ty.generics.clean(cx),
},
false,
),
2018-07-03 19:38:14 +02:00
}
}
}
2019-12-01 16:08:58 +01:00
impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl {
2018-05-03 22:24:50 +09:00
let (generic_params, decl) = enter_impl_trait(cx, || {
(self.generic_params.clean(cx), (&*self.decl, &self.param_names[..]).clean(cx))
2018-05-03 22:24:50 +09:00
});
2019-12-22 17:42:04 -05:00
BareFunctionDecl { unsafety: self.unsafety, abi: self.abi, decl, generic_params }
2013-08-15 16:28:54 -04:00
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Item> for doctree::Static<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
2013-08-15 16:28:54 -04:00
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
2013-08-15 16:28:54 -04:00
inner: StaticItem(Static {
type_: self.type_.clean(cx),
2019-12-21 15:29:46 +01:00
mutability: self.mutability,
expr: print_const_expr(cx, self.expr),
2013-08-15 16:28:54 -04:00
}),
}
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Item> for doctree::Constant<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
let def_id = cx.tcx.hir().local_def_id(self.id);
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
def_id,
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
inner: ConstantItem(Constant {
type_: self.type_.clean(cx),
expr: print_const_expr(cx, self.expr),
value: print_evaluated_const(cx, def_id),
is_literal: is_literal_expr(cx, self.expr.hir_id),
}),
}
}
}
impl Clean<ImplPolarity> for ty::ImplPolarity {
fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
match self {
&ty::ImplPolarity::Positive |
// FIXME: do we want to do something else here?
&ty::ImplPolarity::Reservation => ImplPolarity::Positive,
&ty::ImplPolarity::Negative => ImplPolarity::Negative,
}
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Vec<Item>> for doctree::Impl<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
let mut ret = Vec::new();
let trait_ = self.trait_.clean(cx);
2019-06-12 11:43:15 +03:00
let items = self.items.iter().map(|ii| ii.clean(cx)).collect::<Vec<_>>();
let def_id = cx.tcx.hir().local_def_id(self.id);
// If this impl block is an implementation of the Deref trait, then we
// need to try inlining the target's inherent impl blocks as well.
if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
build_deref_target_impls(cx, &items, &mut ret);
}
2020-01-15 18:52:04 +01:00
let provided: FxHashSet<String> = trait_
2019-12-22 17:42:04 -05:00
.def_id()
.map(|did| {
cx.tcx.provided_trait_methods(did).map(|meth| meth.ident.to_string()).collect()
2019-12-22 17:42:04 -05:00
})
.unwrap_or_default();
2020-01-15 18:52:04 +01:00
let for_ = self.for_.clean(cx);
let type_alias = for_.def_id().and_then(|did| match cx.tcx.def_kind(did) {
Some(DefKind::TyAlias) => Some(cx.tcx.type_of(did).clean(cx)),
_ => None,
});
2020-01-17 19:51:07 +01:00
let make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| Item {
name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
def_id,
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
inner: ImplItem(Impl {
unsafety: self.unsafety,
generics: self.generics.clean(cx),
provided_trait_methods: provided.clone(),
trait_,
for_,
items,
polarity: Some(cx.tcx.impl_polarity(def_id).clean(cx)),
synthetic: false,
blanket_impl: None,
}),
2020-01-16 21:36:39 +01:00
};
if let Some(type_alias) = type_alias {
ret.push(make_item(trait_.clone(), type_alias, items.clone()));
2020-01-15 18:52:04 +01:00
}
2020-01-16 21:36:39 +01:00
ret.push(make_item(trait_, for_, items));
2016-02-28 12:11:13 +01:00
ret
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Vec<Item>> for doctree::ExternCrate<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
2019-12-22 17:42:04 -05:00
let please_inline = self.vis.node.is_pub()
&& self.attrs.iter().any(|a| {
a.check_name(sym::doc)
&& match a.meta_item_list() {
Some(l) => attr::list_contains_name(&l, sym::inline),
None => false,
}
});
2019-01-10 20:27:44 -05:00
if please_inline {
let mut visited = FxHashSet::default();
2019-12-22 17:42:04 -05:00
let res = Res::Def(DefKind::Mod, DefId { krate: self.cnum, index: CRATE_DEF_INDEX });
2019-01-10 20:27:44 -05:00
if let Some(items) = inline::try_inline(
2019-12-22 17:42:04 -05:00
cx,
res,
self.name,
Some(rustc::ty::Attributes::Borrowed(self.attrs)),
2019-12-22 17:42:04 -05:00
&mut visited,
) {
2019-01-10 20:27:44 -05:00
return items;
}
}
vec![Item {
name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
2016-04-25 08:24:50 +02:00
def_id: DefId { krate: self.cnum, index: CRATE_DEF_INDEX },
visibility: self.vis.clean(cx),
stability: None,
2015-12-12 23:01:27 +03:00
deprecation: None,
2019-12-22 17:42:04 -05:00
inner: ExternCrateItem(self.name.clean(cx), self.path.clone()),
2019-01-10 20:27:44 -05:00
}]
}
2013-08-15 16:28:54 -04:00
}
2019-06-12 11:43:15 +03:00
impl Clean<Vec<Item>> for doctree::Import<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
2014-07-02 21:27:07 -04:00
// We consider inlining the documentation of `pub use` statements, but we
// forcefully don't inline if this is not public or if the
// #[doc(no_inline)] attribute is present.
// Don't inline doc(hidden) imports so they can be stripped at a later stage.
2019-12-22 17:42:04 -05:00
let mut denied = !self.vis.node.is_pub()
|| self.attrs.iter().any(|a| {
a.check_name(sym::doc)
&& match a.meta_item_list() {
Some(l) => {
attr::list_contains_name(&l, sym::no_inline)
|| attr::list_contains_name(&l, sym::hidden)
}
None => false,
}
});
// Also check whether imports were asked to be inlined, in case we're trying to re-export a
// crate in Rust 2018+
let please_inline = self.attrs.lists(sym::doc).has_word(sym::inline);
let path = self.path.clean(cx);
let inner = if self.glob {
2018-06-15 18:16:43 -05:00
if !denied {
let mut visited = FxHashSet::default();
if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
2018-06-15 18:16:43 -05:00
return items;
}
}
Import::Glob(resolve_use_source(cx, path))
} else {
let name = self.name;
if !please_inline {
match path.res {
Res::Def(DefKind::Mod, did) => {
if !did.is_local() && did.index == CRATE_DEF_INDEX {
// if we're `pub use`ing an extern crate root, don't inline it unless we
// were specifically asked for it
denied = true;
}
}
_ => {}
}
}
if !denied {
let mut visited = FxHashSet::default();
if let Some(items) = inline::try_inline(
2019-12-22 17:42:04 -05:00
cx,
path.res,
name,
Some(rustc::ty::Attributes::Borrowed(self.attrs)),
2019-12-22 17:42:04 -05:00
&mut visited,
) {
return items;
}
}
Import::Simple(name.clean(cx), resolve_use_source(cx, path))
};
2018-07-12 22:00:57 +02:00
vec![Item {
name: None,
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
def_id: cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID),
visibility: self.vis.clean(cx),
stability: None,
2015-12-12 23:01:27 +03:00
deprecation: None,
2019-12-22 17:42:04 -05:00
inner: ImportItem(inner),
}]
2013-08-15 16:28:54 -04:00
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Item> for doctree::ForeignItem<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
2019-06-12 11:43:15 +03:00
let inner = match self.kind {
2018-07-11 22:56:44 +08:00
hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => {
2019-06-12 11:43:15 +03:00
let abi = cx.tcx.hir().get_foreign_abi(self.id);
2019-12-22 17:42:04 -05:00
let (generics, decl) =
enter_impl_trait(cx, || (generics.clean(cx), (&**decl, &names[..]).clean(cx)));
2019-03-07 16:47:40 +01:00
let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
ForeignFunctionItem(Function {
2018-05-03 22:24:50 +09:00
decl,
generics,
header: hir::FnHeader {
unsafety: hir::Unsafety::Unsafe,
2019-06-12 11:43:15 +03:00
abi,
constness: hir::Constness::NotConst,
asyncness: hir::IsAsync::NotAsync,
},
all_types,
2019-03-07 16:47:40 +01:00
ret_types,
})
}
2019-12-22 17:42:04 -05:00
hir::ForeignItemKind::Static(ref ty, mutbl) => ForeignStaticItem(Static {
type_: ty.clean(cx),
mutability: *mutbl,
expr: String::new(),
}),
hir::ForeignItemKind::Type => ForeignTypeItem,
};
2018-07-12 22:00:57 +02:00
Item {
2019-06-12 11:43:15 +03:00
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
2019-06-12 11:43:15 +03:00
source: self.whence.clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id),
visibility: self.vis.clean(cx),
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
inner,
}
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Item> for doctree::Macro<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
let name = self.name.clean(cx);
Item {
2015-11-26 19:14:36 +01:00
name: Some(name.clone()),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
visibility: Public,
stability: cx.stability(self.hid).clean(cx),
deprecation: cx.deprecation(self.hid).clean(cx),
def_id: self.def_id,
inner: MacroItem(Macro {
2019-12-22 17:42:04 -05:00
source: format!(
"macro_rules! {} {{\n{}}}",
name,
self.matchers
.iter()
.map(|span| { format!(" {} => {{ ... }};\n", span.to_src(cx)) })
.collect::<String>()
),
imported_from: self.imported_from.clean(cx),
}),
}
}
}
2019-06-12 11:43:15 +03:00
impl Clean<Item> for doctree::ProcMacro<'_> {
fn clean(&self, cx: &DocContext<'_>) -> Item {
Item {
name: Some(self.name.clean(cx)),
attrs: self.attrs.clean(cx),
source: self.whence.clean(cx),
visibility: Public,
stability: cx.stability(self.id).clean(cx),
deprecation: cx.deprecation(self.id).clean(cx),
def_id: cx.tcx.hir().local_def_id(self.id),
2019-12-22 17:42:04 -05:00
inner: ProcMacroItem(ProcMacro { kind: self.kind, helpers: self.helpers.clean(cx) }),
}
}
}
impl Clean<Stability> for attr::Stability {
fn clean(&self, _: &DocContext<'_>) -> Stability {
Stability {
level: stability::StabilityLevel::from_attr_level(&self.level),
feature: Some(self.feature.to_string()).filter(|f| !f.is_empty()),
since: match self.level {
2019-12-22 17:42:04 -05:00
attr::Stable { ref since } => since.to_string(),
_ => String::new(),
},
2019-12-22 17:42:04 -05:00
deprecation: self.rustc_depr.as_ref().map(|d| Deprecation {
note: Some(d.reason.to_string()).filter(|r| !r.is_empty()),
since: Some(d.since.to_string()).filter(|d| !d.is_empty()),
}),
unstable_reason: match self.level {
attr::Unstable { reason: Some(ref reason), .. } => Some(reason.to_string()),
_ => None,
},
issue: match self.level {
2019-12-22 17:42:04 -05:00
attr::Unstable { issue, .. } => issue,
_ => None,
2019-12-22 17:42:04 -05:00
},
}
}
}
2015-12-12 23:01:27 +03:00
impl Clean<Deprecation> for attr::Deprecation {
fn clean(&self, _: &DocContext<'_>) -> Deprecation {
2015-12-12 23:01:27 +03:00
Deprecation {
since: self.since.map(|s| s.to_string()).filter(|s| !s.is_empty()),
note: self.note.map(|n| n.to_string()).filter(|n| !n.is_empty()),
2015-12-12 23:01:27 +03:00
}
}
}
2019-12-01 16:08:58 +01:00
impl Clean<TypeBinding> for hir::TypeBinding<'_> {
fn clean(&self, cx: &DocContext<'_>) -> TypeBinding {
2019-12-22 17:42:04 -05:00
TypeBinding { name: self.ident.name.clean(cx), kind: self.kind.clean(cx) }
2019-05-08 15:57:06 -04:00
}
}
2019-12-01 16:08:58 +01:00
impl Clean<TypeBindingKind> for hir::TypeBindingKind<'_> {
2019-05-08 15:57:06 -04:00
fn clean(&self, cx: &DocContext<'_>) -> TypeBindingKind {
match *self {
2019-12-22 17:42:04 -05:00
hir::TypeBindingKind::Equality { ref ty } => {
TypeBindingKind::Equality { ty: ty.clean(cx) }
}
hir::TypeBindingKind::Constraint { ref bounds } => {
TypeBindingKind::Constraint { bounds: bounds.iter().map(|b| b.clean(cx)).collect() }
}
}
}
}
Generate documentation for auto-trait impls A new section is added to both both struct and trait doc pages. On struct/enum pages, a new 'Auto Trait Implementations' section displays any synthetic implementations for auto traits. Currently, this is only done for Send and Sync. On trait pages, a new 'Auto Implementors' section displays all types which automatically implement the trait. Effectively, this is a list of all public types in the standard library. Synthesized impls for a particular auto trait ('synthetic impls') take into account generic bounds. For example, a type 'struct Foo<T>(T)' will have 'impl<T> Send for Foo<T> where T: Send' generated for it. Manual implementations of auto traits are also taken into account. If we have the following types: 'struct Foo<T>(T)' 'struct Wrapper<T>(Foo<T>)' 'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes this sound somehow Then Wrapper will have the following impl generated: 'impl<T> Send for Wrapper<T>' reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send' to hold Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are taken into account by synthetic impls However, if a type can *never* implement a particular auto trait (e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be generated (in this case, 'impl<T> !Send for MyStruct<T>') All of this means that a user should be able to copy-paste a synthetic impl into their code, without any observable changes in behavior (assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
enum SimpleBound {
TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
Outlives(Lifetime),
Generate documentation for auto-trait impls A new section is added to both both struct and trait doc pages. On struct/enum pages, a new 'Auto Trait Implementations' section displays any synthetic implementations for auto traits. Currently, this is only done for Send and Sync. On trait pages, a new 'Auto Implementors' section displays all types which automatically implement the trait. Effectively, this is a list of all public types in the standard library. Synthesized impls for a particular auto trait ('synthetic impls') take into account generic bounds. For example, a type 'struct Foo<T>(T)' will have 'impl<T> Send for Foo<T> where T: Send' generated for it. Manual implementations of auto traits are also taken into account. If we have the following types: 'struct Foo<T>(T)' 'struct Wrapper<T>(Foo<T>)' 'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes this sound somehow Then Wrapper will have the following impl generated: 'impl<T> Send for Wrapper<T>' reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send' to hold Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are taken into account by synthetic impls However, if a type can *never* implement a particular auto trait (e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be generated (in this case, 'impl<T> !Send for MyStruct<T>') All of this means that a user should be able to copy-paste a synthetic impl into their code, without any observable changes in behavior (assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
}
impl From<GenericBound> for SimpleBound {
fn from(bound: GenericBound) -> Self {
Generate documentation for auto-trait impls A new section is added to both both struct and trait doc pages. On struct/enum pages, a new 'Auto Trait Implementations' section displays any synthetic implementations for auto traits. Currently, this is only done for Send and Sync. On trait pages, a new 'Auto Implementors' section displays all types which automatically implement the trait. Effectively, this is a list of all public types in the standard library. Synthesized impls for a particular auto trait ('synthetic impls') take into account generic bounds. For example, a type 'struct Foo<T>(T)' will have 'impl<T> Send for Foo<T> where T: Send' generated for it. Manual implementations of auto traits are also taken into account. If we have the following types: 'struct Foo<T>(T)' 'struct Wrapper<T>(Foo<T>)' 'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes this sound somehow Then Wrapper will have the following impl generated: 'impl<T> Send for Wrapper<T>' reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send' to hold Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are taken into account by synthetic impls However, if a type can *never* implement a particular auto trait (e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be generated (in this case, 'impl<T> !Send for MyStruct<T>') All of this means that a user should be able to copy-paste a synthetic impl into their code, without any observable changes in behavior (assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
match bound.clone() {
GenericBound::Outlives(l) => SimpleBound::Outlives(l),
GenericBound::TraitBound(t, mod_) => match t.trait_ {
2019-12-22 17:42:04 -05:00
Type::ResolvedPath { path, param_names, .. } => SimpleBound::TraitBound(
path.segments,
param_names.map_or_else(
|| Vec::new(),
|v| v.iter().map(|p| SimpleBound::from(p.clone())).collect(),
),
t.generic_params,
mod_,
),
2018-02-10 14:34:46 -05:00
_ => panic!("Unexpected bound {:?}", bound),
2019-12-22 17:42:04 -05:00
},
Generate documentation for auto-trait impls A new section is added to both both struct and trait doc pages. On struct/enum pages, a new 'Auto Trait Implementations' section displays any synthetic implementations for auto traits. Currently, this is only done for Send and Sync. On trait pages, a new 'Auto Implementors' section displays all types which automatically implement the trait. Effectively, this is a list of all public types in the standard library. Synthesized impls for a particular auto trait ('synthetic impls') take into account generic bounds. For example, a type 'struct Foo<T>(T)' will have 'impl<T> Send for Foo<T> where T: Send' generated for it. Manual implementations of auto traits are also taken into account. If we have the following types: 'struct Foo<T>(T)' 'struct Wrapper<T>(Foo<T>)' 'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes this sound somehow Then Wrapper will have the following impl generated: 'impl<T> Send for Wrapper<T>' reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send' to hold Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are taken into account by synthetic impls However, if a type can *never* implement a particular auto trait (e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be generated (in this case, 'impl<T> !Send for MyStruct<T>') All of this means that a user should be able to copy-paste a synthetic impl into their code, without any observable changes in behavior (assuming the rest of the program remains unchanged).
2017-11-22 16:16:55 -05:00
}
}
}