2013-08-15 16:28:54 -04:00
|
|
|
//! This module contains the "cleaned" pieces of the AST, and the functions
|
|
|
|
//! that clean them.
|
|
|
|
|
2018-11-27 02:59:49 +00:00
|
|
|
mod auto_trait;
|
|
|
|
mod blanket_impl;
|
2019-12-22 17:42:04 -05:00
|
|
|
pub mod cfg;
|
|
|
|
pub mod inline;
|
2019-12-03 22:03:38 +01:00
|
|
|
mod simplify;
|
|
|
|
pub mod types;
|
2019-12-22 17:42:04 -05:00
|
|
|
pub mod utils;
|
2014-11-06 00:05:53 -08:00
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
use rustc::middle::lang_items;
|
|
|
|
use rustc::middle::resolve_lifetime as rl;
|
|
|
|
use rustc::middle::stability;
|
2018-11-27 02:59:49 +00:00
|
|
|
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};
|
2020-01-11 13:15:20 +01:00
|
|
|
use rustc_attr as attr;
|
2019-12-24 05:02:53 +01:00
|
|
|
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
|
2020-01-05 02:37:57 +01:00
|
|
|
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};
|
2020-01-01 18:06:00 +01:00
|
|
|
use rustc_mir::const_eval::is_min_const_fn;
|
2019-12-31 20:15:40 +03:00
|
|
|
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;
|
2019-12-03 22:03:38 +01:00
|
|
|
use syntax::ast::{self, Ident};
|
2018-06-04 23:44:35 +02: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
|
|
|
use std::collections::hash_map::Entry;
|
2017-10-16 21:07:26 +02:00
|
|
|
use std::default::Default;
|
2019-12-22 17:42:04 -05:00
|
|
|
use std::hash::Hash;
|
2014-05-23 00:42:33 -07:00
|
|
|
use std::rc::Rc;
|
2014-05-28 19:53:37 -07:00
|
|
|
use std::u32;
|
2019-12-22 17:42:04 -05:00
|
|
|
use std::{mem, vec};
|
2013-10-02 15:39:32 -07:00
|
|
|
|
2019-06-21 12:23:05 +09: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::*;
|
2019-12-03 22:03:38 +01:00
|
|
|
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: &'static str = "Output";
|
2017-08-05 14:38:52 +08:00
|
|
|
|
2013-08-15 16:28:54 -04:00
|
|
|
pub trait Clean<T> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> T;
|
2013-08-15 16:28:54 -04:00
|
|
|
}
|
|
|
|
|
2015-03-10 12:28:44 +02:00
|
|
|
impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Vec<U> {
|
2014-09-06 19:13:40 +03:00
|
|
|
self.iter().map(|x| x.clean(cx)).collect()
|
2014-02-28 17:46:09 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-11-01 19:03:38 +01:00
|
|
|
impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> IndexVec<V, U> {
|
2018-11-01 19:03:38 +01:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-23 00:42:33 -07:00
|
|
|
impl<T: Clean<U>, U> Clean<U> for Rc<T> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> U {
|
2014-09-06 19:13:40 +03:00
|
|
|
(**self).clean(cx)
|
2014-05-23 00:42:33 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-08-15 16:28:54 -04:00
|
|
|
impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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>,
|
|
|
|
{
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> U {
|
2018-04-24 21:45:49 -05:00
|
|
|
self.skip_binder().clean(cx)
|
2015-01-10 23:50:46 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-11-22 21:02:04 +02:00
|
|
|
impl Clean<ExternalCrate> for CrateNum {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> ExternalCrate {
|
2016-11-29 08:15:16 +02:00
|
|
|
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);
|
2016-11-29 08:15:16 +02:00
|
|
|
|
|
|
|
// 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.
|
2019-04-20 19:36:05 +03:00
|
|
|
let as_primitive = |res: Res| {
|
|
|
|
if let Res::Def(DefKind::Mod, def_id) = res {
|
2016-11-29 08:15:16 +02:00
|
|
|
let attrs = cx.tcx.get_attrs(def_id).clean(cx);
|
|
|
|
let mut prim = None;
|
2019-05-08 13:21:18 +10:00
|
|
|
for attr in attrs.lists(sym::doc) {
|
2016-11-29 08:15:16 +02:00
|
|
|
if let Some(v) = attr.value_str() {
|
2019-05-08 13:21:18 +10:00
|
|
|
if attr.check_name(sym::primitive) {
|
2016-11-29 08:15:16 +02:00
|
|
|
prim = PrimitiveType::from_str(&v.as_str());
|
|
|
|
if prim.is_some() {
|
|
|
|
break;
|
|
|
|
}
|
2017-10-17 23:03:50 -07:00
|
|
|
// FIXME: should warn on unknown primitives?
|
2016-11-29 08:15:16 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
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()
|
|
|
|
.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,
|
2016-11-29 08:15:16 +02:00
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
})
|
|
|
|
.collect()
|
2016-11-29 08:15:16 +02:00
|
|
|
} else {
|
2019-12-22 17:42:04 -05:00
|
|
|
cx.tcx
|
|
|
|
.item_children(root)
|
|
|
|
.iter()
|
|
|
|
.map(|item| item.res)
|
|
|
|
.filter_map(as_primitive)
|
|
|
|
.collect()
|
2016-11-29 08:15:16 +02:00
|
|
|
};
|
|
|
|
|
2019-04-20 19:36:05 +03:00
|
|
|
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;
|
2019-05-08 13:21:18 +10:00
|
|
|
for attr in attrs.lists(sym::doc) {
|
2018-05-28 21:30:01 +02:00
|
|
|
if let Some(v) = attr.value_str() {
|
2019-05-08 13:21:18 +10:00
|
|
|
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()
|
|
|
|
.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
|
|
|
};
|
|
|
|
|
2013-10-02 15:39:32 -07:00
|
|
|
ExternalCrate {
|
2016-11-29 08:15:16 +02:00
|
|
|
name: cx.tcx.crate_name(*self).to_string(),
|
2017-12-14 08:09:19 +01:00
|
|
|
src: krate_src,
|
2016-11-29 08:15:16 +02:00
|
|
|
attrs: cx.tcx.get_attrs(root).clean(cx),
|
2017-08-06 22:54:09 -07:00
|
|
|
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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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 {
|
2018-08-23 10:14:52 +02:00
|
|
|
String::new()
|
2013-08-15 16:28:54 -04:00
|
|
|
};
|
2015-02-02 18:33:24 +09:00
|
|
|
|
2018-01-08 11:10:50 -06: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
|
2018-07-27 21:19:36 -05:00
|
|
|
let attrs = self.attrs.clean(cx);
|
2018-01-01 13:01:19 +05:30
|
|
|
|
2015-02-02 18:33:24 +09:00
|
|
|
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)));
|
2015-06-10 17:22:20 +01:00
|
|
|
items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
|
2018-08-30 12:10:15 -05:00
|
|
|
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)));
|
2015-02-02 18:33:24 +09:00
|
|
|
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)));
|
2015-02-02 18:33:24 +09:00
|
|
|
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)));
|
2015-02-02 18:33:24 +09:00
|
|
|
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)));
|
2015-06-10 17:22:20 +01:00
|
|
|
items.extend(self.impls.iter().flat_map(|x| x.clean(cx)));
|
2015-02-02 18:33:24 +09:00
|
|
|
items.extend(self.macros.iter().map(|x| x.clean(cx)));
|
2018-09-25 14:56:43 -05:00
|
|
|
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)));
|
2014-04-27 05:08:36 +09:00
|
|
|
|
|
|
|
// determine if we should display the inner contents or
|
|
|
|
// the outer `mod` item for the source code.
|
2014-08-11 09:32:26 -07:00
|
|
|
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());
|
2014-04-27 05:08:36 +09:00
|
|
|
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)
|
2014-04-27 05:08:36 +09:00
|
|
|
self.where_inner
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2013-08-15 16:28:54 -04:00
|
|
|
Item {
|
|
|
|
name: Some(name),
|
2018-01-08 10:07:16 -06:00
|
|
|
attrs,
|
2014-09-06 19:13:40 +03:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-24 01:40:52 +02:00
|
|
|
impl Clean<Attributes> for [ast::Attribute] {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Attributes {
|
2018-07-27 21:19:36 -05:00
|
|
|
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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-14 12:08:58 +01:00
|
|
|
impl<'a, 'tcx> Clean<GenericBound> for (&'a ty::TraitRef<'tcx>, Vec<TypeBinding>) {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
|
2018-03-27 20:45:24 +02:00
|
|
|
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,
|
|
|
|
);
|
2014-12-16 08:50:52 -08:00
|
|
|
|
2018-03-27 20:45:24 +02:00
|
|
|
debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
|
2014-12-16 08:50:52 -08:00
|
|
|
|
|
|
|
// collect any late bound regions
|
|
|
|
let mut late_bounds = vec![];
|
2018-03-27 20:45:24 +02:00
|
|
|
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 {
|
2017-04-20 04:45:53 -04:00
|
|
|
if let &ty::RegionKind::ReLateBound(..) = *reg {
|
2014-12-20 00:09:35 -08:00
|
|
|
debug!(" hit an ReLateBound {:?}", reg);
|
2018-05-27 16:56:01 +01:00
|
|
|
if let Some(Lifetime(name)) = reg.clean(cx) {
|
|
|
|
late_bounds.push(GenericParamDef {
|
|
|
|
name,
|
|
|
|
kind: GenericParamDefKind::Lifetime,
|
|
|
|
});
|
2014-12-16 08:50:52 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-14 12:23:46 +01:00
|
|
|
GenericBound::TraitBound(
|
2016-03-24 06:10:52 +01:00
|
|
|
PolyTrait {
|
|
|
|
trait_: ResolvedPath {
|
2017-08-06 22:54:09 -07:00
|
|
|
path,
|
2019-03-13 23:37:02 +00:00
|
|
|
param_names: None,
|
2018-03-27 20:45:24 +02:00
|
|
|
did: trait_ref.def_id,
|
2016-03-24 06:10:52 +01:00
|
|
|
is_generic: false,
|
|
|
|
},
|
2017-10-16 21:07:26 +02:00
|
|
|
generic_params: late_bounds,
|
2015-05-25 15:06:38 +02:00
|
|
|
},
|
2019-12-22 17:42:04 -05:00
|
|
|
hir::TraitBoundModifier::None,
|
2016-03-24 06:10:52 +01:00
|
|
|
)
|
2014-05-03 02:08:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-06-14 12:08:58 +01:00
|
|
|
impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> GenericBound {
|
2018-03-27 20:45:24 +02:00
|
|
|
(self, vec![]).clean(cx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-26 09:30:34 +08:00
|
|
|
impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Option<Vec<GenericBound>> {
|
2014-05-03 02:08:58 -07:00
|
|
|
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 }
|
2014-05-03 02:08:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-07-31 00:04:06 -07:00
|
|
|
impl Clean<Lifetime> for hir::Lifetime {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Lifetime {
|
2019-02-18 10:59:17 +01:00
|
|
|
if self.hir_id != hir::DUMMY_HIR_ID {
|
2019-02-03 08:51:50 +01:00
|
|
|
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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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 { .. } => {
|
2020-02-28 14:20:33 +01:00
|
|
|
if !self.bounds.is_empty() {
|
2018-05-28 13:33:28 +01:00
|
|
|
let mut bounds = self.bounds.iter().map(|bound| match bound {
|
2018-06-14 12:08:58 +01:00
|
|
|
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
|
|
|
}
|
2016-05-15 15:29:44 +02:00
|
|
|
}
|
2018-05-26 00:27:54 +01:00
|
|
|
_ => panic!(),
|
2016-05-15 15:29:44 +02:00
|
|
|
}
|
2014-08-05 22:59:24 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-15 22:24:00 +00:00
|
|
|
impl Clean<Constant> for hir::ConstArg {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Constant {
|
2019-02-15 22:24:00 +00:00
|
|
|
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),
|
2019-12-11 14:50:19 +01:00
|
|
|
value: None,
|
|
|
|
is_literal: is_literal_expr(cx, self.value.body.hir_id),
|
2019-02-15 22:24:00 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-11 12:50:17 +03:00
|
|
|
impl Clean<Lifetime> for ty::GenericParamDef {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, _cx: &DocContext<'_>) -> Lifetime {
|
2015-07-28 18:07:20 +02:00
|
|
|
Lifetime(self.name.to_string())
|
2014-05-03 02:08:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-05-11 16:10:47 +03:00
|
|
|
impl Clean<Option<Lifetime>> for ty::RegionKind {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Option<Lifetime> {
|
2014-05-03 02:08:58 -07:00
|
|
|
match *self {
|
2014-10-05 07:35:04 -07:00
|
|
|
ty::ReStatic => Some(Lifetime::statik()),
|
2017-01-06 14:35:23 -05:00
|
|
|
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))),
|
2014-05-03 02:08:58 -07:00
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
ty::ReLateBound(..)
|
|
|
|
| ty::ReFree(..)
|
|
|
|
| ty::ReScope(..)
|
|
|
|
| ty::ReVar(..)
|
|
|
|
| ty::RePlaceholder(..)
|
2019-10-08 19:26:57 -04:00
|
|
|
| ty::ReEmpty(_)
|
2019-12-22 17:42:04 -05:00
|
|
|
| ty::ReClosureBound(_)
|
|
|
|
| ty::ReErased => {
|
2019-07-23 20:06:00 +02:00
|
|
|
debug!("cannot clean region {:?}", self);
|
2019-01-22 19:54:30 -05:00
|
|
|
None
|
|
|
|
}
|
2014-05-03 02:08:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-01 16:08:58 +01:00
|
|
|
impl Clean<WherePredicate> for hir::WherePredicate<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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),
|
|
|
|
},
|
2014-12-23 01:08:00 -08:00
|
|
|
|
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),
|
|
|
|
},
|
2014-12-23 01:08:00 -08:00
|
|
|
|
2017-01-17 21:18:29 +03:00
|
|
|
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
|
|
|
}
|
2014-09-25 02:01:42 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-22 19:54:30 -05:00
|
|
|
impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
|
2016-03-22 17:30:57 +02:00
|
|
|
use rustc::ty::Predicate;
|
2015-01-10 23:50:46 -08:00
|
|
|
|
|
|
|
match *self {
|
2020-01-13 20:30:31 -08:00
|
|
|
Predicate::Trait(ref pred, _) => Some(pred.clean(cx)),
|
2019-01-22 19:54:30 -05:00
|
|
|
Predicate::Subtype(ref pred) => Some(pred.clean(cx)),
|
2015-01-10 23:50:46 -08:00
|
|
|
Predicate::RegionOutlives(ref pred) => pred.clean(cx),
|
|
|
|
Predicate::TypeOutlives(ref pred) => pred.clean(cx),
|
2019-01-22 19:54:30 -05:00
|
|
|
Predicate::Projection(ref pred) => Some(pred.clean(cx)),
|
2018-11-01 15:09:02 +01:00
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
Predicate::WellFormed(..)
|
|
|
|
| Predicate::ObjectSafe(..)
|
|
|
|
| Predicate::ClosureKind(..)
|
|
|
|
| Predicate::ConstEvaluatable(..) => panic!("not user writable"),
|
2015-01-10 23:50:46 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> WherePredicate {
|
2015-01-10 23:50:46 -08:00
|
|
|
WherePredicate::BoundPredicate {
|
2016-08-08 23:39:49 +03:00
|
|
|
ty: self.trait_ref.self_ty().clean(cx),
|
2019-12-22 17:42:04 -05:00
|
|
|
bounds: vec![self.trait_ref.clean(cx)],
|
2015-01-10 23:50:46 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-03-09 21:47:09 -05:00
|
|
|
impl<'tcx> Clean<WherePredicate> for ty::SubtypePredicate<'tcx> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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>>
|
|
|
|
{
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
|
2015-01-10 23:50:46 -08:00
|
|
|
let ty::OutlivesPredicate(ref a, ref b) = *self;
|
2019-01-22 19:54:30 -05:00
|
|
|
|
|
|
|
match (a, b) {
|
2019-10-08 19:26:57 -04:00
|
|
|
(ty::ReEmpty(_), ty::ReEmpty(_)) => {
|
2019-01-22 19:54:30 -05:00
|
|
|
return None;
|
2019-12-22 17:42:04 -05:00
|
|
|
}
|
2019-01-22 19:54:30 -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"))],
|
2019-01-22 19:54:30 -05:00
|
|
|
})
|
2015-01-10 23:50:46 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-22 19:54:30 -05:00
|
|
|
impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Option<WherePredicate> {
|
2015-01-10 23:50:46 -08:00
|
|
|
let ty::OutlivesPredicate(ref ty, ref lt) = *self;
|
|
|
|
|
2019-01-22 19:54:30 -05:00
|
|
|
match lt {
|
2019-10-08 19:26:57 -04:00
|
|
|
ty::ReEmpty(_) => return None,
|
2019-01-22 19:54:30 -05:00
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
|
|
|
|
Some(WherePredicate::BoundPredicate {
|
2015-01-10 23:50:46 -08:00
|
|
|
ty: ty.clean(cx),
|
2019-12-22 17:42:04 -05:00
|
|
|
bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))],
|
2019-01-22 19:54:30 -05:00
|
|
|
})
|
2015-01-10 23:50:46 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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) }
|
2015-01-10 23:50:46 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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) {
|
2018-06-14 12:08:58 +01:00
|
|
|
GenericBound::TraitBound(t, _) => t.trait_,
|
|
|
|
GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
|
2015-01-10 23:50:46 -08:00
|
|
|
};
|
|
|
|
Type::QPath {
|
2018-06-10 22:24:24 +03:00
|
|
|
name: cx.tcx.associated_item(self.item_def_id).ident.name.clean(cx),
|
2017-07-11 10:33:09 -04:00
|
|
|
self_type: box self.self_ty().clean(cx),
|
2019-12-22 17:42:04 -05:00
|
|
|
trait_: box trait_,
|
2015-01-10 23:50:46 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-13 23:39:56 +00:00
|
|
|
impl Clean<GenericParamDef> for ty::GenericParamDef {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
|
2018-05-27 16:56:01 +01:00
|
|
|
let (name, kind) = match self.kind {
|
|
|
|
ty::GenericParamDefKind::Lifetime => {
|
|
|
|
(self.name.to_string(), GenericParamDefKind::Lifetime)
|
|
|
|
}
|
2019-06-21 12:23:05 +09:00
|
|
|
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,
|
|
|
|
},
|
|
|
|
)
|
2018-05-27 16:56:01 +01:00
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
ty::GenericParamDefKind::Const { .. } => (
|
|
|
|
self.name.clean(cx),
|
|
|
|
GenericParamDefKind::Const {
|
2019-03-13 23:39:56 +00:00
|
|
|
did: self.def_id,
|
|
|
|
ty: cx.tcx.type_of(self.def_id).clean(cx),
|
2019-12-22 17:42:04 -05:00
|
|
|
},
|
|
|
|
),
|
2018-05-27 16:56:01 +01: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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> GenericParamDef {
|
2018-05-27 16:56:01 +01:00
|
|
|
let (name, kind) = match self.kind {
|
2018-05-28 13:33:28 +01:00
|
|
|
hir::GenericParamKind::Lifetime { .. } => {
|
2020-02-28 14:20:33 +01:00
|
|
|
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 {
|
2018-06-14 12:08:58 +01:00
|
|
|
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()));
|
2018-05-27 16:56:01 +01:00
|
|
|
}
|
|
|
|
s
|
|
|
|
} else {
|
2018-06-28 00:12:17 +03:00
|
|
|
self.name.ident().to_string()
|
2018-05-27 16:56:01 +01:00
|
|
|
};
|
|
|
|
(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 {
|
2019-06-27 11:28:14 +02:00
|
|
|
did: cx.tcx.hir().local_def_id(self.hir_id),
|
2018-05-28 13:33:28 +01:00
|
|
|
bounds: self.bounds.clean(cx),
|
2018-05-27 16:56:01 +01:00
|
|
|
default: default.clean(cx),
|
2019-10-06 03:42:53 -04:00
|
|
|
synthetic,
|
2019-12-22 17:42:04 -05:00
|
|
|
},
|
|
|
|
),
|
|
|
|
hir::GenericParamKind::Const { ref ty } => (
|
|
|
|
self.name.ident().name.clean(cx),
|
|
|
|
GenericParamDefKind::Const {
|
2019-06-27 11:28:14 +02:00
|
|
|
did: cx.tcx.hir().local_def_id(self.hir_id),
|
2019-02-15 22:24:00 +00:00
|
|
|
ty: ty.clean(cx),
|
2019-12-22 17:42:04 -05:00
|
|
|
},
|
|
|
|
),
|
2018-05-27 16:56:01 +01:00
|
|
|
};
|
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
GenericParamDef { name, kind }
|
2017-10-16 21:07:26 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-01 16:08:58 +01:00
|
|
|
impl Clean<Generics> for hir::Generics<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Generics {
|
2018-05-14 12:07:34 +09:00
|
|
|
// 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,
|
2018-05-14 12:07:34 +09:00
|
|
|
}
|
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
let impl_trait_params = self
|
|
|
|
.params
|
2018-05-14 12:07:34 +09:00
|
|
|
.iter()
|
2018-05-27 16:56:01 +01:00
|
|
|
.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, .. } => {
|
2019-06-21 12:23:05 +09:00
|
|
|
cx.impl_trait_bounds.borrow_mut().insert(did.into(), bounds.clone());
|
2018-05-27 16:56:01 +01:00
|
|
|
}
|
2019-02-15 22:24:00 +00:00
|
|
|
GenericParamDefKind::Const { .. } => unreachable!(),
|
2018-05-14 12:07:34 +09:00
|
|
|
}
|
2018-05-27 16:56:01 +01:00
|
|
|
param
|
2018-05-14 12:07:34 +09:00
|
|
|
})
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
2018-05-03 22:24:50 +09:00
|
|
|
let mut params = Vec::with_capacity(self.params.len());
|
2018-05-14 12:07:34 +09:00
|
|
|
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);
|
|
|
|
}
|
2018-05-14 12:07:34 +09:00
|
|
|
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) };
|
2017-12-17 14:08:09 +01:00
|
|
|
|
|
|
|
// 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.
|
2018-05-27 16:56:01 +01:00
|
|
|
for where_pred in &mut generics.where_predicates {
|
2017-12-17 14:08:09 +01:00
|
|
|
match *where_pred {
|
|
|
|
WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
|
|
|
|
if bounds.is_empty() {
|
2018-05-27 16:56:01 +01:00
|
|
|
for param in &mut generics.params {
|
|
|
|
match param.kind {
|
|
|
|
GenericParamDefKind::Lifetime => {}
|
|
|
|
GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
|
|
|
|
if ¶m.name == name {
|
|
|
|
mem::swap(bounds, ty_bounds);
|
2019-12-22 17:42:04 -05:00
|
|
|
break;
|
2018-05-27 16:56:01 +01:00
|
|
|
}
|
2017-10-16 21:07:26 +02:00
|
|
|
}
|
2019-02-15 22:24:00 +00:00
|
|
|
GenericParamDefKind::Const { .. } => {}
|
2017-12-17 14:08:09 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
_ => continue,
|
|
|
|
}
|
2013-08-15 16:28:54 -04:00
|
|
|
}
|
2018-05-27 16:56:01 +01:00
|
|
|
generics
|
2013-08-15 16:28:54 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-10-18 03:14:57 +03:00
|
|
|
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx>) {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Generics {
|
2015-01-10 23:50:46 -08:00
|
|
|
use self::WherePredicate as WP;
|
2019-07-09 16:37:55 +09:00
|
|
|
use std::collections::BTreeMap;
|
2015-01-10 23:50:46 -08:00
|
|
|
|
2016-08-10 20:39:09 +03:00
|
|
|
let (gens, preds) = *self;
|
2015-02-11 10:28:52 -05:00
|
|
|
|
2019-06-21 12:23:05 +09:00
|
|
|
// Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
|
|
|
|
// since `Clean for ty::Predicate` would consume them.
|
2019-07-09 16:37:55 +09:00
|
|
|
let mut impl_trait = BTreeMap::<ImplTraitParam, Vec<GenericBound>>::default();
|
2019-06-21 12:23:05 +09:00
|
|
|
|
2015-04-06 21:17:51 -07:00
|
|
|
// 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()
|
2019-06-21 12:23:05 +09:00
|
|
|
.filter_map(|param| match param.kind {
|
|
|
|
ty::GenericParamDefKind::Lifetime => None,
|
|
|
|
ty::GenericParamDefKind::Type { synthetic, .. } => {
|
2019-10-18 13:22:50 +11:00
|
|
|
if param.name == kw::SelfUpper {
|
2019-06-21 12:23:05 +09:00
|
|
|
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))
|
2018-04-14 19:20:51 +01:00
|
|
|
}
|
2019-06-21 12:23:05 +09:00
|
|
|
ty::GenericParamDefKind::Const { .. } => None,
|
2019-12-22 17:42:04 -05:00
|
|
|
})
|
|
|
|
.collect::<Vec<GenericParamDef>>();
|
2015-01-10 23:50:46 -08:00
|
|
|
|
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-07-08 17:59:26 +09:00
|
|
|
|
2019-12-22 17:42:04 -05:00
|
|
|
let where_predicates = preds
|
|
|
|
.predicates
|
|
|
|
.iter()
|
2019-06-21 12:23:05 +09:00
|
|
|
.flat_map(|(p, _)| {
|
2019-07-08 20:42:45 +09:00
|
|
|
let mut projection = None;
|
2019-07-08 17:59:26 +09:00
|
|
|
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 {
|
2019-07-08 17:59:26 +09:00
|
|
|
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 {
|
2019-07-08 17:59:26 +09:00
|
|
|
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);
|
2019-07-08 17:59:26 +09:00
|
|
|
return Some(param.index);
|
|
|
|
}
|
2019-06-21 12:23:05 +09:00
|
|
|
}
|
2019-07-08 17:59:26 +09:00
|
|
|
|
2019-06-21 12:23:05 +09:00
|
|
|
None
|
2019-07-08 17:59:26 +09:00
|
|
|
})();
|
2019-06-21 12:23:05 +09:00
|
|
|
|
2019-07-08 17:59:26 +09:00
|
|
|
if let Some(param_idx) = param_idx {
|
|
|
|
if let Some(b) = impl_trait.get_mut(¶m_idx.into()) {
|
2019-07-09 16:59:34 +09:00
|
|
|
let p = p.clean(cx)?;
|
|
|
|
|
2019-07-08 17:59:26 +09:00
|
|
|
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 17:59:26 +09:00
|
|
|
);
|
|
|
|
|
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,
|
|
|
|
));
|
2019-07-08 17:59:26 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
return None;
|
|
|
|
}
|
2019-06-21 12:23:05 +09:00
|
|
|
}
|
|
|
|
|
|
|
|
Some(p)
|
|
|
|
})
|
2018-09-16 20:15:49 +03:00
|
|
|
.collect::<Vec<_>>();
|
2015-02-11 10:28:52 -05:00
|
|
|
|
2019-07-09 16:37:55 +09:00
|
|
|
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-06-21 12:23:05 +09:00
|
|
|
|
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);
|
|
|
|
}
|
2019-06-21 12:23:05 +09:00
|
|
|
|
2019-07-09 16:59:34 +09:00
|
|
|
// 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<_>>();
|
2019-07-09 16:59:34 +09:00
|
|
|
|
2015-04-07 00:16:35 -07:00
|
|
|
// Type parameters and have a Sized bound by default unless removed with
|
2017-12-17 14:08:09 +01:00
|
|
|
// ?Sized. Scan through the predicates and mark any type parameter with
|
2015-04-06 21:17:51 -07:00
|
|
|
// a Sized bound, removing the bounds as we find them.
|
2015-04-07 00:16:35 -07:00
|
|
|
//
|
|
|
|
// 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
|
2015-04-07 00:16:35 -07:00
|
|
|
// handled in cleaning associated types
|
2018-10-16 10:44:26 +02:00
|
|
|
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
|
2015-01-10 23:50:46 -08:00
|
|
|
}
|
|
|
|
}
|
2019-12-22 17:42:04 -05:00
|
|
|
_ => true,
|
2015-04-07 00:16:35 -07:00
|
|
|
});
|
2015-02-11 10:28:52 -05:00
|
|
|
|
2015-04-07 00:16:35 -07:00
|
|
|
// Run through the type parameters again and insert a ?Sized
|
2015-04-06 21:17:51 -07:00
|
|
|
// unbound for any we didn't find to be Sized.
|
2015-01-31 12:20:46 -05:00
|
|
|
for tp in &stripped_typarams {
|
2015-01-10 23:50:46 -08:00
|
|
|
if !sized_params.contains(&tp.name) {
|
|
|
|
where_predicates.push(WP::BoundPredicate {
|
|
|
|
ty: Type::Generic(tp.name.clone()),
|
2018-06-14 12:08:58 +01:00
|
|
|
bounds: vec![GenericBound::maybe_sized(cx)],
|
2015-01-10 23:50:46 -08:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// It would be nice to collect all of the bounds on a type and recombine
|
2018-11-27 02:59:49 +00:00
|
|
|
// them if possible, to avoid e.g., `where T: Foo, T: Bar, T: Sized, T: 'a`
|
2015-01-10 23:50:46 -08:00
|
|
|
// and instead see `where T: Foo + Bar + Sized + 'a`
|
|
|
|
|
2014-05-03 02:08:58 -07:00
|
|
|
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(),
|
2015-04-07 12:20:24 -07:00
|
|
|
where_predicates: simplify::where_clauses(cx, where_predicates),
|
2014-05-03 02:08:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
{
|
2018-12-08 20:30:23 +01: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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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
|
|
|
|
2019-06-27 11:28:14 +02:00
|
|
|
let did = cx.tcx.hir().local_def_id(self.id);
|
2020-01-01 18:06:00 +01:00
|
|
|
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 {
|
2014-09-06 19:13:40 +03:00
|
|
|
name: Some(self.name.clean(cx)),
|
|
|
|
attrs: self.attrs.clean(cx),
|
|
|
|
source: self.whence.clean(cx),
|
|
|
|
visibility: self.vis.clean(cx),
|
2019-07-24 16:18:32 -04:00
|
|
|
stability: cx.stability(self.id).clean(cx),
|
2019-07-24 16:22:48 -04:00
|
|
|
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 {
|
2018-03-24 14:12:08 +09:00
|
|
|
decl,
|
|
|
|
generics,
|
2018-12-18 22:24:20 +01:00
|
|
|
header: hir::FnHeader { constness, ..self.header },
|
2019-03-07 02:44:28 +01:00
|
|
|
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]) {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Arguments {
|
2016-12-20 22:46:11 +02:00
|
|
|
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(),
|
2016-12-20 22:46:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-01 16:08:58 +01:00
|
|
|
impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], hir::BodyId) {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Arguments {
|
2018-12-04 13:45:36 +01:00
|
|
|
let body = cx.tcx.hir().body(self.1);
|
2016-12-20 22:46:11 +02:00
|
|
|
|
|
|
|
Arguments {
|
2019-12-22 17:42:04 -05:00
|
|
|
values: self
|
|
|
|
.0
|
|
|
|
.iter()
|
|
|
|
.enumerate()
|
|
|
|
.map(|(i, ty)| Argument {
|
2019-08-27 13:24:32 +02:00
|
|
|
name: name_from_pat(&body.params[i].pat),
|
2016-12-20 22:46:11 +02:00
|
|
|
type_: ty.clean(cx),
|
2019-12-22 17:42:04 -05:00
|
|
|
})
|
|
|
|
.collect(),
|
2016-12-20 22:46:11 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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>,
|
2016-12-20 22:46:11 +02:00
|
|
|
{
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
|
2013-08-15 16:28:54 -04:00
|
|
|
FnDecl {
|
2016-12-20 22:46:11 +02:00
|
|
|
inputs: (&self.0.inputs[..], self.1).clean(cx),
|
|
|
|
output: self.0.output.clean(cx),
|
2019-08-10 14:38:17 +03:00
|
|
|
c_variadic: self.0.c_variadic,
|
2019-03-07 02:44:28 +01:00
|
|
|
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>) {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> FnDecl {
|
2014-05-23 18:47:01 -07:00
|
|
|
let (did, sig) = *self;
|
2019-03-04 09:00:30 +01:00
|
|
|
let mut names = if cx.tcx.hir().as_local_hir_id(did).is_some() {
|
2015-09-04 13:52:28 -04:00
|
|
|
vec![].into_iter()
|
2014-05-23 18:47:01 -07:00
|
|
|
} 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
|
|
|
};
|
|
|
|
|
2014-05-03 02:08:58 -07:00
|
|
|
FnDecl {
|
2016-11-28 19:35:38 -07:00
|
|
|
output: Return(sig.skip_binder().output().clean(cx)),
|
2016-11-24 01:40:52 +02:00
|
|
|
attrs: Attributes::default(),
|
2019-08-10 14:38:17 +03:00
|
|
|
c_variadic: sig.skip_binder().c_variadic,
|
2014-05-03 02:08:58 -07:00
|
|
|
inputs: Arguments {
|
2019-12-22 17:42:04 -05:00
|
|
|
values: sig
|
|
|
|
.skip_binder()
|
|
|
|
.inputs()
|
|
|
|
.iter()
|
|
|
|
.map(|t| Argument {
|
2014-09-06 19:13:40 +03:00
|
|
|
type_: t.clean(cx),
|
2018-08-23 10:14:52 +02:00
|
|
|
name: names.next().map_or(String::new(), |name| name.to_string()),
|
2019-12-22 17:42:04 -05:00
|
|
|
})
|
|
|
|
.collect(),
|
2014-05-03 02:08:58 -07:00
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2017-10-04 15:51:35 -05:00
|
|
|
let attrs = self.attrs.clean(cx);
|
2019-05-08 13:21:18 +10:00
|
|
|
let is_spotlight = attrs.has_doc_flag(sym::spotlight);
|
2013-08-15 16:28:54 -04:00
|
|
|
Item {
|
2014-09-06 19:13:40 +03:00
|
|
|
name: Some(self.name.clean(cx)),
|
2019-10-06 03:42:53 -04:00
|
|
|
attrs,
|
2014-09-06 19:13:40 +03:00
|
|
|
source: self.whence.clean(cx),
|
2019-06-27 11:28:14 +02:00
|
|
|
def_id: cx.tcx.hir().local_def_id(self.id),
|
2014-09-06 19:13:40 +03:00
|
|
|
visibility: self.vis.clean(cx),
|
2019-07-24 16:18:32 -04:00
|
|
|
stability: cx.stability(self.id).clean(cx),
|
2019-07-24 16:22:48 -04:00
|
|
|
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),
|
2014-12-09 19:59:20 -05:00
|
|
|
unsafety: self.unsafety,
|
2019-06-12 11:43:15 +03:00
|
|
|
items: self.items.iter().map(|ti| ti.clean(cx)).collect(),
|
2014-09-06 19:13:40 +03:00
|
|
|
generics: self.generics.clean(cx),
|
|
|
|
bounds: self.bounds.clean(cx),
|
2019-02-05 14:27:09 +01:00
|
|
|
is_spotlight,
|
2018-01-23 01:04:24 +00:00
|
|
|
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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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),
|
2019-06-27 11:28:14 +02:00
|
|
|
def_id: cx.tcx.hir().local_def_id(self.id),
|
2019-02-05 14:27:09 +01:00
|
|
|
visibility: self.vis.clean(cx),
|
2019-07-24 16:18:32 -04:00
|
|
|
stability: cx.stability(self.id).clean(cx),
|
2019-07-24 16:22:48 -04:00
|
|
|
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),
|
|
|
|
}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-23 01:04:24 +00:00
|
|
|
impl Clean<bool> for hir::IsAuto {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, _: &DocContext<'_>) -> bool {
|
2018-01-23 01:04:24 +00:00
|
|
|
match *self {
|
|
|
|
hir::IsAuto::Yes => true,
|
|
|
|
hir::IsAuto::No => false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-01 16:08:58 +01:00
|
|
|
impl Clean<Type> for hir::TraitRef<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Type {
|
2019-02-18 10:59:17 +01:00
|
|
|
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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> PolyTrait {
|
2014-12-16 08:50:52 -08:00
|
|
|
PolyTrait {
|
|
|
|
trait_: self.trait_ref.clean(cx),
|
2019-12-22 17:42:04 -05:00
|
|
|
generic_params: self.bound_generic_params.clean(cx),
|
2014-12-16 08:50:52 -08:00
|
|
|
}
|
2014-11-07 06:53:45 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-28 21:47:10 +01:00
|
|
|
impl Clean<Item> for hir::TraitItem<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2019-09-26 17:07:54 +01:00
|
|
|
let inner = match self.kind {
|
2016-12-21 12:32:59 +02:00
|
|
|
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)))
|
2015-03-14 12:05:00 -06:00
|
|
|
}
|
2016-12-20 22:46:11 +02:00
|
|
|
hir::TraitItemKind::Method(ref sig, hir::TraitMethod::Provided(body)) => {
|
2019-03-05 02:29:21 +01:00
|
|
|
MethodItem((sig, &self.generics, body, None).clean(cx))
|
2015-03-11 23:38:58 +02:00
|
|
|
}
|
2016-12-20 22:46:11 +02:00
|
|
|
hir::TraitItemKind::Method(ref sig, hir::TraitMethod::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 })
|
2015-03-11 23:38:58 +02:00
|
|
|
}
|
2016-12-04 04:21:06 +02:00
|
|
|
hir::TraitItemKind::Type(ref bounds, ref default) => {
|
2019-05-19 16:26:08 +08:00
|
|
|
AssocTypeItem(bounds.clean(cx), default.clean(cx))
|
2015-03-10 12:28:44 +02:00
|
|
|
}
|
|
|
|
};
|
2019-06-27 11:28:14 +02:00
|
|
|
let local_did = cx.tcx.hir().local_def_id(self.hir_id);
|
2015-03-10 12:28:44 +02:00
|
|
|
Item {
|
2018-06-10 22:24:24 +03:00
|
|
|
name: Some(self.ident.name.clean(cx)),
|
2015-03-10 12:28:44 +02:00
|
|
|
attrs: self.attrs.clean(cx),
|
|
|
|
source: self.span.clean(cx),
|
2019-02-26 11:04:58 +01:00
|
|
|
def_id: local_did,
|
2019-09-12 22:32:12 -04:00
|
|
|
visibility: Visibility::Inherited,
|
2019-02-26 11:04:58 +01:00
|
|
|
stability: get_stability(cx, local_did),
|
|
|
|
deprecation: get_deprecation(cx, local_did),
|
2017-08-06 22:54:09 -07:00
|
|
|
inner,
|
2014-08-04 13:56:56 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-28 22:16:44 +01:00
|
|
|
impl Clean<Item> for hir::ImplItem<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2019-09-26 16:38:13 +01:00
|
|
|
let inner = match self.kind {
|
2016-12-21 12:32:59 +02:00
|
|
|
hir::ImplItemKind::Const(ref ty, expr) => {
|
2019-12-22 17:42:04 -05:00
|
|
|
AssocConstItem(ty.clean(cx), Some(print_const_expr(cx, expr)))
|
2015-03-14 12:05:00 -06:00
|
|
|
}
|
2016-12-20 22:46:11 +02:00
|
|
|
hir::ImplItemKind::Method(ref sig, body) => {
|
2019-03-05 02:29:21 +01:00
|
|
|
MethodItem((sig, &self.generics, body, Some(self.defaultness)).clean(cx))
|
2015-03-11 23:38:58 +02:00
|
|
|
}
|
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,
|
|
|
|
),
|
2015-03-10 12:28:44 +02:00
|
|
|
};
|
2019-06-27 11:28:14 +02:00
|
|
|
let local_did = cx.tcx.hir().local_def_id(self.hir_id);
|
2015-03-10 12:28:44 +02:00
|
|
|
Item {
|
2018-06-10 22:24:24 +03:00
|
|
|
name: Some(self.ident.name.clean(cx)),
|
2015-03-10 12:28:44 +02:00
|
|
|
source: self.span.clean(cx),
|
|
|
|
attrs: self.attrs.clean(cx),
|
2019-02-26 15:11:59 +01:00
|
|
|
def_id: local_did,
|
2015-03-10 12:28:44 +02:00
|
|
|
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),
|
2017-08-06 22:54:09 -07:00
|
|
|
inner,
|
2013-08-15 16:28:54 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-11 12:50:17 +03:00
|
|
|
impl Clean<Item> for ty::AssocItem {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2016-11-10 02:06:34 +02:00
|
|
|
let inner = match self.kind {
|
2019-05-19 16:26:08 +08:00
|
|
|
ty::AssocKind::Const => {
|
2017-04-24 15:20:46 +03:00
|
|
|
let ty = cx.tcx.type_of(self.def_id);
|
2017-11-29 22:05:38 +00:00
|
|
|
let default = if self.defaultness.has_value() {
|
|
|
|
Some(inline::print_inlined_const(cx, self.def_id))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2019-05-19 16:26:08 +08:00
|
|
|
AssocConstItem(ty.clean(cx), default)
|
2016-05-08 21:19:29 +03:00
|
|
|
}
|
2019-05-19 16:26:08 +08: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);
|
2017-05-13 17:11:52 +03:00
|
|
|
let sig = cx.tcx.fn_sig(self.def_id);
|
2017-02-13 10:51:06 +02:00
|
|
|
let mut decl = (self.def_id, sig).clean(cx);
|
2016-11-10 02:06:34 +02:00
|
|
|
|
|
|
|
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),
|
2019-08-12 22:15:12 +01:00
|
|
|
ty::TraitContainer(_) => cx.tcx.types.self_param,
|
2016-11-10 02:06:34 +02:00
|
|
|
};
|
2017-02-13 10:51:06 +02:00
|
|
|
let self_arg_ty = *sig.input(0).skip_binder();
|
2016-11-10 02:06:34 +02:00
|
|
|
if self_arg_ty == self_ty {
|
2016-12-04 03:18:11 +02:00
|
|
|
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 {
|
2018-05-02 15:21:05 +02:00
|
|
|
if ty == self_ty {
|
2016-11-10 02:06:34 +02:00
|
|
|
match decl.inputs.values[0].type_ {
|
2019-12-22 17:42:04 -05:00
|
|
|
BorrowedRef { ref mut type_, .. } => {
|
2016-12-04 03:18:11 +02:00
|
|
|
**type_ = Generic(String::from("Self"))
|
|
|
|
}
|
2016-11-10 02:06:34 +02:00
|
|
|
_ => unreachable!(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2016-11-14 11:00:02 -05:00
|
|
|
|
2016-11-10 02:06:34 +02:00
|
|
|
let provided = match self.container {
|
2017-11-29 22:05:38 +00:00
|
|
|
ty::ImplContainer(_) => true,
|
2019-12-22 17:42:04 -05:00
|
|
|
ty::TraitContainer(_) => self.defaultness.has_value(),
|
2016-11-10 02:06:34 +02:00
|
|
|
};
|
2019-03-07 16:47:40 +01:00
|
|
|
let (all_types, ret_types) = get_all_types(&generics, &decl, cx);
|
2016-11-10 02:06:34 +02:00
|
|
|
if provided {
|
2020-01-01 18:06:00 +01:00
|
|
|
let constness = if is_min_const_fn(cx.tcx, self.def_id) {
|
2017-11-29 22:05:38 +00:00
|
|
|
hir::Constness::Const
|
|
|
|
} else {
|
|
|
|
hir::Constness::NotConst
|
|
|
|
};
|
2019-09-21 03:17:57 +00:00
|
|
|
let asyncness = cx.tcx.asyncness(self.def_id);
|
2019-04-14 23:53:51 +01:00
|
|
|
let defaultness = match self.container {
|
|
|
|
ty::ImplContainer(_) => Some(self.defaultness),
|
|
|
|
ty::TraitContainer(_) => None,
|
|
|
|
};
|
2016-11-10 02:06:34 +02:00
|
|
|
MethodItem(Method {
|
2017-08-06 22:54:09 -07:00
|
|
|
generics,
|
|
|
|
decl,
|
2018-05-16 22:55:18 -07:00
|
|
|
header: hir::FnHeader {
|
|
|
|
unsafety: sig.unsafety(),
|
|
|
|
abi: sig.abi(),
|
|
|
|
constness,
|
2019-09-19 03:21:11 +00:00
|
|
|
asyncness,
|
2019-03-05 02:29:21 +01:00
|
|
|
},
|
2019-04-14 23:53:51 +01:00
|
|
|
defaultness,
|
2019-03-07 02:44:28 +01:00
|
|
|
all_types,
|
2019-03-07 16:47:40 +01:00
|
|
|
ret_types,
|
2016-11-10 02:06:34 +02:00
|
|
|
})
|
|
|
|
} else {
|
|
|
|
TyMethodItem(TyMethod {
|
2017-08-06 22:54:09 -07:00
|
|
|
generics,
|
|
|
|
decl,
|
2018-05-16 22:55:18 -07:00
|
|
|
header: hir::FnHeader {
|
|
|
|
unsafety: sig.unsafety(),
|
|
|
|
abi: sig.abi(),
|
2018-06-22 17:27:58 -07:00
|
|
|
constness: hir::Constness::NotConst,
|
|
|
|
asyncness: hir::IsAsync::NotAsync,
|
2019-03-07 02:44:28 +01:00
|
|
|
},
|
|
|
|
all_types,
|
2019-03-07 16:47:40 +01:00
|
|
|
ret_types,
|
2016-11-10 02:06:34 +02:00
|
|
|
})
|
2016-05-08 21:19:29 +03:00
|
|
|
}
|
|
|
|
}
|
2019-05-19 16:26:08 +08:00
|
|
|
ty::AssocKind::Type => {
|
2018-06-10 22:24:24 +03:00
|
|
|
let my_name = self.ident.name.clean(cx);
|
2016-11-10 02:06:34 +02:00
|
|
|
|
2017-11-29 22:05:38 +00:00
|
|
|
if let ty::TraitContainer(did) = self.container {
|
2016-11-10 02:06:34 +02:00
|
|
|
// 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.
|
2019-03-31 15:32:25 +02:00
|
|
|
let predicates = cx.tcx.explicit_predicates_of(did);
|
2019-10-18 03:14:57 +03:00
|
|
|
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<_>>();
|
2017-11-29 22:05:38 +00:00
|
|
|
// 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);
|
|
|
|
}
|
2018-06-14 12:08:58 +01:00
|
|
|
None => bounds.push(GenericBound::maybe_sized(cx)),
|
2017-11-29 22:05:38 +00:00
|
|
|
}
|
2016-11-10 02:06:34 +02:00
|
|
|
|
2017-11-29 22:05:38 +00:00
|
|
|
let ty = if self.defaultness.has_value() {
|
|
|
|
Some(cx.tcx.type_of(self.def_id))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
};
|
2016-11-10 02:06:34 +02:00
|
|
|
|
2019-05-19 16:26:08 +08:00
|
|
|
AssocTypeItem(bounds, ty.clean(cx))
|
2016-11-10 02:06:34 +02:00
|
|
|
} 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,
|
2017-11-29 22:05:38 +00:00
|
|
|
},
|
2019-12-22 17:42:04 -05:00
|
|
|
true,
|
|
|
|
)
|
2017-11-29 22:05:38 +00:00
|
|
|
}
|
2015-04-07 11:50:14 -07:00
|
|
|
}
|
2019-08-01 00:41:54 +01:00
|
|
|
ty::AssocKind::OpaqueTy => unimplemented!(),
|
2015-04-07 11:50:14 -07:00
|
|
|
};
|
|
|
|
|
2017-11-29 22:05:38 +00:00
|
|
|
let visibility = match self.container {
|
|
|
|
ty::ImplContainer(_) => self.vis.clean(cx),
|
2019-09-12 22:32:12 -04:00
|
|
|
ty::TraitContainer(_) => Inherited,
|
2017-11-29 22:05:38 +00:00
|
|
|
};
|
|
|
|
|
2014-06-02 00:09:44 -07:00
|
|
|
Item {
|
2018-06-10 22:24:24 +03:00
|
|
|
name: Some(self.ident.name.clean(cx)),
|
2017-11-29 22:05:38 +00:00
|
|
|
visibility,
|
2014-09-06 19:13:40 +03:00
|
|
|
stability: get_stability(cx, self.def_id),
|
2015-12-12 23:01:27 +03:00
|
|
|
deprecation: get_deprecation(cx, self.def_id),
|
2014-05-03 02:08:58 -07:00
|
|
|
def_id: self.def_id,
|
Use doc comments from 'pub use' statements
Split off from #62855
Currently, rustdoc ignores any doc comments found on 'pub use'
statements. As described in issue #58700, this makes it impossible to
properly document procedural macros. Any doc comments must be written on
the procedural macro definition, which must occur in a dedicated
proc-macro crate. This means that any doc comments or doc tests cannot
reference items defined in re-exporting crate, despite the fact that
such items may be required to use the procedural macro.
To solve this issue, this commit allows doc comments to be written on
'pub use' statements. For consistency, this applies to *all* 'pub use'
statements, not just those importing procedural macros.
When inlining documentation, documentation on 'pub use' statements will
be prepended to the documentation of the inlined item. For example,
the following items:
```rust
mod other_mod {
/// Doc comment from definition
pub struct MyStruct;
}
/// Doc comment from 'pub use'
///
pub use other_mod::MyStruct;
```
will caues the documentation for the re-export of 'MyStruct' to be
rendered as:
```
Doc comment from 'pub use'
Doc comment from definition
```
Note the empty line in the 'pub use' doc comments - because doc comments
are concatenated as-is, this ensure that the doc comments on the
definition start on a new line.
2019-07-27 14:18:50 -04:00
|
|
|
attrs: inline::load_attrs(cx, self.def_id).clean(cx),
|
2016-11-29 08:15:16 +02:00
|
|
|
source: cx.tcx.def_span(self.def_id).clean(cx),
|
2017-08-06 22:54:09 -07:00
|
|
|
inner,
|
2014-06-02 00:09:44 -07:00
|
|
|
}
|
2014-05-03 02:08:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-01 16:08:58 +01:00
|
|
|
impl Clean<Type> for hir::Ty<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Type {
|
2020-01-05 02:37:57 +01:00
|
|
|
use rustc_hir::*;
|
2018-08-21 00:43:02 +02:00
|
|
|
|
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) }
|
2017-01-09 17:46:11 +02:00
|
|
|
}
|
2018-07-11 23:36:06 +08:00
|
|
|
TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
|
|
|
|
TyKind::Array(ref ty, ref length) => {
|
2019-06-27 11:28:14 +02:00
|
|
|
let def_id = cx.tcx.hir().local_def_id(length.hir_id);
|
2019-11-30 08:42:56 +13:00
|
|
|
let length = match cx.tcx.const_eval_poly(def_id) {
|
2020-02-15 11:56:23 +13:00
|
|
|
Ok(length) => {
|
2020-02-16 09:59:01 +13:00
|
|
|
print_const(cx, ty::Const::from_value(cx.tcx, length, cx.tcx.types.usize))
|
2020-02-15 11:56:23 +13:00
|
|
|
}
|
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()),
|
2018-12-11 19:56:59 +01:00
|
|
|
};
|
2018-05-17 21:28:50 +03:00
|
|
|
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, _) => {
|
2019-06-14 18:58:55 +02:00
|
|
|
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)) => {
|
2019-04-20 19:36:05 +03:00
|
|
|
if let Res::Def(DefKind::TyParam, did) = path.res {
|
2019-04-20 19:46:19 +03:00
|
|
|
if let Some(new_ty) = cx.ty_substs.borrow().get(&did).cloned() {
|
|
|
|
return new_ty;
|
|
|
|
}
|
2019-06-21 12:23:05 +09:00
|
|
|
if let Some(bounds) = cx.impl_trait_bounds.borrow_mut().remove(&did.into()) {
|
2018-03-24 14:12:08 +09:00
|
|
|
return ImplTrait(bounds);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-20 03:42:54 +02:00
|
|
|
let mut alias = None;
|
2019-04-20 19:36:05 +03:00
|
|
|
if let Res::Def(DefKind::TyAlias, def_id) = path.res {
|
2016-11-20 03:42:54 +02:00
|
|
|
// Substitute private type aliases
|
2019-02-15 12:16:36 +01:00
|
|
|
if let Some(hir_id) = cx.tcx.hir().as_local_hir_id(def_id) {
|
2018-08-30 16:46:10 -05:00
|
|
|
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-11-20 03:42:54 +02:00
|
|
|
}
|
2016-09-01 10:21:12 +03:00
|
|
|
}
|
2016-11-20 03:42:54 +02:00
|
|
|
};
|
|
|
|
|
2019-08-02 11:02:08 +01: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");
|
2018-10-16 10:44:26 +02:00
|
|
|
let mut ty_substs = FxHashMap::default();
|
|
|
|
let mut lt_substs = FxHashMap::default();
|
2019-04-20 19:46:19 +03:00
|
|
|
let mut ct_substs = FxHashMap::default();
|
2019-06-12 11:42:58 +03:00
|
|
|
let generic_args = provided_params.generic_args();
|
|
|
|
{
|
2018-08-07 17:44:30 +01:00
|
|
|
let mut indices: GenericParamCount = Default::default();
|
2018-04-13 00:57:38 +01:00
|
|
|
for param in generics.params.iter() {
|
2018-05-26 00:27:54 +01:00
|
|
|
match param.kind {
|
|
|
|
hir::GenericParamKind::Lifetime { .. } => {
|
2018-05-27 01:43:03 +01:00
|
|
|
let mut j = 0;
|
2019-12-22 17:42:04 -05:00
|
|
|
let lifetime =
|
|
|
|
generic_args.args.iter().find_map(|arg| match arg {
|
2019-02-15 22:26:05 +00:00
|
|
|
hir::GenericArg::Lifetime(lt) => {
|
2018-05-27 01:43:03 +01:00
|
|
|
if indices.lifetimes == j {
|
|
|
|
return Some(lt);
|
|
|
|
}
|
|
|
|
j += 1;
|
|
|
|
None
|
|
|
|
}
|
|
|
|
_ => None,
|
2019-12-22 17:42:04 -05:00
|
|
|
});
|
2018-05-27 01:43:03 +01:00
|
|
|
if let Some(lt) = lifetime.cloned() {
|
2018-04-18 11:33:52 +01:00
|
|
|
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);
|
2018-04-18 11:33:52 +01:00
|
|
|
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);
|
2018-05-27 01:43:03 +01:00
|
|
|
let mut j = 0;
|
2019-12-22 17:42:04 -05:00
|
|
|
let type_ =
|
|
|
|
generic_args.args.iter().find_map(|arg| match arg {
|
2019-02-15 22:26:05 +00:00
|
|
|
hir::GenericArg::Type(ty) => {
|
2018-05-27 01:43:03 +01:00
|
|
|
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_ {
|
2019-04-20 19:46:19 +03:00
|
|
|
ty_substs.insert(ty_param_def_id, ty.clean(cx));
|
2020-01-22 16:30:15 +01:00
|
|
|
} else if let Some(default) = *default {
|
2019-12-22 17:42:04 -05:00
|
|
|
ty_substs.insert(ty_param_def_id, default.clean(cx));
|
2018-04-13 00:57:38 +01:00
|
|
|
}
|
2018-04-18 11:33:52 +01:00
|
|
|
indices.types += 1;
|
2017-09-21 23:24:26 +03:00
|
|
|
}
|
2019-02-15 22:24:00 +00:00
|
|
|
hir::GenericParamKind::Const { .. } => {
|
2019-04-20 19:46:19 +03:00
|
|
|
let const_param_def_id =
|
2019-06-27 11:28:14 +02:00
|
|
|
cx.tcx.hir().local_def_id(param.hir_id);
|
2019-02-15 22:24:00 +00:00
|
|
|
let mut j = 0;
|
2019-12-22 17:42:04 -05:00
|
|
|
let const_ =
|
|
|
|
generic_args.args.iter().find_map(|arg| match arg {
|
2019-02-15 22:24:00 +00:00
|
|
|
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_ {
|
2019-04-20 19:46:19 +03:00
|
|
|
ct_substs.insert(const_param_def_id, ct.clean(cx));
|
2019-02-15 22:24:00 +00:00
|
|
|
}
|
|
|
|
// FIXME(const_generics:defaults)
|
|
|
|
indices.consts += 1;
|
|
|
|
}
|
2017-01-09 17:46:11 +02:00
|
|
|
}
|
2016-07-07 18:20:26 +03:00
|
|
|
}
|
2019-06-12 11:42:58 +03:00
|
|
|
}
|
2019-04-20 19:46:19 +03:00
|
|
|
return cx.enter_alias(ty_substs, lt_substs, ct_substs, || ty.clean(cx));
|
2016-07-07 18:20:26 +03:00
|
|
|
}
|
2019-02-18 10:59:17 +01:00
|
|
|
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(),
|
2019-04-20 19:36:05 +03:00
|
|
|
res: Res::Def(
|
2019-04-20 18:26:26 +03:00
|
|
|
DefKind::Trait,
|
2019-04-20 19:36:05 +03:00
|
|
|
cx.tcx.associated_item(p.res.def_id()).container.id(),
|
2019-04-20 18:26:26 +03:00
|
|
|
),
|
2019-06-12 11:43:15 +03:00
|
|
|
segments: trait_segments.clean(cx),
|
2015-12-17 20:41:28 +03:00
|
|
|
};
|
2015-01-31 05:51:21 +02:00
|
|
|
Type::QPath {
|
2018-07-29 15:39:51 +02:00
|
|
|
name: p.segments.last().expect("segments were empty").ident.name.clean(cx),
|
2016-10-27 05:17:42 +03:00
|
|
|
self_type: box qself.clean(cx),
|
2019-12-22 17:42:04 -05:00
|
|
|
trait_: box resolve_type(cx, trait_path, self.hir_id),
|
2016-10-27 05:17:42 +03:00
|
|
|
}
|
|
|
|
}
|
2018-07-11 23:36:06 +08:00
|
|
|
TyKind::Path(hir::QPath::TypeRelative(ref qself, ref segment)) => {
|
2019-04-20 19:36:05 +03:00
|
|
|
let mut res = Res::Err;
|
2017-05-03 11:53:06 -04:00
|
|
|
let ty = hir_ty_to_ty(cx.tcx, self);
|
2019-09-16 19:08:35 +01:00
|
|
|
if let ty::Projection(proj) = ty.kind {
|
2019-04-20 19:36:05 +03:00
|
|
|
res = Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id);
|
2016-10-29 13:19:59 +03:00
|
|
|
}
|
2019-12-01 16:08:58 +01:00
|
|
|
let trait_path = hir::Path { span: self.span, res, segments: &[] };
|
2016-10-27 05:17:42 +03:00
|
|
|
Type::QPath {
|
2018-06-10 17:40:45 +03:00
|
|
|
name: segment.ident.name.clean(cx),
|
2016-10-27 05:17:42 +03:00
|
|
|
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),
|
2015-01-31 05:51:21 +02:00
|
|
|
}
|
|
|
|
}
|
2018-07-11 23:36:06 +08:00
|
|
|
TyKind::TraitObject(ref bounds, ref lifetime) => {
|
2017-01-24 17:17:06 +02:00
|
|
|
match bounds[0].clean(cx).trait_ {
|
2019-03-13 23:37:02 +00:00
|
|
|
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();
|
2017-01-24 17:17:06 +02:00
|
|
|
if !lifetime.is_elided() {
|
2018-06-14 12:23:46 +01:00
|
|
|
bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
|
2015-05-25 15:06:38 +02:00
|
|
|
}
|
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
|
|
|
}
|
2019-02-28 22:43:53 +00:00
|
|
|
_ => Infer, // shouldn't happen
|
2014-11-20 19:44:49 -05:00
|
|
|
}
|
2014-02-28 17:46:09 -08: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-09-24 13:53:09 -07:00
|
|
|
}
|
2013-08-15 16:28:54 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-14 21:44:23 -04:00
|
|
|
impl<'tcx> Clean<Type> for Ty<'tcx> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Type {
|
2019-04-27 20:33:03 -04:00
|
|
|
debug!("cleaning type: {:?}", self);
|
2019-09-16 19:08:35 +01:00
|
|
|
match self.kind {
|
2018-08-22 01:35:02 +01:00
|
|
|
ty::Never => Never,
|
2018-08-22 01:35:55 +01:00
|
|
|
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),
|
2018-08-22 01:35:02 +01:00
|
|
|
ty::Slice(ty) => Slice(box ty.clean(cx)),
|
|
|
|
ty::Array(ty, n) => {
|
2019-04-03 15:29:31 +02:00
|
|
|
let mut n = cx.tcx.lift(&n).expect("array lift failed");
|
2019-11-30 08:42:56 +13:00
|
|
|
n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
|
2018-01-29 10:32:11 +01:00
|
|
|
let n = print_const(cx, n);
|
2017-08-05 16:11:24 +03:00
|
|
|
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(_) => {
|
2018-08-22 01:35:02 +01:00
|
|
|
let ty = cx.tcx.lift(self).expect("FnPtr lift failed");
|
2017-05-13 17:11:52 +03:00
|
|
|
let sig = ty.fn_sig(cx.tcx);
|
2019-06-27 11:16:59 +02:00
|
|
|
let local_def_id = cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID);
|
2017-05-13 17:11:52 +03:00
|
|
|
BareFunction(box BareFunctionDecl {
|
|
|
|
unsafety: sig.unsafety(),
|
2017-10-16 21:07:26 +02:00
|
|
|
generic_params: Vec::new(),
|
2019-06-27 11:16:59 +02:00
|
|
|
decl: (local_def_id, sig).clean(cx),
|
2017-05-13 17:11:52 +03:00
|
|
|
abi: sig.abi(),
|
|
|
|
})
|
|
|
|
}
|
2018-08-22 01:35:02 +01:00
|
|
|
ty::Adt(def, substs) => {
|
2015-07-20 22:13:36 +03:00
|
|
|
let did = def.did;
|
2016-09-06 01:26:02 +03:00
|
|
|
let kind = match def.adt_kind() {
|
2016-10-01 00:34:00 -04:00
|
|
|
AdtKind::Struct => TypeKind::Struct,
|
|
|
|
AdtKind::Union => TypeKind::Union,
|
|
|
|
AdtKind::Enum => TypeKind::Enum,
|
2014-05-03 02:08:58 -07:00
|
|
|
};
|
2015-12-05 11:58:04 +01:00
|
|
|
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 }
|
2014-05-03 02:08:58 -07:00
|
|
|
}
|
2018-08-22 01:35:29 +01:00
|
|
|
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
|
|
|
}
|
2018-08-22 01:35:02 +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
|
|
|
};
|
|
|
|
|
2018-10-13 19:41:27 +02:00
|
|
|
inline::record_extern_fqn(cx, did, TypeKind::Trait);
|
|
|
|
|
2019-03-13 23:37:02 +00:00
|
|
|
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 {
|
2018-10-13 19:41:27 +02:00
|
|
|
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);
|
2016-11-12 15:46:16 -07:00
|
|
|
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(),
|
2018-10-13 19:41:27 +02:00
|
|
|
},
|
2019-12-22 17:42:04 -05:00
|
|
|
hir::TraitBoundModifier::None,
|
|
|
|
);
|
2019-03-13 23:37:02 +00:00
|
|
|
param_names.push(bound);
|
2018-10-13 19:41:27 +02:00
|
|
|
}
|
2016-11-12 15:46:16 -07:00
|
|
|
|
2018-10-13 19:41:27 +02:00
|
|
|
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) },
|
2018-10-13 19:41:27 +02:00
|
|
|
});
|
|
|
|
}
|
2016-08-04 15:52:57 +03:00
|
|
|
|
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 }
|
2014-12-26 04:36:04 -05:00
|
|
|
}
|
2019-04-26 00:27:33 +01:00
|
|
|
ty::Tuple(ref t) => {
|
|
|
|
Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx))
|
|
|
|
}
|
2014-05-03 02:08:58 -07:00
|
|
|
|
2018-08-22 01:35:02 +01:00
|
|
|
ty::Projection(ref data) => data.clean(cx),
|
2014-12-17 14:16:28 -05:00
|
|
|
|
2019-06-21 12:23:05 +09:00
|
|
|
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())
|
|
|
|
}
|
|
|
|
}
|
2014-05-03 02:08:58 -07:00
|
|
|
|
2018-08-23 13:51:32 -06:00
|
|
|
ty::Opaque(def_id, substs) => {
|
2016-07-22 18:56:22 +03:00
|
|
|
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
|
|
|
|
// by looking up the projections associated with the def_id.
|
2019-03-31 15:32:25 +02:00
|
|
|
let predicates_of = cx.tcx.explicit_predicates_of(def_id);
|
2018-08-23 13:51:32 -06:00
|
|
|
let substs = cx.tcx.lift(&substs).expect("Opaque lift failed");
|
2017-04-24 15:20:46 +03:00
|
|
|
let bounds = predicates_of.instantiate(cx.tcx, substs);
|
2018-03-27 21:26:44 +02:00
|
|
|
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)));
|
2018-03-27 20:59:09 +02:00
|
|
|
return None;
|
2019-12-22 17:42:04 -05:00
|
|
|
} else {
|
|
|
|
return None;
|
|
|
|
};
|
2018-03-27 20:59:09 +02:00
|
|
|
|
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;
|
2018-03-27 20:45:24 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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<_>>();
|
2018-03-27 21:26:44 +02:00
|
|
|
bounds.extend(regions);
|
|
|
|
if !has_sized && !bounds.is_empty() {
|
2018-06-14 12:08:58 +01:00
|
|
|
bounds.insert(0, GenericBound::maybe_sized(cx));
|
2018-03-27 21:26:44 +02:00
|
|
|
}
|
|
|
|
ImplTrait(bounds)
|
2016-07-22 18:56:22 +03:00
|
|
|
}
|
|
|
|
|
2018-08-22 01:35:02 +01:00
|
|
|
ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
|
2014-05-28 22:26:56 -07:00
|
|
|
|
2018-10-22 20:37:56 +02:00
|
|
|
ty::Bound(..) => panic!("Bound"),
|
2018-11-02 18:48:24 +01:00
|
|
|
ty::Placeholder(..) => panic!("Placeholder"),
|
2018-10-03 18:49:27 +02:00
|
|
|
ty::UnnormalizedProjection(..) => panic!("UnnormalizedProjection"),
|
2018-08-22 01:35:02 +01:00
|
|
|
ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
|
|
|
|
ty::Infer(..) => panic!("Infer"),
|
|
|
|
ty::Error => panic!("Error"),
|
2014-05-03 02:08:58 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-13 23:38:33 +00:00
|
|
|
impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
|
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Constant {
|
2019-12-11 14:50:19 +01:00
|
|
|
Constant {
|
|
|
|
type_: self.ty.clean(cx),
|
|
|
|
expr: format!("{}", self),
|
|
|
|
value: None,
|
|
|
|
is_literal: false,
|
|
|
|
}
|
2019-03-13 23:38:33 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-11-29 09:40:33 +01:00
|
|
|
impl Clean<Item> for hir::StructField<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2019-06-27 11:28:14 +02:00
|
|
|
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),
|
2016-02-27 11:34:29 +03:00
|
|
|
attrs: self.attrs.clean(cx),
|
2014-09-06 19:13:40 +03:00
|
|
|
source: self.span.clean(cx),
|
2016-03-25 06:08:11 +00:00
|
|
|
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,
|
2016-04-02 08:17:59 +02:00
|
|
|
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 {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2014-05-23 00:42:33 -07:00
|
|
|
Item {
|
2018-05-26 02:50:15 +03:00
|
|
|
name: Some(self.ident.name).clean(cx),
|
2016-11-20 03:42:54 +02:00
|
|
|
attrs: cx.tcx.get_attrs(self.did).clean(cx),
|
2016-11-29 08:15:16 +02:00
|
|
|
source: cx.tcx.def_span(self.did).clean(cx),
|
2016-03-25 06:08:11 +00:00
|
|
|
visibility: self.vis.clean(cx),
|
2015-08-02 22:52:50 +03:00
|
|
|
stability: get_stability(cx, self.did),
|
2015-12-12 23:01:27 +03:00
|
|
|
deprecation: get_deprecation(cx, self.did),
|
2015-08-02 22:52:50 +03:00
|
|
|
def_id: self.did,
|
2017-04-24 15:20:46 +03:00
|
|
|
inner: StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
|
2014-05-23 00:42:33 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-01 16:08:58 +01:00
|
|
|
impl Clean<Visibility> for hir::Visibility<'_> {
|
2019-09-12 22:32:12 -04:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Visibility {
|
|
|
|
match self.node {
|
2018-07-01 11:05:10 -07:00
|
|
|
hir::VisibilityKind::Public => Visibility::Public,
|
|
|
|
hir::VisibilityKind::Inherited => Visibility::Inherited,
|
|
|
|
hir::VisibilityKind::Crate(_) => Visibility::Crate,
|
|
|
|
hir::VisibilityKind::Restricted { ref path, .. } => {
|
2018-05-12 18:25:09 +01:00
|
|
|
let path = path.clean(cx);
|
2019-04-20 19:36:05 +03:00
|
|
|
let did = register_res(cx, path.res);
|
2018-05-12 18:25:09 +01:00
|
|
|
Visibility::Restricted(did, path)
|
|
|
|
}
|
2019-09-12 22:32:12 -04:00
|
|
|
}
|
2016-03-25 06:08:11 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-12 22:32:12 -04:00
|
|
|
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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2018-08-30 12:10:15 -05:00
|
|
|
Item {
|
|
|
|
name: Some(self.name.clean(cx)),
|
2014-09-06 19:13:40 +03:00
|
|
|
attrs: self.attrs.clean(cx),
|
|
|
|
source: self.whence.clean(cx),
|
2019-06-27 11:28:14 +02:00
|
|
|
def_id: cx.tcx.hir().local_def_id(self.id),
|
2014-09-06 19:13:40 +03:00
|
|
|
visibility: self.vis.clean(cx),
|
2019-07-24 16:18:32 -04:00
|
|
|
stability: cx.stability(self.id).clean(cx),
|
2019-07-24 16:22:48 -04:00
|
|
|
deprecation: cx.deprecation(self.id).clean(cx),
|
2013-08-15 16:28:54 -04:00
|
|
|
inner: StructItem(Struct {
|
|
|
|
struct_type: self.struct_type,
|
2014-09-06 19:13:40 +03:00
|
|
|
generics: self.generics.clean(cx),
|
|
|
|
fields: self.fields.clean(cx),
|
2013-10-13 20:37:43 -07:00
|
|
|
fields_stripped: false,
|
2013-08-15 16:28:54 -04:00
|
|
|
}),
|
2018-08-30 12:10:15 -05:00
|
|
|
}
|
2013-08-15 16:28:54 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 11:43:15 +03:00
|
|
|
impl Clean<Item> for doctree::Union<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2018-08-30 12:10:15 -05:00
|
|
|
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),
|
2019-06-27 11:28:14 +02:00
|
|
|
def_id: cx.tcx.hir().local_def_id(self.id),
|
2016-08-10 21:00:17 +03:00
|
|
|
visibility: self.vis.clean(cx),
|
2019-07-24 16:18:32 -04:00
|
|
|
stability: cx.stability(self.id).clean(cx),
|
2019-07-24 16:22:48 -04:00
|
|
|
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,
|
|
|
|
}),
|
2018-08-30 12:10:15 -05:00
|
|
|
}
|
2016-08-10 21:00:17 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-05 02:37:57 +01:00
|
|
|
impl Clean<VariantStruct> for rustc_hir::VariantData<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> VariantStruct {
|
2013-08-15 16:28:54 -04:00
|
|
|
VariantStruct {
|
|
|
|
struct_type: doctree::struct_type_from_def(self),
|
2015-10-25 18:33:51 +03:00
|
|
|
fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
|
2013-10-13 20:37:43 -07:00
|
|
|
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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2018-08-30 12:10:15 -05:00
|
|
|
Item {
|
|
|
|
name: Some(self.name.clean(cx)),
|
2014-09-06 19:13:40 +03:00
|
|
|
attrs: self.attrs.clean(cx),
|
|
|
|
source: self.whence.clean(cx),
|
2019-06-27 11:28:14 +02:00
|
|
|
def_id: cx.tcx.hir().local_def_id(self.id),
|
2014-09-06 19:13:40 +03:00
|
|
|
visibility: self.vis.clean(cx),
|
2019-07-24 16:18:32 -04:00
|
|
|
stability: cx.stability(self.id).clean(cx),
|
2019-07-24 16:22:48 -04:00
|
|
|
deprecation: cx.deprecation(self.id).clean(cx),
|
2013-08-15 16:28:54 -04:00
|
|
|
inner: EnumItem(Enum {
|
2018-11-01 19:03:38 +01:00
|
|
|
variants: self.variants.iter().map(|v| v.clean(cx)).collect(),
|
2014-09-06 19:13:40 +03:00
|
|
|
generics: self.generics.clean(cx),
|
2013-10-13 20:37:43 -07:00
|
|
|
variants_stripped: false,
|
2013-08-15 16:28:54 -04:00
|
|
|
}),
|
2018-08-30 12:10:15 -05:00
|
|
|
}
|
2013-08-15 16:28:54 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 11:43:15 +03:00
|
|
|
impl Clean<Item> for doctree::Variant<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2013-08-15 16:28:54 -04:00
|
|
|
Item {
|
2014-09-06 19:13:40 +03:00
|
|
|
name: Some(self.name.clean(cx)),
|
|
|
|
attrs: self.attrs.clean(cx),
|
|
|
|
source: self.whence.clean(cx),
|
2019-09-12 22:32:12 -04:00
|
|
|
visibility: Inherited,
|
2019-07-24 16:18:32 -04:00
|
|
|
stability: cx.stability(self.id).clean(cx),
|
2019-07-24 16:22:48 -04:00
|
|
|
deprecation: cx.deprecation(self.id).clean(cx),
|
2019-06-27 11:28:14 +02:00
|
|
|
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 {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2016-09-15 00:51:46 +03:00
|
|
|
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 {
|
2018-12-01 02:47:08 +00:00
|
|
|
name: Some(self.ident.clean(cx)),
|
Use doc comments from 'pub use' statements
Split off from #62855
Currently, rustdoc ignores any doc comments found on 'pub use'
statements. As described in issue #58700, this makes it impossible to
properly document procedural macros. Any doc comments must be written on
the procedural macro definition, which must occur in a dedicated
proc-macro crate. This means that any doc comments or doc tests cannot
reference items defined in re-exporting crate, despite the fact that
such items may be required to use the procedural macro.
To solve this issue, this commit allows doc comments to be written on
'pub use' statements. For consistency, this applies to *all* 'pub use'
statements, not just those importing procedural macros.
When inlining documentation, documentation on 'pub use' statements will
be prepended to the documentation of the inlined item. For example,
the following items:
```rust
mod other_mod {
/// Doc comment from definition
pub struct MyStruct;
}
/// Doc comment from 'pub use'
///
pub use other_mod::MyStruct;
```
will caues the documentation for the re-export of 'MyStruct' to be
rendered as:
```
Doc comment from 'pub use'
Doc comment from definition
```
Note the empty line in the 'pub use' doc comments - because doc comments
are concatenated as-is, this ensure that the doc comments on the
definition start on a new line.
2019-07-27 14:18:50 -04:00
|
|
|
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),
|
2019-09-12 22:32:12 -04:00
|
|
|
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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> VariantKind {
|
2019-03-24 00:06:58 +03:00
|
|
|
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())
|
|
|
|
}
|
2019-03-24 00:06:58 +03:00
|
|
|
hir::VariantData::Unit(..) => VariantKind::CLike,
|
2016-10-01 15:09:27 -04:00
|
|
|
}
|
2015-10-02 00:03:22 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-31 20:15:40 +03:00
|
|
|
impl Clean<Span> for rustc_span::Span {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Span {
|
2018-06-25 01:00:21 +03:00
|
|
|
if self.is_dummy() {
|
2015-07-06 14:13:19 +12:00
|
|
|
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());
|
2013-09-27 15:12:23 -07:00
|
|
|
Span {
|
2017-12-14 08:09:19 +01:00
|
|
|
filename,
|
2013-09-27 15:12:23 -07:00
|
|
|
loline: lo.line,
|
2015-01-17 23:49:08 +00:00
|
|
|
locol: lo.col.to_usize(),
|
2013-09-27 15:12:23 -07:00
|
|
|
hiline: hi.line,
|
2015-01-17 23:49:08 +00:00
|
|
|
hicol: hi.col.to_usize(),
|
2019-05-16 18:31:53 +02:00
|
|
|
original: *self,
|
2013-09-27 15:12:23 -07:00
|
|
|
}
|
2013-08-15 16:28:54 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-01 16:08:58 +01:00
|
|
|
impl Clean<Path> for hir::Path<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Path {
|
2013-08-15 16:28:54 -04:00
|
|
|
Path {
|
2016-12-05 03:51:11 +00:00
|
|
|
global: self.is_global(),
|
2019-04-20 19:36:05 +03:00
|
|
|
res: self.res,
|
2016-12-05 03:51:11 +00:00
|
|
|
segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
|
2013-09-12 15:11:06 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-01 16:08:58 +01:00
|
|
|
impl Clean<GenericArgs> for hir::GenericArgs<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> GenericArgs {
|
2017-07-29 01:13:40 +03:00
|
|
|
if self.parenthesized {
|
2019-05-08 15:57:06 -04:00
|
|
|
let output = self.bindings[0].ty().clean(cx);
|
2018-02-13 11:32:37 +00:00
|
|
|
GenericArgs::Parenthesized {
|
2017-07-29 01:13:40 +03:00
|
|
|
inputs: self.inputs().clean(cx),
|
2019-12-22 17:42:04 -05:00
|
|
|
output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None },
|
2014-11-03 21:52:52 -05:00
|
|
|
}
|
2017-07-29 01:13:40 +03:00
|
|
|
} else {
|
2019-03-13 23:39:56 +00:00
|
|
|
let elide_lifetimes = self.args.iter().all(|arg| match arg {
|
|
|
|
hir::GenericArg::Lifetime(lt) => lt.is_elided(),
|
|
|
|
_ => true,
|
|
|
|
});
|
2018-02-13 11:32:37 +00:00
|
|
|
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(),
|
2017-07-29 01:13:40 +03:00
|
|
|
bindings: self.bindings.clean(cx),
|
2014-11-03 21:52:52 -05:00
|
|
|
}
|
2014-12-16 12:40:43 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-11-03 21:52:52 -05:00
|
|
|
|
2019-12-01 16:08:58 +01:00
|
|
|
impl Clean<PathSegment> for hir::PathSegment<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-01 02:47:08 +00:00
|
|
|
impl Clean<String> for Ident {
|
|
|
|
#[inline]
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> String {
|
2018-12-01 02:47:08 +00:00
|
|
|
self.name.clean(cx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-05-24 11:56:38 -07:00
|
|
|
impl Clean<String> for ast::Name {
|
2018-12-01 02:47:08 +00:00
|
|
|
#[inline]
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, _: &DocContext<'_>) -> String {
|
2015-07-28 18:07:20 +02:00
|
|
|
self.to_string()
|
2014-05-23 00:42:33 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 11:43:15 +03:00
|
|
|
impl Clean<Item> for doctree::Typedef<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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 {
|
2014-09-06 19:13:40 +03:00
|
|
|
name: Some(self.name.clean(cx)),
|
|
|
|
attrs: self.attrs.clean(cx),
|
|
|
|
source: self.whence.clean(cx),
|
2019-06-27 11:28:14 +02:00
|
|
|
def_id: cx.tcx.hir().local_def_id(self.id),
|
2014-09-06 19:13:40 +03:00
|
|
|
visibility: self.vis.clean(cx),
|
2019-07-24 16:18:32 -04:00
|
|
|
stability: cx.stability(self.id).clean(cx),
|
2019-07-24 16:22:48 -04:00
|
|
|
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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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),
|
2019-06-27 11:28:14 +02:00
|
|
|
def_id: cx.tcx.hir().local_def_id(self.id),
|
2018-07-03 19:38:14 +02:00
|
|
|
visibility: self.vis.clean(cx),
|
2019-07-24 16:18:32 -04:00
|
|
|
stability: cx.stability(self.id).clean(cx),
|
2019-07-24 16:22:48 -04:00
|
|
|
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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> BareFunctionDecl {
|
2018-05-03 22:24:50 +09:00
|
|
|
let (generic_params, decl) = enter_impl_trait(cx, || {
|
2019-08-27 13:24:32 +02:00
|
|
|
(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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2014-12-20 00:09:35 -08:00
|
|
|
debug!("cleaning static {}: {:?}", self.name.clean(cx), self);
|
2013-08-15 16:28:54 -04:00
|
|
|
Item {
|
2014-09-06 19:13:40 +03:00
|
|
|
name: Some(self.name.clean(cx)),
|
|
|
|
attrs: self.attrs.clean(cx),
|
|
|
|
source: self.whence.clean(cx),
|
2019-06-27 11:28:14 +02:00
|
|
|
def_id: cx.tcx.hir().local_def_id(self.id),
|
2014-09-06 19:13:40 +03:00
|
|
|
visibility: self.vis.clean(cx),
|
2019-07-24 16:18:32 -04:00
|
|
|
stability: cx.stability(self.id).clean(cx),
|
2019-07-24 16:22:48 -04:00
|
|
|
deprecation: cx.deprecation(self.id).clean(cx),
|
2013-08-15 16:28:54 -04:00
|
|
|
inner: StaticItem(Static {
|
2014-09-06 19:13:40 +03:00
|
|
|
type_: self.type_.clean(cx),
|
2019-12-21 15:29:46 +01:00
|
|
|
mutability: self.mutability,
|
2016-12-21 12:32:59 +02:00
|
|
|
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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2019-12-11 14:50:19 +01:00
|
|
|
let def_id = cx.tcx.hir().local_def_id(self.id);
|
|
|
|
|
2014-10-06 17:41:15 -07:00
|
|
|
Item {
|
|
|
|
name: Some(self.name.clean(cx)),
|
|
|
|
attrs: self.attrs.clean(cx),
|
|
|
|
source: self.whence.clean(cx),
|
2019-12-11 14:50:19 +01:00
|
|
|
def_id,
|
2014-10-06 17:41:15 -07:00
|
|
|
visibility: self.vis.clean(cx),
|
2019-07-24 16:18:32 -04:00
|
|
|
stability: cx.stability(self.id).clean(cx),
|
2019-07-24 16:22:48 -04:00
|
|
|
deprecation: cx.deprecation(self.id).clean(cx),
|
2014-10-06 17:41:15 -07:00
|
|
|
inner: ConstantItem(Constant {
|
|
|
|
type_: self.type_.clean(cx),
|
2016-12-21 12:32:59 +02:00
|
|
|
expr: print_const_expr(cx, self.expr),
|
2019-12-11 14:50:19 +01:00
|
|
|
value: print_evaluated_const(cx, def_id),
|
|
|
|
is_literal: is_literal_expr(cx, self.expr.hir_id),
|
2014-10-06 17:41:15 -07:00
|
|
|
}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-07-14 00:09:46 +03:00
|
|
|
impl Clean<ImplPolarity> for ty::ImplPolarity {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, _: &DocContext<'_>) -> ImplPolarity {
|
2015-01-21 04:35:57 +00:00
|
|
|
match self {
|
2019-07-14 00:09:46 +03:00
|
|
|
&ty::ImplPolarity::Positive |
|
|
|
|
// FIXME: do we want to do something else here?
|
|
|
|
&ty::ImplPolarity::Reservation => ImplPolarity::Positive,
|
|
|
|
&ty::ImplPolarity::Negative => ImplPolarity::Negative,
|
2015-01-21 04:35:57 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 11:43:15 +03:00
|
|
|
impl Clean<Vec<Item>> for doctree::Impl<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Vec<Item> {
|
2015-04-13 16:23:32 -07:00
|
|
|
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<_>>();
|
2019-07-14 00:09:46 +03:00
|
|
|
let def_id = cx.tcx.hir().local_def_id(self.id);
|
2015-04-13 16:23:32 -07:00
|
|
|
|
|
|
|
// 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.
|
2017-08-31 09:19:33 -07:00
|
|
|
if trait_.def_id() == cx.tcx.lang_items().deref_trait() {
|
2016-03-24 06:10:52 +01:00
|
|
|
build_deref_target_impls(cx, &items, &mut ret);
|
2015-04-13 16:23:32 -07:00
|
|
|
}
|
|
|
|
|
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| {
|
2020-02-07 21:33:23 +01:00
|
|
|
cx.tcx.provided_trait_methods(did).map(|meth| meth.ident.to_string()).collect()
|
2019-12-22 17:42:04 -05:00
|
|
|
})
|
|
|
|
.unwrap_or_default();
|
2016-03-24 06:10:52 +01:00
|
|
|
|
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
|
2015-04-13 16:23:32 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 11:43:15 +03:00
|
|
|
impl Clean<Vec<Item>> for doctree::ExternCrate<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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
|
|
|
|
Use doc comments from 'pub use' statements
Split off from #62855
Currently, rustdoc ignores any doc comments found on 'pub use'
statements. As described in issue #58700, this makes it impossible to
properly document procedural macros. Any doc comments must be written on
the procedural macro definition, which must occur in a dedicated
proc-macro crate. This means that any doc comments or doc tests cannot
reference items defined in re-exporting crate, despite the fact that
such items may be required to use the procedural macro.
To solve this issue, this commit allows doc comments to be written on
'pub use' statements. For consistency, this applies to *all* 'pub use'
statements, not just those importing procedural macros.
When inlining documentation, documentation on 'pub use' statements will
be prepended to the documentation of the inlined item. For example,
the following items:
```rust
mod other_mod {
/// Doc comment from definition
pub struct MyStruct;
}
/// Doc comment from 'pub use'
///
pub use other_mod::MyStruct;
```
will caues the documentation for the re-export of 'MyStruct' to be
rendered as:
```
Doc comment from 'pub use'
Doc comment from definition
```
Note the empty line in the 'pub use' doc comments - because doc comments
are concatenated as-is, this ensure that the doc comments on the
definition start on a new line.
2019-07-27 14:18:50 -04:00
|
|
|
if let Some(items) = inline::try_inline(
|
2019-12-22 17:42:04 -05:00
|
|
|
cx,
|
|
|
|
res,
|
|
|
|
self.name,
|
Use doc comments from 'pub use' statements
Split off from #62855
Currently, rustdoc ignores any doc comments found on 'pub use'
statements. As described in issue #58700, this makes it impossible to
properly document procedural macros. Any doc comments must be written on
the procedural macro definition, which must occur in a dedicated
proc-macro crate. This means that any doc comments or doc tests cannot
reference items defined in re-exporting crate, despite the fact that
such items may be required to use the procedural macro.
To solve this issue, this commit allows doc comments to be written on
'pub use' statements. For consistency, this applies to *all* 'pub use'
statements, not just those importing procedural macros.
When inlining documentation, documentation on 'pub use' statements will
be prepended to the documentation of the inlined item. For example,
the following items:
```rust
mod other_mod {
/// Doc comment from definition
pub struct MyStruct;
}
/// Doc comment from 'pub use'
///
pub use other_mod::MyStruct;
```
will caues the documentation for the re-export of 'MyStruct' to be
rendered as:
```
Doc comment from 'pub use'
Doc comment from definition
```
Note the empty line in the 'pub use' doc comments - because doc comments
are concatenated as-is, this ensure that the doc comments on the
definition start on a new line.
2019-07-27 14:18:50 -04:00
|
|
|
Some(rustc::ty::Attributes::Borrowed(self.attrs)),
|
2019-12-22 17:42:04 -05:00
|
|
|
&mut visited,
|
Use doc comments from 'pub use' statements
Split off from #62855
Currently, rustdoc ignores any doc comments found on 'pub use'
statements. As described in issue #58700, this makes it impossible to
properly document procedural macros. Any doc comments must be written on
the procedural macro definition, which must occur in a dedicated
proc-macro crate. This means that any doc comments or doc tests cannot
reference items defined in re-exporting crate, despite the fact that
such items may be required to use the procedural macro.
To solve this issue, this commit allows doc comments to be written on
'pub use' statements. For consistency, this applies to *all* 'pub use'
statements, not just those importing procedural macros.
When inlining documentation, documentation on 'pub use' statements will
be prepended to the documentation of the inlined item. For example,
the following items:
```rust
mod other_mod {
/// Doc comment from definition
pub struct MyStruct;
}
/// Doc comment from 'pub use'
///
pub use other_mod::MyStruct;
```
will caues the documentation for the re-export of 'MyStruct' to be
rendered as:
```
Doc comment from 'pub use'
Doc comment from definition
```
Note the empty line in the 'pub use' doc comments - because doc comments
are concatenated as-is, this ensure that the doc comments on the
definition start on a new line.
2019-07-27 14:18:50 -04:00
|
|
|
) {
|
2019-01-10 20:27:44 -05:00
|
|
|
return items;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vec![Item {
|
2014-12-26 10:55:16 +02:00
|
|
|
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 },
|
2014-12-26 10:55:16 +02:00
|
|
|
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
|
|
|
}]
|
2014-12-26 10:55:16 +02:00
|
|
|
}
|
2013-08-15 16:28:54 -04:00
|
|
|
}
|
|
|
|
|
2019-06-12 11:43:15 +03:00
|
|
|
impl Clean<Vec<Item>> for doctree::Import<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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
|
2014-05-24 11:56:38 -07:00
|
|
|
// forcefully don't inline if this is not public or if the
|
|
|
|
// #[doc(no_inline)] attribute is present.
|
2016-06-07 01:20:12 +01:00
|
|
|
// 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,
|
|
|
|
}
|
|
|
|
});
|
2018-11-08 19:06:16 -06:00
|
|
|
// Also check whether imports were asked to be inlined, in case we're trying to re-export a
|
|
|
|
// crate in Rust 2018+
|
2019-05-08 13:21:18 +10:00
|
|
|
let please_inline = self.attrs.lists(sym::doc).has_word(sym::inline);
|
2016-11-24 06:11:31 +02:00
|
|
|
let path = self.path.clean(cx);
|
|
|
|
let inner = if self.glob {
|
2018-06-15 18:16:43 -05:00
|
|
|
if !denied {
|
2018-10-16 10:44:26 +02:00
|
|
|
let mut visited = FxHashSet::default();
|
2019-04-20 19:36:05 +03:00
|
|
|
if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
|
2018-06-15 18:16:43 -05:00
|
|
|
return items;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-11-25 13:21:19 +02:00
|
|
|
Import::Glob(resolve_use_source(cx, path))
|
2016-11-24 06:11:31 +02:00
|
|
|
} else {
|
|
|
|
let name = self.name;
|
2018-11-08 19:06:16 -06:00
|
|
|
if !please_inline {
|
2019-04-20 19:36:05 +03:00
|
|
|
match path.res {
|
|
|
|
Res::Def(DefKind::Mod, did) => {
|
2019-04-20 18:26:26 +03:00
|
|
|
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;
|
|
|
|
}
|
2018-11-08 19:06:16 -06:00
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
2016-11-24 06:11:31 +02:00
|
|
|
if !denied {
|
2018-10-16 10:44:26 +02:00
|
|
|
let mut visited = FxHashSet::default();
|
Use doc comments from 'pub use' statements
Split off from #62855
Currently, rustdoc ignores any doc comments found on 'pub use'
statements. As described in issue #58700, this makes it impossible to
properly document procedural macros. Any doc comments must be written on
the procedural macro definition, which must occur in a dedicated
proc-macro crate. This means that any doc comments or doc tests cannot
reference items defined in re-exporting crate, despite the fact that
such items may be required to use the procedural macro.
To solve this issue, this commit allows doc comments to be written on
'pub use' statements. For consistency, this applies to *all* 'pub use'
statements, not just those importing procedural macros.
When inlining documentation, documentation on 'pub use' statements will
be prepended to the documentation of the inlined item. For example,
the following items:
```rust
mod other_mod {
/// Doc comment from definition
pub struct MyStruct;
}
/// Doc comment from 'pub use'
///
pub use other_mod::MyStruct;
```
will caues the documentation for the re-export of 'MyStruct' to be
rendered as:
```
Doc comment from 'pub use'
Doc comment from definition
```
Note the empty line in the 'pub use' doc comments - because doc comments
are concatenated as-is, this ensure that the doc comments on the
definition start on a new line.
2019-07-27 14:18:50 -04:00
|
|
|
if let Some(items) = inline::try_inline(
|
2019-12-22 17:42:04 -05:00
|
|
|
cx,
|
|
|
|
path.res,
|
|
|
|
name,
|
Use doc comments from 'pub use' statements
Split off from #62855
Currently, rustdoc ignores any doc comments found on 'pub use'
statements. As described in issue #58700, this makes it impossible to
properly document procedural macros. Any doc comments must be written on
the procedural macro definition, which must occur in a dedicated
proc-macro crate. This means that any doc comments or doc tests cannot
reference items defined in re-exporting crate, despite the fact that
such items may be required to use the procedural macro.
To solve this issue, this commit allows doc comments to be written on
'pub use' statements. For consistency, this applies to *all* 'pub use'
statements, not just those importing procedural macros.
When inlining documentation, documentation on 'pub use' statements will
be prepended to the documentation of the inlined item. For example,
the following items:
```rust
mod other_mod {
/// Doc comment from definition
pub struct MyStruct;
}
/// Doc comment from 'pub use'
///
pub use other_mod::MyStruct;
```
will caues the documentation for the re-export of 'MyStruct' to be
rendered as:
```
Doc comment from 'pub use'
Doc comment from definition
```
Note the empty line in the 'pub use' doc comments - because doc comments
are concatenated as-is, this ensure that the doc comments on the
definition start on a new line.
2019-07-27 14:18:50 -04:00
|
|
|
Some(rustc::ty::Attributes::Borrowed(self.attrs)),
|
2019-12-22 17:42:04 -05:00
|
|
|
&mut visited,
|
Use doc comments from 'pub use' statements
Split off from #62855
Currently, rustdoc ignores any doc comments found on 'pub use'
statements. As described in issue #58700, this makes it impossible to
properly document procedural macros. Any doc comments must be written on
the procedural macro definition, which must occur in a dedicated
proc-macro crate. This means that any doc comments or doc tests cannot
reference items defined in re-exporting crate, despite the fact that
such items may be required to use the procedural macro.
To solve this issue, this commit allows doc comments to be written on
'pub use' statements. For consistency, this applies to *all* 'pub use'
statements, not just those importing procedural macros.
When inlining documentation, documentation on 'pub use' statements will
be prepended to the documentation of the inlined item. For example,
the following items:
```rust
mod other_mod {
/// Doc comment from definition
pub struct MyStruct;
}
/// Doc comment from 'pub use'
///
pub use other_mod::MyStruct;
```
will caues the documentation for the re-export of 'MyStruct' to be
rendered as:
```
Doc comment from 'pub use'
Doc comment from definition
```
Note the empty line in the 'pub use' doc comments - because doc comments
are concatenated as-is, this ensure that the doc comments on the
definition start on a new line.
2019-07-27 14:18:50 -04:00
|
|
|
) {
|
2016-11-24 06:11:31 +02:00
|
|
|
return items;
|
2014-12-26 10:55:16 +02:00
|
|
|
}
|
2014-02-28 17:46:09 -08:00
|
|
|
}
|
2016-11-25 13:21:19 +02:00
|
|
|
Import::Simple(name.clean(cx), resolve_use_source(cx, path))
|
2014-12-26 10:55:16 +02:00
|
|
|
};
|
2018-07-12 22:00:57 +02:00
|
|
|
|
2016-11-24 06:11:31 +02:00
|
|
|
vec![Item {
|
2014-12-26 10:55:16 +02:00
|
|
|
name: None,
|
|
|
|
attrs: self.attrs.clean(cx),
|
|
|
|
source: self.whence.clean(cx),
|
2019-06-27 11:16:59 +02:00
|
|
|
def_id: cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID),
|
2014-12-26 10:55:16 +02:00
|
|
|
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),
|
2016-11-24 06:11:31 +02:00
|
|
|
}]
|
2013-08-15 16:28:54 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 11:43:15 +03:00
|
|
|
impl Clean<Item> for doctree::ForeignItem<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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);
|
2013-09-26 11:57:25 -07:00
|
|
|
ForeignFunctionItem(Function {
|
2018-05-03 22:24:50 +09:00
|
|
|
decl,
|
2018-03-24 14:12:08 +09:00
|
|
|
generics,
|
2018-06-22 17:27:58 -07:00
|
|
|
header: hir::FnHeader {
|
|
|
|
unsafety: hir::Unsafety::Unsafe,
|
2019-06-12 11:43:15 +03:00
|
|
|
abi,
|
2018-06-22 17:27:58 -07:00
|
|
|
constness: hir::Constness::NotConst,
|
|
|
|
asyncness: hir::IsAsync::NotAsync,
|
|
|
|
},
|
2019-03-07 02:44:28 +01:00
|
|
|
all_types,
|
2019-03-07 16:47:40 +01:00
|
|
|
ret_types,
|
2013-09-26 11:57:25 -07:00
|
|
|
})
|
|
|
|
}
|
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,
|
2013-09-26 11:57:25 -07:00
|
|
|
};
|
2018-07-12 22:00:57 +02:00
|
|
|
|
2013-09-26 11:57:25 -07:00
|
|
|
Item {
|
2019-06-12 11:43:15 +03:00
|
|
|
name: Some(self.name.clean(cx)),
|
2014-09-06 19:13:40 +03:00
|
|
|
attrs: self.attrs.clean(cx),
|
2019-06-12 11:43:15 +03:00
|
|
|
source: self.whence.clean(cx),
|
2019-06-27 11:28:14 +02:00
|
|
|
def_id: cx.tcx.hir().local_def_id(self.id),
|
2014-09-06 19:13:40 +03:00
|
|
|
visibility: self.vis.clean(cx),
|
2019-07-24 16:18:32 -04:00
|
|
|
stability: cx.stability(self.id).clean(cx),
|
2019-07-24 16:22:48 -04:00
|
|
|
deprecation: cx.deprecation(self.id).clean(cx),
|
2017-08-06 22:54:09 -07:00
|
|
|
inner,
|
2013-09-26 11:57:25 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-12 11:43:15 +03:00
|
|
|
impl Clean<Item> for doctree::Macro<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2016-08-03 12:55:01 +12:00
|
|
|
let name = self.name.clean(cx);
|
2014-02-16 21:40:26 -08:00
|
|
|
Item {
|
2015-11-26 19:14:36 +01:00
|
|
|
name: Some(name.clone()),
|
2014-09-06 19:13:40 +03:00
|
|
|
attrs: self.attrs.clean(cx),
|
|
|
|
source: self.whence.clean(cx),
|
2019-09-12 22:32:12 -04:00
|
|
|
visibility: Public,
|
2019-07-24 16:18:32 -04:00
|
|
|
stability: cx.stability(self.hid).clean(cx),
|
2019-07-24 16:22:48 -04:00
|
|
|
deprecation: cx.deprecation(self.hid).clean(cx),
|
2016-12-19 14:24:33 -05:00
|
|
|
def_id: self.def_id,
|
2014-02-16 21:40:26 -08:00
|
|
|
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>()
|
|
|
|
),
|
2015-04-13 15:25:40 -07:00
|
|
|
imported_from: self.imported_from.clean(cx),
|
2014-02-16 21:40:26 -08:00
|
|
|
}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2014-06-26 11:37:39 -07:00
|
|
|
|
2019-06-12 11:43:15 +03:00
|
|
|
impl Clean<Item> for doctree::ProcMacro<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, cx: &DocContext<'_>) -> Item {
|
2018-09-25 14:56:43 -05:00
|
|
|
Item {
|
|
|
|
name: Some(self.name.clean(cx)),
|
|
|
|
attrs: self.attrs.clean(cx),
|
|
|
|
source: self.whence.clean(cx),
|
2019-09-12 22:32:12 -04:00
|
|
|
visibility: Public,
|
2019-07-24 16:18:32 -04:00
|
|
|
stability: cx.stability(self.id).clean(cx),
|
2019-07-24 16:22:48 -04:00
|
|
|
deprecation: cx.deprecation(self.id).clean(cx),
|
2019-06-27 11:28:14 +02:00
|
|
|
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) }),
|
2018-09-25 14:56:43 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-26 11:37:39 -07:00
|
|
|
impl Clean<Stability> for attr::Stability {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, _: &DocContext<'_>) -> Stability {
|
2015-05-26 00:41:27 +03:00
|
|
|
Stability {
|
2015-10-13 06:01:31 +03:00
|
|
|
level: stability::StabilityLevel::from_attr_level(&self.level),
|
2018-12-13 23:28:54 -05:00
|
|
|
feature: Some(self.feature.to_string()).filter(|f| !f.is_empty()),
|
2015-10-13 06:01:31 +03:00
|
|
|
since: match self.level {
|
2019-12-22 17:42:04 -05:00
|
|
|
attr::Stable { ref since } => since.to_string(),
|
2018-08-23 10:14:52 +02:00
|
|
|
_ => String::new(),
|
2015-10-13 06:01:31 +03:00
|
|
|
},
|
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()),
|
2018-12-13 23:28:54 -05:00
|
|
|
}),
|
2016-11-13 15:56:23 -05:00
|
|
|
unstable_reason: match self.level {
|
2018-12-13 23:28:54 -05:00
|
|
|
attr::Unstable { reason: Some(ref reason), .. } => Some(reason.to_string()),
|
|
|
|
_ => None,
|
2015-10-13 06:01:31 +03:00
|
|
|
},
|
|
|
|
issue: match self.level {
|
2019-12-22 17:42:04 -05:00
|
|
|
attr::Unstable { issue, .. } => issue,
|
2015-10-13 06:01:31 +03:00
|
|
|
_ => None,
|
2019-12-22 17:42:04 -05:00
|
|
|
},
|
2015-05-26 00:41:27 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-12-12 23:01:27 +03:00
|
|
|
impl Clean<Deprecation> for attr::Deprecation {
|
2018-12-08 20:30:23 +01:00
|
|
|
fn clean(&self, _: &DocContext<'_>) -> Deprecation {
|
2015-12-12 23:01:27 +03:00
|
|
|
Deprecation {
|
2018-12-13 23:28:54 -05:00
|
|
|
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<'_> {
|
2018-12-08 20:30:23 +01:00
|
|
|
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.into_iter().map(|b| b.clean(cx)).collect(),
|
|
|
|
},
|
2015-01-07 16:10:40 -08: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
|
|
|
|
|
|
|
enum SimpleBound {
|
2018-05-28 15:23:16 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
|
2018-06-14 12:08:58 +01: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() {
|
2018-06-14 12:08:58 +01:00
|
|
|
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
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|