rust/src/librustdoc/clean/mod.rs

2365 lines
93 KiB
Rust
Raw Normal View History

2013-08-15 22:28:54 +02:00
//! This module contains the "cleaned" pieces of the AST, and the functions
//! that clean them.
mod auto_trait;
mod blanket_impl;
crate mod cfg;
crate mod inline;
mod simplify;
crate mod types;
crate mod utils;
2020-04-27 19:56:11 +02:00
use rustc_ast as ast;
use rustc_attr as attr;
2019-12-24 05:02:53 +01:00
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir as hir;
use rustc_hir::def::{CtorKind, DefKind, Res};
2020-11-23 03:51:57 +01:00
use rustc_hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
2019-12-22 23:42:04 +01:00
use rustc_index::vec::{Idx, IndexVec};
2020-01-06 23:31:06 +01:00
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
use rustc_middle::bug;
2020-03-29 16:41:09 +02:00
use rustc_middle::middle::resolve_lifetime as rl;
use rustc_middle::ty::fold::TypeFolder;
2020-06-30 23:41:57 +02:00
use rustc_middle::ty::subst::{InternalSubsts, Subst};
2020-03-29 16:41:09 +02:00
use rustc_middle::ty::{self, AdtKind, Lift, Ty, TyCtxt};
use rustc_mir::const_eval::{is_const_fn, is_min_const_fn, is_unstable_const_fn};
use rustc_span::hygiene::{AstPass, MacroKind};
2020-04-19 13:00:18 +02:00
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::{self, ExpnKind};
2019-12-22 23:42:04 +01:00
use rustc_typeck::hir_ty_to_ty;
Generate documentation for auto-trait impls A new section is added to both both struct and trait doc pages. On struct/enum pages, a new 'Auto Trait Implementations' section displays any synthetic implementations for auto traits. Currently, this is only done for Send and Sync. On trait pages, a new 'Auto Implementors' section displays all types which automatically implement the trait. Effectively, this is a list of all public types in the standard library. Synthesized impls for a particular auto trait ('synthetic impls') take into account generic bounds. For example, a type 'struct Foo<T>(T)' will have 'impl<T> Send for Foo<T> where T: Send' generated for it. Manual implementations of auto traits are also taken into account. If we have the following types: 'struct Foo<T>(T)' 'struct Wrapper<T>(Foo<T>)' 'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes this sound somehow Then Wrapper will have the following impl generated: 'impl<T> Send for Wrapper<T>' reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send' to hold Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are taken into account by synthetic impls However, if a type can *never* implement a particular auto trait (e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be generated (in this case, 'impl<T> !Send for MyStruct<T>') All of this means that a user should be able to copy-paste a synthetic impl into their code, without any observable changes in behavior (assuming the rest of the program remains unchanged).
2017-11-22 22:16:55 +01:00
use std::collections::hash_map::Entry;
use std::default::Default;
2019-12-22 23:42:04 +01:00
use std::hash::Hash;
use std::rc::Rc;
2019-12-22 23:42:04 +01:00
use std::{mem, vec};
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-03 00:39:32 +02:00
use crate::core::{self, DocContext, ImplTraitParam};
2019-02-23 08:40:07 +01:00
use crate::doctree;
2019-12-09 17:53:42 +01:00
use utils::*;
crate use utils::{get_auto_trait_and_blanket_impls, krate, register_res};
2019-12-09 17:53:42 +01:00
crate use self::types::FnRetTy::*;
crate use self::types::ItemKind::*;
crate use self::types::SelfTy::*;
crate use self::types::Type::*;
crate use self::types::Visibility::{Inherited, Public};
crate 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 22:16:55 +01:00
crate trait Clean<T> {
fn clean(&self, cx: &mut DocContext<'_>) -> T;
2013-08-15 22:28:54 +02:00
}
impl<T: Clean<U>, U> Clean<Vec<U>> for [T] {
fn clean(&self, cx: &mut DocContext<'_>) -> Vec<U> {
self.iter().map(|x| x.clean(cx)).collect()
}
}
impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> {
fn clean(&self, cx: &mut DocContext<'_>) -> IndexVec<V, U> {
self.iter().map(|x| x.clean(cx)).collect()
}
}
2019-11-28 21:47:10 +01:00
impl<T: Clean<U>, U> Clean<U> for &T {
fn clean(&self, cx: &mut DocContext<'_>) -> U {
2019-11-28 21:47:10 +01:00
(**self).clean(cx)
}
}
impl<T: Clean<U>, U> Clean<U> for Rc<T> {
fn clean(&self, cx: &mut DocContext<'_>) -> U {
(**self).clean(cx)
}
}
2013-08-15 22:28:54 +02:00
impl<T: Clean<U>, U> Clean<Option<U>> for Option<T> {
fn clean(&self, cx: &mut DocContext<'_>) -> Option<U> {
2016-02-28 12:11:13 +01:00
self.as_ref().map(|v| v.clean(cx))
2013-08-15 22:28:54 +02:00
}
}
2015-11-22 20:02:04 +01:00
impl Clean<ExternalCrate> for CrateNum {
fn clean(&self, cx: &mut DocContext<'_>) -> ExternalCrate {
let tcx = cx.tcx;
let root = DefId { krate: *self, index: CRATE_DEF_INDEX };
let krate_span = tcx.def_span(root);
2018-08-18 12:14:09 +02:00
let krate_src = cx.sess().source_map().span_to_filename(krate_span);
// Collect all inner modules which are tagged as implementations of
// primitives.
//
// Note that this loop only searches the top-level items of the crate,
// and this is intentional. If we were to search the entire crate for an
// item tagged with `#[doc(primitive)]` then we would also have to
// search the entirety of external modules for items tagged
// `#[doc(primitive)]`, which is a pretty inefficient process (decoding
// all that metadata unconditionally).
//
// In order to keep the metadata load under control, the
// `#[doc(primitive)]` feature is explicitly designed to only allow the
// primitive tags to show up as the top level items in a crate.
//
// Also note that this does not attempt to deal with modules tagged
// duplicately for the same primitive. This is handled later on when
// rendering by delegating everything to a hash map.
let mut as_primitive = |res: Res| {
if let Res::Def(DefKind::Mod, def_id) = res {
let attrs = cx.tcx.get_attrs(def_id).clean(cx);
let mut prim = None;
for attr in attrs.lists(sym::doc) {
if let Some(v) = attr.value_str() {
if attr.has_name(sym::primitive) {
prim = PrimitiveType::from_symbol(v);
if prim.is_some() {
break;
}
// FIXME: should warn on unknown primitives?
}
}
}
return prim.map(|p| (def_id, p));
}
None
};
let primitives = if root.is_local() {
tcx.hir()
2019-12-22 23:42:04 +01:00
.krate()
2020-02-07 16:43:36 +01:00
.item
2019-12-22 23:42:04 +01:00
.module
.item_ids
.iter()
.filter_map(|&id| {
let item = tcx.hir().item(id);
2019-12-22 23:42:04 +01:00
match item.kind {
hir::ItemKind::Mod(_) => {
as_primitive(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
}
2019-12-22 23:42:04 +01:00
hir::ItemKind::Use(ref path, hir::UseKind::Single)
if item.vis.node.is_pub() =>
{
as_primitive(path.res).map(|(_, prim)| {
2019-12-22 23:42:04 +01:00
// Pretend the primitive is local.
(id.def_id.to_def_id(), prim)
2019-12-22 23:42:04 +01:00
})
}
_ => None,
}
2019-12-22 23:42:04 +01:00
})
.collect()
} else {
tcx.item_children(root).iter().map(|item| item.res).filter_map(as_primitive).collect()
};
let mut as_keyword = |res: Res| {
if let Res::Def(DefKind::Mod, def_id) = res {
let attrs = tcx.get_attrs(def_id).clean(cx);
2018-05-28 21:30:01 +02:00
let mut keyword = None;
for attr in attrs.lists(sym::doc) {
if attr.has_name(sym::keyword) {
if let Some(v) = attr.value_str() {
keyword = Some(v);
break;
2018-05-28 21:30:01 +02:00
}
}
}
return keyword.map(|p| (def_id, p));
2018-05-28 21:30:01 +02:00
}
None
};
let keywords = if root.is_local() {
tcx.hir()
2019-12-22 23:42:04 +01:00
.krate()
2020-02-07 16:43:36 +01:00
.item
2019-12-22 23:42:04 +01:00
.module
.item_ids
.iter()
.filter_map(|&id| {
let item = tcx.hir().item(id);
2019-12-22 23:42:04 +01:00
match item.kind {
hir::ItemKind::Mod(_) => {
as_keyword(Res::Def(DefKind::Mod, id.def_id.to_def_id()))
}
2019-12-22 23:42:04 +01:00
hir::ItemKind::Use(ref path, hir::UseKind::Single)
if item.vis.node.is_pub() =>
{
as_keyword(path.res).map(|(_, prim)| (id.def_id.to_def_id(), prim))
2019-12-22 23:42:04 +01:00
}
_ => None,
2018-05-28 21:30:01 +02:00
}
2019-12-22 23:42:04 +01:00
})
.collect()
2018-05-28 21:30:01 +02:00
} else {
tcx.item_children(root).iter().map(|item| item.res).filter_map(as_keyword).collect()
2018-05-28 21:30:01 +02:00
};
rustdoc: Generate hyperlinks between crates The general idea of hyperlinking between crates is that it should require as little configuration as possible, if any at all. In this vein, there are two separate ways to generate hyperlinks between crates: 1. When you're generating documentation for a crate 'foo' into folder 'doc', then if foo's external crate dependencies already have documented in the folder 'doc', then hyperlinks will be generated. This will work because all documentation is in the same folder, allowing links to work seamlessly both on the web and on the local filesystem browser. The rationale for this use case is a package with multiple libraries/crates that all want to link to one another, and you don't want to have to deal with going to the web. In theory this could be extended to have a RUST_PATH-style searching situtation, but I'm not sure that it would work seamlessly on the web as it does on the local filesystem, so I'm not attempting to explore this case in this pull request. I believe to fully realize this potential rustdoc would have to be acting as a server instead of a static site generator. 2. One of foo's external dependencies has a #[doc(html_root_url = "...")] attribute. This means that all hyperlinks to the dependency will be rooted at this url. This use case encompasses all packages using libstd/libextra. These two crates now have this attribute encoded (currently at the /doc/master url) and will be read by anything which has a dependency on libstd/libextra. This should also work for arbitrary crates in the wild that have online documentation. I don't like how the version is hard-wired into the url, but I think that this may be a case-by-case thing which doesn't end up being too bad in the long run. Closes #9539
2013-10-03 00:39:32 +02:00
ExternalCrate {
name: tcx.crate_name(*self),
src: krate_src,
attrs: tcx.get_attrs(root).clean(cx),
primitives,
2018-05-28 21:30:01 +02:00
keywords,
2013-08-15 22:28:54 +02:00
}
}
}
2019-06-12 10:43:15 +02:00
impl Clean<Item> for doctree::Module<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Item {
let mut items: Vec<Item> = vec![];
2019-06-12 10:43:15 +02:00
items.extend(self.foreigns.iter().map(|x| x.clean(cx)));
items.extend(self.mods.iter().map(|x| x.clean(cx)));
2020-11-22 19:34:06 +01:00
items.extend(self.items.iter().map(|x| x.clean(cx)).flatten());
items.extend(self.macros.iter().map(|x| x.clean(cx)));
// determine if we should display the inner contents or
// the outer `mod` item for the source code.
let span = {
2020-02-22 15:07:05 +01:00
let sm = cx.sess().source_map();
let outer = sm.lookup_char_pos(self.where_outer.lo());
let inner = sm.lookup_char_pos(self.where_inner.lo());
if outer.file.start_pos == inner.file.start_pos {
// mod foo { ... }
self.where_outer
} else {
2018-08-18 12:13:52 +02:00
// mod foo; (and a separate SourceFile for the contents)
self.where_inner
}
};
let what_rustc_thinks = Item::from_hir_id_and_parts(
self.id,
self.name,
ModuleItem(Module { is_crate: self.is_crate, items }),
cx,
);
Item { source: span.clean(cx), ..what_rustc_thinks }
2013-08-15 22:28:54 +02:00
}
}
impl Clean<Attributes> for [ast::Attribute] {
fn clean(&self, cx: &mut DocContext<'_>) -> Attributes {
Attributes::from_ast(cx.sess().diagnostic(), self, None)
2013-08-15 22:28:54 +02:00
}
}
2019-12-01 16:08:58 +01:00
impl Clean<GenericBound> for hir::GenericBound<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
2013-08-15 22:28:54 +02:00
match *self {
2018-06-14 13:23:46 +02:00
hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
let trait_ref = ty::TraitRef::identity(cx.tcx, def_id);
let generic_args = generic_args.clean(cx);
let bindings = match generic_args {
GenericArgs::AngleBracketed { bindings, .. } => bindings,
_ => bug!("clean: parenthesized `GenericBound::LangItemTrait`"),
};
GenericBound::TraitBound(
PolyTrait { trait_: (trait_ref, &*bindings).clean(cx), generic_params: vec![] },
hir::TraitBoundModifier::None,
)
}
2018-06-14 13:23:46 +02:00
hir::GenericBound::Trait(ref t, modifier) => {
GenericBound::TraitBound(t.clean(cx), modifier)
}
2013-08-15 22:28:54 +02:00
}
}
}
impl Clean<Type> for (ty::TraitRef<'_>, &[TypeBinding]) {
fn clean(&self, cx: &mut DocContext<'_>) -> Type {
let (trait_ref, bounds) = *self;
inline::record_extern_fqn(cx, trait_ref.def_id, TypeKind::Trait);
2019-12-22 23:42:04 +01:00
let path = external_path(
cx,
cx.tcx.item_name(trait_ref.def_id),
Some(trait_ref.def_id),
true,
bounds.to_vec(),
2019-12-22 23:42:04 +01:00
trait_ref.substs,
);
debug!("ty::TraitRef\n subst: {:?}\n", trait_ref.substs);
ResolvedPath { path, param_names: None, did: trait_ref.def_id, is_generic: false }
}
}
impl<'tcx> Clean<GenericBound> for ty::TraitRef<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
GenericBound::TraitBound(
PolyTrait { trait_: (*self, &[][..]).clean(cx), generic_params: vec![] },
hir::TraitBoundModifier::None,
)
}
}
impl Clean<GenericBound> for (ty::PolyTraitRef<'_>, &[TypeBinding]) {
fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
let (poly_trait_ref, bounds) = *self;
let poly_trait_ref = poly_trait_ref.lift_to_tcx(cx.tcx).unwrap();
// collect any late bound regions
let late_bound_regions: Vec<_> = cx
.tcx
.collect_referenced_late_bound_regions(&poly_trait_ref)
.into_iter()
.filter_map(|br| match br {
ty::BrNamed(_, name) => {
Some(GenericParamDef { name, kind: GenericParamDefKind::Lifetime })
}
_ => None,
})
.collect();
2018-06-14 13:23:46 +02:00
GenericBound::TraitBound(
PolyTrait {
2020-06-24 23:40:33 +02:00
trait_: (poly_trait_ref.skip_binder(), bounds).clean(cx),
generic_params: late_bound_regions,
},
2019-12-22 23:42:04 +01:00
hir::TraitBoundModifier::None,
)
}
}
impl<'tcx> Clean<GenericBound> for ty::PolyTraitRef<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> GenericBound {
(*self, &[][..]).clean(cx)
}
}
impl<'tcx> Clean<Option<Vec<GenericBound>>> for InternalSubsts<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> Option<Vec<GenericBound>> {
let mut v = Vec::new();
2018-06-14 13:23:46 +02:00
v.extend(self.regions().filter_map(|r| r.clean(cx)).map(GenericBound::Outlives));
2019-12-22 23:42:04 +01:00
v.extend(self.types().map(|t| {
GenericBound::TraitBound(
PolyTrait { trait_: t.clean(cx), generic_params: Vec::new() },
hir::TraitBoundModifier::None,
)
}));
if !v.is_empty() { Some(v) } else { None }
}
}
2015-07-31 09:04:06 +02:00
impl Clean<Lifetime> for hir::Lifetime {
fn clean(&self, cx: &mut DocContext<'_>) -> Lifetime {
2020-04-13 18:52:40 +02:00
let def = cx.tcx.named_region(self.hir_id);
match def {
2020-04-16 22:58:47 +02:00
Some(
rl::Region::EarlyBound(_, node_id, _)
| rl::Region::LateBound(_, node_id, _)
| rl::Region::Free(_, node_id),
) => {
if let Some(lt) = cx.lt_substs.get(&node_id).cloned() {
2020-04-13 18:52:40 +02:00
return lt;
2016-09-01 09:21:12 +02:00
}
}
2020-04-13 18:52:40 +02:00
_ => {}
2016-09-01 09:21:12 +02:00
}
Lifetime(self.name.ident().name)
2013-08-15 22:28:54 +02:00
}
}
2019-12-01 16:08:58 +01:00
impl Clean<Lifetime> for hir::GenericParam<'_> {
fn clean(&self, _: &mut DocContext<'_>) -> Lifetime {
2018-05-26 01:27:54 +02:00
match self.kind {
2018-05-28 14:33:28 +02:00
hir::GenericParamKind::Lifetime { .. } => {
if !self.bounds.is_empty() {
2018-05-28 14:33:28 +02:00
let mut bounds = self.bounds.iter().map(|bound| match bound {
hir::GenericBound::Outlives(lt) => lt,
2018-05-28 14:33:28 +02:00
_ => panic!(),
});
2018-07-29 15:39:51 +02:00
let name = bounds.next().expect("no more bounds").name.ident();
2018-06-09 22:25:33 +02:00
let mut s = format!("{}: {}", self.name.ident(), name);
2018-05-28 14:33:28 +02:00
for bound in bounds {
2018-06-09 22:25:33 +02:00
s.push_str(&format!(" + {}", bound.name.ident()));
2018-05-26 01:27:54 +02:00
}
Lifetime(Symbol::intern(&s))
2018-05-26 01:27:54 +02:00
} else {
Lifetime(self.name.ident().name)
2018-05-26 01:27:54 +02:00
}
}
2018-05-26 01:27:54 +02:00
_ => panic!(),
}
}
}
impl Clean<Constant> for hir::ConstArg {
fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
Constant {
type_: cx
.tcx
.type_of(cx.tcx.hir().body_owner_def_id(self.value.body).to_def_id())
.clean(cx),
2021-02-11 20:37:36 +01:00
expr: print_const_expr(cx.tcx, self.value.body),
value: None,
is_literal: is_literal_expr(cx, self.value.body.hir_id),
}
}
}
2019-06-11 11:50:17 +02:00
impl Clean<Lifetime> for ty::GenericParamDef {
fn clean(&self, _cx: &mut DocContext<'_>) -> Lifetime {
Lifetime(self.name)
}
}
impl Clean<Option<Lifetime>> for ty::RegionKind {
fn clean(&self, _cx: &mut DocContext<'_>) -> Option<Lifetime> {
match *self {
ty::ReStatic => Some(Lifetime::statik()),
ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name) }) => {
Some(Lifetime(name))
}
ty::ReEarlyBound(ref data) => Some(Lifetime(data.name)),
2019-12-22 23:42:04 +01:00
ty::ReLateBound(..)
| ty::ReFree(..)
| ty::ReVar(..)
| ty::RePlaceholder(..)
| ty::ReEmpty(_)
2019-12-22 23:42:04 +01:00
| ty::ReErased => {
debug!("cannot clean region {:?}", self);
None
}
}
}
}
2019-12-01 16:08:58 +01:00
impl Clean<WherePredicate> for hir::WherePredicate<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
2014-12-03 00:03:02 +01:00
match *self {
2019-12-22 23:42:04 +01:00
hir::WherePredicate::BoundPredicate(ref wbp) => WherePredicate::BoundPredicate {
ty: wbp.bounded_ty.clean(cx),
bounds: wbp.bounds.clean(cx),
},
2019-12-22 23:42:04 +01:00
hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
lifetime: wrp.lifetime.clean(cx),
bounds: wrp.bounds.clean(cx),
},
hir::WherePredicate::EqPredicate(ref wrp) => {
2019-12-22 23:42:04 +01:00
WherePredicate::EqPredicate { lhs: wrp.lhs_ty.clean(cx), rhs: wrp.rhs_ty.clean(cx) }
2014-12-03 00:03:02 +01:00
}
}
}
}
impl<'a> Clean<Option<WherePredicate>> for ty::Predicate<'a> {
fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
2021-01-07 17:20:28 +01:00
let bound_predicate = self.kind();
2020-12-17 04:36:14 +01:00
match bound_predicate.skip_binder() {
2021-01-07 17:20:28 +01:00
ty::PredicateKind::Trait(pred, _) => Some(bound_predicate.rebind(pred).clean(cx)),
ty::PredicateKind::RegionOutlives(pred) => pred.clean(cx),
ty::PredicateKind::TypeOutlives(pred) => pred.clean(cx),
ty::PredicateKind::Projection(pred) => Some(pred.clean(cx)),
ty::PredicateKind::Subtype(..)
| ty::PredicateKind::WellFormed(..)
| ty::PredicateKind::ObjectSafe(..)
| ty::PredicateKind::ClosureKind(..)
| ty::PredicateKind::ConstEvaluatable(..)
| ty::PredicateKind::ConstEquate(..)
| ty::PredicateKind::TypeWellFormedFromEnv(..) => panic!("not user writable"),
}
}
}
impl<'a> Clean<WherePredicate> for ty::PolyTraitPredicate<'a> {
fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
let poly_trait_ref = self.map_bound(|pred| pred.trait_ref);
WherePredicate::BoundPredicate {
ty: poly_trait_ref.skip_binder().self_ty().clean(cx),
bounds: vec![poly_trait_ref.clean(cx)],
}
}
}
2019-12-22 23:42:04 +01:00
impl<'tcx> Clean<Option<WherePredicate>>
2020-07-18 18:46:30 +02:00
for ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>
2019-12-22 23:42:04 +01:00
{
fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
2020-07-18 18:46:30 +02:00
let ty::OutlivesPredicate(a, b) = self;
if let (ty::ReEmpty(_), ty::ReEmpty(_)) = (a, b) {
return None;
}
Some(WherePredicate::RegionPredicate {
2018-07-29 15:39:51 +02:00
lifetime: a.clean(cx).expect("failed to clean lifetime"),
2019-12-22 23:42:04 +01:00
bounds: vec![GenericBound::Outlives(b.clean(cx).expect("failed to clean bounds"))],
})
}
}
2020-07-18 18:46:30 +02:00
impl<'tcx> Clean<Option<WherePredicate>> for ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>> {
fn clean(&self, cx: &mut DocContext<'_>) -> Option<WherePredicate> {
2020-07-18 18:46:30 +02:00
let ty::OutlivesPredicate(ty, lt) = self;
if let ty::ReEmpty(_) = lt {
return None;
}
Some(WherePredicate::BoundPredicate {
ty: ty.clean(cx),
2019-12-22 23:42:04 +01:00
bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))],
})
}
}
2020-07-18 18:46:30 +02:00
impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> WherePredicate {
2020-07-18 18:46:30 +02:00
let ty::ProjectionPredicate { projection_ty, ty } = self;
WherePredicate::EqPredicate { lhs: projection_ty.clean(cx), rhs: ty.clean(cx) }
}
}
impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> Type {
2019-12-08 23:02:33 +01:00
let lifted = self.lift_to_tcx(cx.tcx).unwrap();
let trait_ = match lifted.trait_ref(cx.tcx).clean(cx) {
GenericBound::TraitBound(t, _) => t.trait_,
GenericBound::Outlives(_) => panic!("cleaning a trait got a lifetime"),
};
Type::QPath {
name: cx.tcx.associated_item(self.item_def_id).ident.name,
self_type: box self.self_ty().clean(cx),
2019-12-22 23:42:04 +01:00
trait_: box trait_,
}
}
}
impl Clean<GenericParamDef> for ty::GenericParamDef {
fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
let (name, kind) = match self.kind {
ty::GenericParamDefKind::Lifetime => (self.name, GenericParamDefKind::Lifetime),
ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
2019-12-22 23:42:04 +01:00
let default =
if has_default { Some(cx.tcx.type_of(self.def_id).clean(cx)) } else { None };
(
self.name,
2019-12-22 23:42:04 +01:00
GenericParamDefKind::Type {
did: self.def_id,
bounds: vec![], // These are filled in from the where-clauses.
default,
synthetic,
},
)
}
2019-12-22 23:42:04 +01:00
ty::GenericParamDefKind::Const { .. } => (
self.name,
2019-12-22 23:42:04 +01:00
GenericParamDefKind::Const {
did: self.def_id,
ty: cx.tcx.type_of(self.def_id).clean(cx),
2019-12-22 23:42:04 +01:00
},
),
};
2019-12-22 23:42:04 +01:00
GenericParamDef { name, kind }
2018-03-24 03:03:06 +01:00
}
}
2019-12-01 16:08:58 +01:00
impl Clean<GenericParamDef> for hir::GenericParam<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> GenericParamDef {
let (name, kind) = match self.kind {
2018-05-28 14:33:28 +02:00
hir::GenericParamKind::Lifetime { .. } => {
let name = if !self.bounds.is_empty() {
2018-05-28 14:33:28 +02:00
let mut bounds = self.bounds.iter().map(|bound| match bound {
hir::GenericBound::Outlives(lt) => lt,
2018-05-28 14:33:28 +02:00
_ => panic!(),
});
2018-07-29 15:39:51 +02:00
let name = bounds.next().expect("no more bounds").name.ident();
2018-06-27 23:12:17 +02:00
let mut s = format!("{}: {}", self.name.ident(), name);
2018-05-28 14:33:28 +02:00
for bound in bounds {
2018-06-27 23:12:17 +02:00
s.push_str(&format!(" + {}", bound.name.ident()));
}
Symbol::intern(&s)
} else {
self.name.ident().name
};
(name, GenericParamDefKind::Lifetime)
}
2019-12-22 23:42:04 +01:00
hir::GenericParamKind::Type { ref default, synthetic } => (
self.name.ident().name,
2019-12-22 23:42:04 +01:00
GenericParamDefKind::Type {
did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(),
2018-05-28 14:33:28 +02:00
bounds: self.bounds.clean(cx),
default: default.clean(cx),
synthetic,
2019-12-22 23:42:04 +01:00
},
),
hir::GenericParamKind::Const { ref ty, default: _ } => (
self.name.ident().name,
2019-12-22 23:42:04 +01:00
GenericParamDefKind::Const {
did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(),
ty: ty.clean(cx),
// FIXME(const_generics_defaults): add `default` field here for docs
2019-12-22 23:42:04 +01:00
},
),
};
2019-12-22 23:42:04 +01:00
GenericParamDef { name, kind }
}
}
2019-12-01 16:08:58 +01:00
impl Clean<Generics> for hir::Generics<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Generics {
// Synthetic type-parameters are inserted after normal ones.
// In order for normal parameters to be able to refer to synthetic ones,
// scans them first.
2019-12-01 16:08:58 +01:00
fn is_impl_trait(param: &hir::GenericParam<'_>) -> bool {
2018-05-26 01:27:54 +02:00
match param.kind {
hir::GenericParamKind::Type { synthetic, .. } => {
synthetic == Some(hir::SyntheticTyParamKind::ImplTrait)
}
_ => false,
}
}
/// This can happen for `async fn`, e.g. `async fn f<'_>(&'_ self)`.
///
/// See [`lifetime_to_generic_param`] in [`rustc_ast_lowering`] for more information.
///
/// [`lifetime_to_generic_param`]: rustc_ast_lowering::LoweringContext::lifetime_to_generic_param
fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
matches!(
param.kind,
hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided }
)
}
2019-12-22 23:42:04 +01:00
let impl_trait_params = self
.params
.iter()
.filter(|param| is_impl_trait(param))
.map(|param| {
let param: GenericParamDef = param.clean(cx);
match param.kind {
GenericParamDefKind::Lifetime => unreachable!(),
GenericParamDefKind::Type { did, ref bounds, .. } => {
cx.impl_trait_bounds.insert(did.into(), bounds.clone());
}
GenericParamDefKind::Const { .. } => unreachable!(),
}
param
})
.collect::<Vec<_>>();
2018-05-03 15:24:50 +02:00
let mut params = Vec::with_capacity(self.params.len());
for p in self.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) {
2018-05-03 15:24:50 +02:00
let p = p.clean(cx);
params.push(p);
}
params.extend(impl_trait_params);
2019-12-22 23:42:04 +01:00
let mut generics =
Generics { params, where_predicates: self.where_clause.predicates.clean(cx) };
// Some duplicates are generated for ?Sized bounds between type params and where
// predicates. The point in here is to move the bounds definitions from type params
// to where predicates when such cases occur.
for where_pred in &mut generics.where_predicates {
match *where_pred {
WherePredicate::BoundPredicate { ty: Generic(ref name), ref mut bounds } => {
if bounds.is_empty() {
for param in &mut generics.params {
match param.kind {
GenericParamDefKind::Lifetime => {}
GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
if &param.name == name {
mem::swap(bounds, ty_bounds);
2019-12-22 23:42:04 +01:00
break;
}
}
GenericParamDefKind::Const { .. } => {}
}
}
}
}
_ => continue,
}
2013-08-15 22:28:54 +02:00
}
generics
2013-08-15 22:28:54 +02:00
}
}
impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics, ty::GenericPredicates<'tcx>) {
fn clean(&self, cx: &mut DocContext<'_>) -> Generics {
use self::WherePredicate as WP;
use std::collections::BTreeMap;
let (gens, preds) = *self;
// Don't populate `cx.impl_trait_bounds` before `clean`ning `where` clauses,
// since `Clean for ty::Predicate` would consume them.
let mut impl_trait = BTreeMap::<ImplTraitParam, Vec<GenericBound>>::default();
// Bounds in the type_params and lifetimes fields are repeated in the
// predicates field (see rustc_typeck::collect::ty_generics), so remove
// them.
2020-07-31 23:51:19 +02:00
let stripped_params = gens
2019-12-22 23:42:04 +01:00
.params
.iter()
.filter_map(|param| match param.kind {
2020-07-31 23:51:19 +02:00
ty::GenericParamDefKind::Lifetime => Some(param.clean(cx)),
ty::GenericParamDefKind::Type { synthetic, .. } => {
if param.name == kw::SelfUpper {
assert_eq!(param.index, 0);
return None;
}
if synthetic == Some(hir::SyntheticTyParamKind::ImplTrait) {
impl_trait.insert(param.index.into(), vec![]);
return None;
}
Some(param.clean(cx))
}
2020-07-31 23:51:19 +02:00
ty::GenericParamDefKind::Const { .. } => Some(param.clean(cx)),
2019-12-22 23:42:04 +01:00
})
.collect::<Vec<GenericParamDef>>();
2019-07-08 13:42:45 +02:00
// param index -> [(DefId of trait, associated type name, type)]
let mut impl_trait_proj = FxHashMap::<u32, Vec<(DefId, Symbol, Ty<'tcx>)>>::default();
2019-12-22 23:42:04 +01:00
let where_predicates = preds
.predicates
.iter()
.flat_map(|(p, _)| {
2019-07-08 13:42:45 +02:00
let mut projection = None;
let param_idx = (|| {
2021-01-07 17:20:28 +01:00
let bound_p = p.kind();
2020-12-17 04:36:14 +01:00
match bound_p.skip_binder() {
2021-01-07 17:20:28 +01:00
ty::PredicateKind::Trait(pred, _constness) => {
if let ty::Param(param) = pred.self_ty().kind() {
2020-06-19 10:05:05 +02:00
return Some(param.index);
}
}
2021-01-07 17:20:28 +01:00
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
if let ty::Param(param) = ty.kind() {
2020-06-19 10:05:05 +02:00
return Some(param.index);
}
}
2021-01-07 17:20:28 +01:00
ty::PredicateKind::Projection(p) => {
if let ty::Param(param) = p.projection_ty.self_ty().kind() {
2020-12-17 04:36:14 +01:00
projection = Some(bound_p.rebind(p));
2020-06-19 10:05:05 +02:00
return Some(param.index);
}
}
2020-06-19 10:05:05 +02:00
_ => (),
}
None
})();
if let Some(param_idx) = param_idx {
if let Some(b) = impl_trait.get_mut(&param_idx.into()) {
let p = p.clean(cx)?;
b.extend(
p.get_bounds()
.into_iter()
.flatten()
.cloned()
2019-12-22 23:42:04 +01:00
.filter(|b| !b.is_sized_bound(cx)),
);
2019-07-08 13:42:45 +02: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)))
{
impl_trait_proj
.entry(param_idx)
.or_default()
.push((trait_did, name, rhs));
}
return None;
}
}
Some(p)
})
.collect::<Vec<_>>();
for (param, mut bounds) in impl_trait {
// Move trait bounds to the front.
bounds.sort_by_key(|b| !matches!(b, GenericBound::TraitBound(..)));
2019-07-08 13:42:45 +02: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 {
let rhs = rhs.clean(cx);
simplify::merge_bounds(cx, &mut bounds, trait_did, name, &rhs);
2019-07-08 13:42:45 +02:00
}
}
} else {
unreachable!();
}
cx.impl_trait_bounds.insert(param, bounds);
2019-07-08 13:42:45 +02:00
}
// Now that `cx.impl_trait_bounds` is populated, we can process
// remaining predicates which could contain `impl Trait`.
2019-12-22 23:42:04 +01:00
let mut where_predicates =
where_predicates.into_iter().flat_map(|p| p.clean(cx)).collect::<Vec<_>>();
2020-09-12 13:27:57 +02:00
// Type parameters have a Sized bound by default unless removed with
// ?Sized. Scan through the predicates and mark any type parameter with
// a Sized bound, removing the bounds as we find them.
//
// Note that associated types also have a sized bound by default, but we
2015-05-06 01:49:07 +02:00
// don't actually know the set of associated types right here so that's
// handled in cleaning associated types
let mut sized_params = FxHashSet::default();
2019-12-22 23:42:04 +01: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)) {
2020-12-29 19:33:48 +01:00
sized_params.insert(*g);
2019-12-22 23:42:04 +01:00
false
} else {
true
}
}
2019-12-22 23:42:04 +01:00
_ => true,
});
// Run through the type parameters again and insert a ?Sized
// unbound for any we didn't find to be Sized.
2020-07-31 23:51:19 +02:00
for tp in &stripped_params {
if matches!(tp.kind, types::GenericParamDefKind::Type { .. })
&& !sized_params.contains(&tp.name)
{
where_predicates.push(WP::BoundPredicate {
2020-12-29 19:33:48 +01:00
ty: Type::Generic(tp.name),
bounds: vec![GenericBound::maybe_sized(cx)],
})
}
}
// It would be nice to collect all of the bounds on a type and recombine
// them if possible, to avoid e.g., `where T: Foo, T: Bar, T: Sized, T: 'a`
// and instead see `where T: Foo + Bar + Sized + 'a`
Generics {
2020-07-31 23:51:19 +02:00
params: stripped_params,
where_predicates: simplify::where_clauses(cx, where_predicates),
}
}
}
2020-11-23 03:20:08 +01:00
fn clean_fn_or_proc_macro(
item: &hir::Item<'_>,
sig: &'a hir::FnSig<'a>,
generics: &'a hir::Generics<'a>,
body_id: hir::BodyId,
name: &mut Symbol,
cx: &mut DocContext<'_>,
2020-11-23 03:20:08 +01:00
) -> ItemKind {
2021-01-24 13:17:54 +01:00
let attrs = cx.tcx.hir().attrs(item.hir_id());
let macro_kind = attrs.iter().find_map(|a| {
2020-11-23 03:20:08 +01:00
if a.has_name(sym::proc_macro) {
Some(MacroKind::Bang)
} else if a.has_name(sym::proc_macro_derive) {
Some(MacroKind::Derive)
} else if a.has_name(sym::proc_macro_attribute) {
Some(MacroKind::Attr)
} else {
None
}
});
match macro_kind {
Some(kind) => {
if kind == MacroKind::Derive {
2021-01-24 13:17:54 +01:00
*name = attrs
2020-11-23 03:20:08 +01:00
.lists(sym::proc_macro_derive)
.find_map(|mi| mi.ident())
.expect("proc-macro derives require a name")
.name;
}
let mut helpers = Vec::new();
2021-01-24 13:17:54 +01:00
for mi in attrs.lists(sym::proc_macro_derive) {
2020-11-23 03:20:08 +01:00
if !mi.has_name(sym::attributes) {
continue;
}
if let Some(list) = mi.meta_item_list() {
for inner_mi in list {
if let Some(ident) = inner_mi.ident() {
helpers.push(ident.name);
}
}
}
}
ProcMacroItem(ProcMacro { kind, helpers })
2020-11-23 03:20:08 +01:00
}
None => {
let mut func = (sig, generics, body_id).clean(cx);
let def_id = item.def_id.to_def_id();
2020-11-23 03:20:08 +01:00
func.header.constness =
if is_const_fn(cx.tcx, def_id) && is_unstable_const_fn(cx.tcx, def_id).is_none() {
hir::Constness::Const
} else {
hir::Constness::NotConst
};
FunctionItem(func)
}
}
}
impl<'a> Clean<Function> for (&'a hir::FnSig<'a>, &'a hir::Generics<'a>, hir::BodyId) {
fn clean(&self, cx: &mut DocContext<'_>) -> Function {
2019-12-22 23:42:04 +01:00
let (generics, decl) =
enter_impl_trait(cx, |cx| (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx)));
Function { decl, generics, header: self.0.header }
2013-08-15 22:28:54 +02:00
}
}
2020-04-19 13:00:18 +02:00
impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], &'a [Ident]) {
fn clean(&self, cx: &mut DocContext<'_>) -> Arguments {
Arguments {
2019-12-22 23:42:04 +01:00
values: self
.0
.iter()
.enumerate()
.map(|(i, ty)| {
let mut name = self.1.get(i).map_or(kw::Empty, |ident| ident.name);
2019-12-22 23:42:04 +01:00
if name.is_empty() {
name = kw::Underscore;
2019-12-22 23:42:04 +01:00
}
Argument { name, type_: ty.clean(cx) }
})
.collect(),
}
}
}
2019-12-01 16:08:58 +01:00
impl<'a> Clean<Arguments> for (&'a [hir::Ty<'a>], hir::BodyId) {
fn clean(&self, cx: &mut DocContext<'_>) -> Arguments {
let body = cx.tcx.hir().body(self.1);
Arguments {
2019-12-22 23:42:04 +01:00
values: self
.0
.iter()
.enumerate()
.map(|(i, ty)| Argument {
name: name_from_pat(&body.params[i].pat),
type_: ty.clean(cx),
2019-12-22 23:42:04 +01:00
})
.collect(),
}
}
}
2019-12-01 16:08:58 +01:00
impl<'a, A: Copy> Clean<FnDecl> for (&'a hir::FnDecl<'a>, A)
2019-12-22 23:42:04 +01:00
where
2019-12-01 16:08:58 +01:00
(&'a [hir::Ty<'a>], A): Clean<Arguments>,
{
fn clean(&self, cx: &mut DocContext<'_>) -> FnDecl {
2013-08-15 22:28:54 +02:00
FnDecl {
inputs: (self.0.inputs, self.1).clean(cx),
output: self.0.output.clean(cx),
c_variadic: self.0.c_variadic,
attrs: Attributes::default(),
2013-08-15 22:28:54 +02:00
}
}
}
2019-06-11 11:50:17 +02:00
impl<'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
fn clean(&self, cx: &mut DocContext<'_>) -> FnDecl {
let (did, sig) = *self;
let mut names = if did.is_local() { &[] } else { cx.tcx.fn_arg_names(did) }.iter();
2018-03-23 14:06:28 +01:00
FnDecl {
output: Return(sig.skip_binder().output().clean(cx)),
attrs: Attributes::default(),
c_variadic: sig.skip_binder().c_variadic,
inputs: Arguments {
2019-12-22 23:42:04 +01:00
values: sig
.skip_binder()
.inputs()
.iter()
.map(|t| Argument {
type_: t.clean(cx),
name: names.next().map_or(kw::Empty, |i| i.name),
2019-12-22 23:42:04 +01:00
})
.collect(),
},
}
}
}
2020-02-15 04:10:59 +01:00
impl Clean<FnRetTy> for hir::FnRetTy<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> FnRetTy {
2013-08-15 22:28:54 +02: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 22:28:54 +02:00
}
}
}
impl Clean<bool> for hir::IsAuto {
fn clean(&self, _: &mut DocContext<'_>) -> bool {
match *self {
hir::IsAuto::Yes => true,
hir::IsAuto::No => false,
}
}
}
2019-12-01 16:08:58 +01:00
impl Clean<Type> for hir::TraitRef<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Type {
let path = self.path.clean(cx);
resolve_type(cx, path, self.hir_ref_id)
2013-08-15 22:28:54 +02:00
}
}
2019-12-01 16:08:58 +01:00
impl Clean<PolyTrait> for hir::PolyTraitRef<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> PolyTrait {
PolyTrait {
trait_: self.trait_ref.clean(cx),
2019-12-22 23:42:04 +01:00
generic_params: self.bound_generic_params.clean(cx),
}
2014-11-07 12:53:45 +01:00
}
}
impl Clean<TypeKind> for hir::def::DefKind {
fn clean(&self, _: &mut DocContext<'_>) -> TypeKind {
(*self).into()
}
}
2019-11-28 21:47:10 +01:00
impl Clean<Item> for hir::TraitItem<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Item {
let local_did = self.def_id.to_def_id();
cx.with_param_env(local_did, |cx| {
let inner = match self.kind {
hir::TraitItemKind::Const(ref ty, default) => {
2021-02-11 20:37:36 +01:00
AssocConstItem(ty.clean(cx), default.map(|e| print_const_expr(cx.tcx, e)))
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
let mut m = (sig, &self.generics, body).clean(cx);
if m.header.constness == hir::Constness::Const
&& is_unstable_const_fn(cx.tcx, local_did).is_some()
{
m.header.constness = hir::Constness::NotConst;
}
MethodItem(m, None)
}
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Required(ref names)) => {
let (generics, decl) = enter_impl_trait(cx, |cx| {
(self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
});
let mut t = Function { header: sig.header, decl, generics };
if t.header.constness == hir::Constness::Const
&& is_unstable_const_fn(cx.tcx, local_did).is_some()
{
t.header.constness = hir::Constness::NotConst;
}
TyMethodItem(t)
}
hir::TraitItemKind::Type(ref bounds, ref default) => {
AssocTypeItem(bounds.clean(cx), default.clean(cx))
}
};
let what_rustc_thinks =
Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx);
// Trait items always inherit the trait's visibility -- we don't want to show `pub`.
Item { visibility: Inherited, ..what_rustc_thinks }
})
}
}
2019-11-28 22:16:44 +01:00
impl Clean<Item> for hir::ImplItem<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Item {
let local_did = self.def_id.to_def_id();
cx.with_param_env(local_did, |cx| {
let inner = match self.kind {
hir::ImplItemKind::Const(ref ty, expr) => {
2021-02-11 20:37:36 +01:00
AssocConstItem(ty.clean(cx), Some(print_const_expr(cx.tcx, expr)))
}
hir::ImplItemKind::Fn(ref sig, body) => {
let mut m = (sig, &self.generics, body).clean(cx);
if m.header.constness == hir::Constness::Const
&& is_unstable_const_fn(cx.tcx, local_did).is_some()
{
m.header.constness = hir::Constness::NotConst;
}
MethodItem(m, Some(self.defaultness))
}
hir::ImplItemKind::TyAlias(ref hir_ty) => {
let type_ = hir_ty.clean(cx);
let item_type = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
2021-01-03 22:08:21 +01:00
TypedefItem(
Typedef {
type_,
generics: Generics::default(),
item_type: Some(item_type),
},
true,
)
}
};
let what_rustc_thinks =
Item::from_def_id_and_parts(local_did, Some(self.ident.name), inner, cx);
let parent_item = cx.tcx.hir().expect_item(cx.tcx.hir().get_parent_item(self.hir_id()));
if let hir::ItemKind::Impl(impl_) = &parent_item.kind {
if impl_.of_trait.is_some() {
// Trait impl items always inherit the impl's visibility --
// we don't want to show `pub`.
Item { visibility: Inherited, ..what_rustc_thinks }
} else {
what_rustc_thinks
}
} else {
panic!("found impl item with non-impl parent {:?}", parent_item);
}
})
2013-08-15 22:28:54 +02:00
}
}
2019-06-11 11:50:17 +02:00
impl Clean<Item> for ty::AssocItem {
fn clean(&self, cx: &mut DocContext<'_>) -> Item {
let tcx = cx.tcx;
let kind = match self.kind {
ty::AssocKind::Const => {
let ty = tcx.type_of(self.def_id);
let default = if self.defaultness.has_value() {
Some(inline::print_inlined_const(cx, self.def_id))
} else {
None
};
AssocConstItem(ty.clean(cx), default)
2016-05-08 20:19:29 +02:00
}
ty::AssocKind::Fn => {
2019-12-22 23:42:04 +01:00
let generics =
(tcx.generics_of(self.def_id), tcx.explicit_predicates_of(self.def_id))
2019-12-22 23:42:04 +01:00
.clean(cx);
let sig = tcx.fn_sig(self.def_id);
let mut decl = (self.def_id, sig).clean(cx);
if self.fn_has_self_parameter {
let self_ty = match self.container {
ty::ImplContainer(def_id) => tcx.type_of(def_id),
ty::TraitContainer(_) => tcx.types.self_param,
};
2020-06-24 23:40:33 +02:00
let self_arg_ty = sig.input(0).skip_binder();
if self_arg_ty == self_ty {
decl.inputs.values[0].type_ = Generic(kw::SelfUpper);
} else if let ty::Ref(_, ty, _) = *self_arg_ty.kind() {
if ty == self_ty {
match decl.inputs.values[0].type_ {
2019-12-22 23:42:04 +01:00
BorrowedRef { ref mut type_, .. } => {
**type_ = Generic(kw::SelfUpper)
}
_ => unreachable!(),
}
}
}
}
let provided = match self.container {
ty::ImplContainer(_) => true,
2019-12-22 23:42:04 +01:00
ty::TraitContainer(_) => self.defaultness.has_value(),
};
if provided {
let constness = if is_min_const_fn(tcx, self.def_id) {
hir::Constness::Const
} else {
hir::Constness::NotConst
};
let asyncness = tcx.asyncness(self.def_id);
let defaultness = match self.container {
ty::ImplContainer(_) => Some(self.defaultness),
ty::TraitContainer(_) => None,
};
MethodItem(
Function {
generics,
decl,
header: hir::FnHeader {
unsafety: sig.unsafety(),
abi: sig.abi(),
constness,
asyncness,
},
},
defaultness,
)
} else {
TyMethodItem(Function {
generics,
decl,
header: hir::FnHeader {
unsafety: sig.unsafety(),
abi: sig.abi(),
constness: hir::Constness::NotConst,
asyncness: hir::IsAsync::NotAsync,
},
})
2016-05-08 20:19:29 +02:00
}
}
ty::AssocKind::Type => {
let my_name = self.ident.name;
2020-06-30 23:41:57 +02:00
if let ty::TraitContainer(_) = self.container {
let bounds = tcx.explicit_item_bounds(self.def_id);
2020-06-30 23:41:57 +02:00
let predicates = ty::GenericPredicates { parent: None, predicates: bounds };
let generics = (tcx.generics_of(self.def_id), predicates).clean(cx);
2019-12-22 23:42:04 +01: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 == kw::SelfUpper => {}
2019-12-22 23:42:04 +01:00
_ => return None,
}
Some(bounds)
})
.flat_map(|i| i.iter().cloned())
.collect::<Vec<_>>();
// Our Sized/?Sized bound didn't get handled when creating the generics
// because we didn't actually get our whole set of bounds until just now
// (some of them may have come from the trait). If we do have a sized
// bound, we remove it, and if we don't then we add the `?Sized` bound
// at the end.
match bounds.iter().position(|b| b.is_sized_bound(cx)) {
2019-12-22 23:42:04 +01:00
Some(i) => {
bounds.remove(i);
}
None => bounds.push(GenericBound::maybe_sized(cx)),
}
let ty = if self.defaultness.has_value() {
Some(tcx.type_of(self.def_id))
} else {
None
};
AssocTypeItem(bounds, ty.clean(cx))
} else {
2021-02-14 13:18:17 +01:00
// FIXME: when could this happen? Associated items in inherent impls?
let type_ = tcx.type_of(self.def_id).clean(cx);
2019-12-22 23:42:04 +01:00
TypedefItem(
Typedef {
2020-01-10 02:07:13 +01:00
type_,
2019-12-22 23:42:04 +01:00
generics: Generics { params: Vec::new(), where_predicates: Vec::new() },
2021-01-03 22:08:21 +01:00
item_type: None,
},
2019-12-22 23:42:04 +01:00
true,
)
}
}
};
Item::from_def_id_and_parts(self.def_id, Some(self.ident.name), kind, cx)
}
}
fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &mut DocContext<'_>) -> Type {
use rustc_hir::GenericParamCount;
let hir::Ty { hir_id, span, ref kind } = *hir_ty;
let qpath = match kind {
hir::TyKind::Path(qpath) => qpath,
_ => unreachable!(),
};
match qpath {
hir::QPath::Resolved(None, ref path) => {
if let Res::Def(DefKind::TyParam, did) = path.res {
if let Some(new_ty) = cx.ty_substs.get(&did).cloned() {
return new_ty;
}
if let Some(bounds) = cx.impl_trait_bounds.remove(&did.into()) {
return ImplTrait(bounds);
}
}
let mut alias = None;
if let Res::Def(DefKind::TyAlias, def_id) = path.res {
// Substitute private type aliases
if let Some(def_id) = def_id.as_local() {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def_id);
if !cx.cache.access_levels.is_exported(def_id.to_def_id()) {
alias = Some(&cx.tcx.hir().expect_item(hir_id).kind);
}
}
};
if let Some(&hir::ItemKind::TyAlias(ref ty, ref generics)) = alias {
let provided_params = &path.segments.last().expect("segments were empty");
let mut ty_substs = FxHashMap::default();
let mut lt_substs = FxHashMap::default();
let mut ct_substs = FxHashMap::default();
let generic_args = provided_params.args();
{
let mut indices: GenericParamCount = Default::default();
for param in generics.params.iter() {
match param.kind {
hir::GenericParamKind::Lifetime { .. } => {
let mut j = 0;
let lifetime = generic_args.args.iter().find_map(|arg| match arg {
hir::GenericArg::Lifetime(lt) => {
if indices.lifetimes == j {
return Some(lt);
}
j += 1;
None
}
_ => None,
});
if let Some(lt) = lifetime.cloned() {
let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
let cleaned = if !lt.is_elided() {
lt.clean(cx)
} else {
self::types::Lifetime::elided()
};
lt_substs.insert(lt_def_id.to_def_id(), cleaned);
}
indices.lifetimes += 1;
}
hir::GenericParamKind::Type { ref default, .. } => {
let ty_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
let mut j = 0;
let type_ = generic_args.args.iter().find_map(|arg| match arg {
hir::GenericArg::Type(ty) => {
if indices.types == j {
return Some(ty);
}
j += 1;
None
}
_ => None,
});
if let Some(ty) = type_ {
ty_substs.insert(ty_param_def_id.to_def_id(), ty.clean(cx));
} else if let Some(default) = *default {
ty_substs
.insert(ty_param_def_id.to_def_id(), default.clean(cx));
}
indices.types += 1;
}
hir::GenericParamKind::Const { .. } => {
let const_param_def_id = cx.tcx.hir().local_def_id(param.hir_id);
let mut j = 0;
let const_ = generic_args.args.iter().find_map(|arg| match arg {
hir::GenericArg::Const(ct) => {
if indices.consts == j {
return Some(ct);
}
j += 1;
None
}
_ => None,
});
if let Some(ct) = const_ {
ct_substs.insert(const_param_def_id.to_def_id(), ct.clean(cx));
}
// FIXME(const_generics_defaults)
indices.consts += 1;
}
}
}
}
return cx.enter_alias(ty_substs, lt_substs, ct_substs, |cx| ty.clean(cx));
}
let path = path.clean(cx);
resolve_type(cx, path, hir_id)
}
hir::QPath::Resolved(Some(ref qself), ref p) => {
// Try to normalize `<X as Y>::T` to a type
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
if let Some(normalized_value) = normalize(cx, ty) {
return normalized_value.clean(cx);
}
let segments = if p.is_global() { &p.segments[1..] } else { &p.segments };
let trait_segments = &segments[..segments.len() - 1];
let trait_path = self::Path {
global: p.is_global(),
res: Res::Def(
DefKind::Trait,
cx.tcx.associated_item(p.res.def_id()).container.id(),
),
segments: trait_segments.clean(cx),
};
Type::QPath {
name: p.segments.last().expect("segments were empty").ident.name,
self_type: box qself.clean(cx),
trait_: box resolve_type(cx, trait_path, hir_id),
}
}
hir::QPath::TypeRelative(ref qself, ref segment) => {
let ty = hir_ty_to_ty(cx.tcx, hir_ty);
let res = if let ty::Projection(proj) = ty.kind() {
Res::Def(DefKind::Trait, proj.trait_ref(cx.tcx).def_id)
} else {
Res::Err
};
let trait_path = hir::Path { span, res, segments: &[] }.clean(cx);
Type::QPath {
name: segment.ident.name,
self_type: box qself.clean(cx),
trait_: box resolve_type(cx, trait_path, hir_id),
}
}
hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"),
}
}
2019-12-01 16:08:58 +01:00
impl Clean<Type> for hir::Ty<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Type {
use rustc_hir::*;
2019-09-26 18:25:31 +02:00
match self.kind {
2018-07-11 17:36:06 +02: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 17:36:06 +02:00
TyKind::Rptr(ref l, ref m) => {
// There are two times a `Fresh` lifetime can be created:
// 1. For `&'_ x`, written by the user. This corresponds to `lower_lifetime` in `rustc_ast_lowering`.
// 2. For `&x` as a parameter to an `async fn`. This corresponds to `elided_ref_lifetime in `rustc_ast_lowering`.
2020-12-23 03:26:17 +01:00
// See #59286 for more information.
// Ideally we would only hide the `'_` for case 2., but I don't know a way to distinguish it.
// Turning `fn f(&'_ self)` into `fn f(&self)` isn't the worst thing in the world, though;
// there's no case where it could cause the function to fail to compile.
let elided =
l.is_elided() || matches!(l.name, LifetimeName::Param(ParamName::Fresh(_)));
let lifetime = if elided { None } else { Some(l.clean(cx)) };
2019-12-22 23:42:04 +01:00
BorrowedRef { lifetime, mutability: m.mutbl, type_: box m.ty.clean(cx) }
}
2018-07-11 17:36:06 +02:00
TyKind::Slice(ref ty) => Slice(box ty.clean(cx)),
TyKind::Array(ref ty, ref length) => {
let def_id = cx.tcx.hir().local_def_id(length.hir_id);
// NOTE(min_const_generics): We can't use `const_eval_poly` for constants
// as we currently do not supply the parent generics to anonymous constants
// but do allow `ConstKind::Param`.
//
// `const_eval_poly` tries to to first substitute generic parameters which
// results in an ICE while manually constructing the constant and using `eval`
// does nothing for `ConstKind::Param`.
let ct = ty::Const::from_anon_const(cx.tcx, def_id);
let param_env = cx.tcx.param_env(def_id);
let length = print_const(cx, ct.eval(cx.tcx, param_env));
Array(box ty.clean(cx), length)
2019-12-22 23:42:04 +01:00
}
2018-07-11 17:36:06 +02:00
TyKind::Tup(ref tys) => Tuple(tys.clean(cx)),
2020-06-07 19:56:17 +02:00
TyKind::OpaqueDef(item_id, _) => {
2021-01-30 12:06:04 +01:00
let item = cx.tcx.hir().item(item_id);
2019-09-26 18:51:36 +02: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!()
}
}
TyKind::Path(_) => clean_qpath(&self, cx),
TyKind::TraitObject(ref bounds, ref lifetime, _) => {
match bounds[0].clean(cx).trait_ {
ResolvedPath { path, param_names: None, did, is_generic } => {
2019-12-22 23:42:04 +01:00
let mut bounds: Vec<self::GenericBound> = bounds[1..]
.iter()
.map(|bound| {
self::GenericBound::TraitBound(
bound.clean(cx),
hir::TraitBoundModifier::None,
)
})
.collect();
if !lifetime.is_elided() {
2018-06-14 13:23:46 +02:00
bounds.push(self::GenericBound::Outlives(lifetime.clean(cx)));
}
2019-12-22 23:42:04 +01:00
ResolvedPath { path, param_names: Some(bounds), did, is_generic }
2014-11-21 01:44:49 +01:00
}
_ => Infer, // shouldn't happen
2014-11-21 01:44:49 +01:00
}
}
2018-07-11 17:36:06 +02:00
TyKind::BareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
TyKind::Infer | TyKind::Err => Infer,
2019-09-26 18:25:31 +02:00
TyKind::Typeof(..) => panic!("unimplemented type {:?}", self.kind),
}
2013-08-15 22:28:54 +02:00
}
}
/// Returns `None` if the type could not be normalized
fn normalize(cx: &mut DocContext<'tcx>, ty: Ty<'_>) -> Option<Ty<'tcx>> {
// HACK: low-churn fix for #79459 while we wait for a trait normalization fix
if !cx.tcx.sess.opts.debugging_opts.normalize_docs {
return None;
}
use crate::rustc_trait_selection::infer::TyCtxtInferExt;
use crate::rustc_trait_selection::traits::query::normalize::AtExt;
use rustc_middle::traits::ObligationCause;
// Try to normalize `<X as Y>::T` to a type
let lifted = ty.lift_to_tcx(cx.tcx).unwrap();
let normalized = cx.tcx.infer_ctxt().enter(|infcx| {
infcx
.at(&ObligationCause::dummy(), cx.param_env)
.normalize(lifted)
.map(|resolved| infcx.resolve_vars_if_possible(resolved.value))
});
match normalized {
Ok(normalized_value) => {
debug!("normalized {:?} to {:?}", ty, normalized_value);
Some(normalized_value)
}
Err(err) => {
debug!("failed to normalize {:?}: {:?}", ty, err);
None
}
}
}
2017-09-15 03:44:23 +02:00
impl<'tcx> Clean<Type> for Ty<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> Type {
debug!("cleaning type: {:?}", self);
let ty = normalize(cx, self).unwrap_or(self);
match *ty.kind() {
ty::Never => Never,
ty::Bool => Primitive(PrimitiveType::Bool),
ty::Char => Primitive(PrimitiveType::Char),
ty::Int(int_ty) => Primitive(int_ty.into()),
ty::Uint(uint_ty) => Primitive(uint_ty.into()),
ty::Float(float_ty) => Primitive(float_ty.into()),
ty::Str => Primitive(PrimitiveType::Str),
ty::Slice(ty) => Slice(box ty.clean(cx)),
ty::Array(ty, n) => {
2020-10-16 21:59:49 +02:00
let mut n = cx.tcx.lift(n).expect("array lift failed");
n = n.eval(cx.tcx, ty::ParamEnv::reveal_all());
2018-01-29 10:32:11 +01:00
let n = print_const(cx, n);
Array(box ty.clean(cx), n)
}
2019-12-21 15:29:46 +01:00
ty::RawPtr(mt) => RawPointer(mt.mutbl, box mt.ty.clean(cx)),
2019-12-22 23:42:04 +01:00
ty::Ref(r, ty, mutbl) => {
BorrowedRef { lifetime: r.clean(cx), mutability: mutbl, type_: box ty.clean(cx) }
}
ty::FnDef(..) | ty::FnPtr(_) => {
2020-10-16 21:59:49 +02:00
let ty = cx.tcx.lift(*self).expect("FnPtr lift failed");
let sig = ty.fn_sig(cx.tcx);
let def_id = DefId::local(CRATE_DEF_INDEX);
BareFunction(box BareFunctionDecl {
unsafety: sig.unsafety(),
generic_params: Vec::new(),
decl: (def_id, sig).clean(cx),
abi: sig.abi(),
})
}
ty::Adt(def, substs) => {
let did = def.did;
let kind = match def.adt_kind() {
AdtKind::Struct => TypeKind::Struct,
AdtKind::Union => TypeKind::Union,
AdtKind::Enum => TypeKind::Enum,
};
inline::record_extern_fqn(cx, did, kind);
2019-09-05 03:43:05 +02:00
let path = external_path(cx, cx.tcx.item_name(did), None, false, vec![], substs);
2019-12-22 23:42:04 +01:00
ResolvedPath { path, param_names: None, did, is_generic: false }
}
ty::Foreign(did) => {
2017-09-03 20:53:58 +02:00
inline::record_extern_fqn(cx, did, TypeKind::Foreign);
2019-12-22 23:42:04 +01: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 20:53:58 +02:00
}
ty::Dynamic(ref obj, ref reg) => {
2018-12-15 16:35:55 +01: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 23:42:04 +01:00
let did = dids
.next()
.unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", self));
2018-12-15 16:35:55 +01:00
let substs = match obj.principal() {
Some(principal) => principal.skip_binder().substs,
// marker traits have no substs.
2019-12-22 23:42:04 +01:00
_ => cx.tcx.intern_substs(&[]),
2018-12-15 16:35:55 +01:00
};
inline::record_extern_fqn(cx, did, TypeKind::Trait);
let mut param_names = vec![];
if let Some(b) = reg.clean(cx) {
param_names.push(GenericBound::Outlives(b));
}
2018-12-15 16:35:55 +01:00
for did in dids {
let empty = cx.tcx.intern_substs(&[]);
2019-12-22 23:42:04 +01:00
let path =
external_path(cx, cx.tcx.item_name(did), Some(did), false, vec![], empty);
inline::record_extern_fqn(cx, did, TypeKind::Trait);
2019-12-22 23:42:04 +01:00
let bound = GenericBound::TraitBound(
PolyTrait {
trait_: ResolvedPath {
path,
param_names: None,
did,
is_generic: false,
},
generic_params: Vec::new(),
},
2019-12-22 23:42:04 +01:00
hir::TraitBoundModifier::None,
);
param_names.push(bound);
}
let mut bindings = vec![];
for pb in obj.projection_bounds() {
bindings.push(TypeBinding {
name: cx.tcx.associated_item(pb.item_def_id()).ident.name,
2019-12-22 23:42:04 +01:00
kind: TypeBindingKind::Equality { ty: pb.skip_binder().ty.clean(cx) },
});
}
2019-12-22 23:42:04 +01:00
let path =
external_path(cx, cx.tcx.item_name(did), Some(did), false, bindings, substs);
ResolvedPath { path, param_names: Some(param_names), did, is_generic: false }
}
2019-04-26 01:27:33 +02:00
ty::Tuple(ref t) => {
Tuple(t.iter().map(|t| t.expect_ty()).collect::<Vec<_>>().clean(cx))
}
ty::Projection(ref data) => data.clean(cx),
ty::Param(ref p) => {
if let Some(bounds) = cx.impl_trait_bounds.remove(&p.index.into()) {
ImplTrait(bounds)
} else {
Generic(p.name)
}
}
ty::Opaque(def_id, substs) => {
// Grab the "TraitA + TraitB" from `impl TraitA + TraitB`,
2020-06-30 23:41:57 +02:00
// by looking up the bounds associated with the def_id.
2020-10-16 21:59:49 +02:00
let substs = cx.tcx.lift(substs).expect("Opaque lift failed");
2020-06-30 23:41:57 +02:00
let bounds = cx
.tcx
.explicit_item_bounds(def_id)
.iter()
.map(|(bound, _)| bound.subst(cx.tcx, substs))
.collect::<Vec<_>>();
let mut regions = vec![];
let mut has_sized = false;
2019-12-22 23:42:04 +01:00
let mut bounds = bounds
.iter()
2020-06-30 23:41:57 +02:00
.filter_map(|bound| {
2021-01-07 17:20:28 +01:00
let bound_predicate = bound.kind();
2020-12-17 04:36:14 +01:00
let trait_ref = match bound_predicate.skip_binder() {
2021-01-07 17:20:28 +01:00
ty::PredicateKind::Trait(tr, _constness) => {
2020-12-17 04:36:14 +01:00
bound_predicate.rebind(tr.trait_ref)
2020-06-21 14:42:47 +02:00
}
2021-01-07 17:20:28 +01:00
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
2020-07-18 18:46:30 +02:00
if let Some(r) = reg.clean(cx) {
2020-06-21 14:42:47 +02:00
regions.push(GenericBound::Outlives(r));
}
return None;
}
2020-06-21 14:42:47 +02:00
_ => return None,
2019-12-22 23:42:04 +01:00
};
2019-12-22 23:42:04 +01:00
if let Some(sized) = cx.tcx.lang_items().sized_trait() {
if trait_ref.def_id() == sized {
has_sized = true;
return None;
}
}
let bounds: Vec<_> = bounds
2019-12-22 23:42:04 +01:00
.iter()
2020-06-30 23:41:57 +02:00
.filter_map(|bound| {
2021-01-07 17:20:28 +01:00
if let ty::PredicateKind::Projection(proj) =
bound.kind().skip_binder()
2020-06-19 10:05:05 +02:00
{
2019-12-22 23:42:04 +01:00
if proj.projection_ty.trait_ref(cx.tcx)
2020-06-24 23:40:33 +02:00
== trait_ref.skip_binder()
2019-12-22 23:42:04 +01:00
{
Some(TypeBinding {
name: cx
.tcx
.associated_item(proj.projection_ty.item_def_id)
.ident
.name,
2019-12-22 23:42:04 +01:00
kind: TypeBindingKind::Equality {
ty: proj.ty.clean(cx),
},
})
} else {
None
}
} else {
None
}
})
.collect();
Some((trait_ref, &bounds[..]).clean(cx))
2019-12-22 23:42:04 +01:00
})
.collect::<Vec<_>>();
bounds.extend(regions);
if !has_sized && !bounds.is_empty() {
bounds.insert(0, GenericBound::maybe_sized(cx));
}
ImplTrait(bounds)
}
ty::Closure(..) | ty::Generator(..) => Tuple(vec![]), // FIXME(pcwalton)
2018-10-22 20:37:56 +02:00
ty::Bound(..) => panic!("Bound"),
ty::Placeholder(..) => panic!("Placeholder"),
ty::GeneratorWitness(..) => panic!("GeneratorWitness"),
ty::Infer(..) => panic!("Infer"),
ty::Error(_) => panic!("Error"),
}
}
}
impl<'tcx> Clean<Constant> for ty::Const<'tcx> {
fn clean(&self, cx: &mut DocContext<'_>) -> Constant {
Constant {
type_: self.ty.clean(cx),
expr: format!("{}", self),
value: None,
is_literal: false,
}
}
}
impl Clean<Item> for hir::FieldDef<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Item {
let what_rustc_thinks = Item::from_hir_id_and_parts(
self.hir_id,
Some(self.ident.name),
StructFieldItem(self.ty.clean(cx)),
cx,
);
// Don't show `pub` for fields on enum variants; they are always public
Item { visibility: self.vis.clean(cx), ..what_rustc_thinks }
2013-08-15 22:28:54 +02:00
}
}
2019-06-11 11:50:17 +02:00
impl Clean<Item> for ty::FieldDef {
fn clean(&self, cx: &mut DocContext<'_>) -> Item {
let what_rustc_thinks = Item::from_def_id_and_parts(
self.did,
Some(self.ident.name),
StructFieldItem(cx.tcx.type_of(self.did).clean(cx)),
cx,
);
// Don't show `pub` for fields on enum variants; they are always public
Item { visibility: self.vis.clean(cx), ..what_rustc_thinks }
}
}
2019-12-01 16:08:58 +01:00
impl Clean<Visibility> for hir::Visibility<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Visibility {
match self.node {
hir::VisibilityKind::Public => Visibility::Public,
hir::VisibilityKind::Inherited => Visibility::Inherited,
hir::VisibilityKind::Crate(_) => {
let krate = DefId::local(CRATE_DEF_INDEX);
Visibility::Restricted(krate)
}
hir::VisibilityKind::Restricted { ref path, .. } => {
let path = path.clean(cx);
let did = register_res(cx, path.res);
Visibility::Restricted(did)
}
}
}
}
impl Clean<Visibility> for ty::Visibility {
fn clean(&self, _cx: &mut DocContext<'_>) -> Visibility {
match *self {
ty::Visibility::Public => Visibility::Public,
// NOTE: this is not quite right: `ty` uses `Invisible` to mean 'private',
// while rustdoc really does mean inherited. That means that for enum variants, such as
// `pub enum E { V }`, `V` will be marked as `Public` by `ty`, but as `Inherited` by rustdoc.
// This is the main reason `impl Clean for hir::Visibility` still exists; various parts of clean
// override `tcx.visibility` explicitly to make sure this distinction is captured.
ty::Visibility::Invisible => Visibility::Inherited,
ty::Visibility::Restricted(module) => Visibility::Restricted(module),
}
2013-08-15 22:28:54 +02:00
}
}
impl Clean<VariantStruct> for rustc_hir::VariantData<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> VariantStruct {
2013-08-15 22:28:54 +02:00
VariantStruct {
struct_type: CtorKind::from_hir(self),
fields: self.fields().iter().map(|x| x.clean(cx)).collect(),
fields_stripped: false,
2013-08-15 22:28:54 +02:00
}
}
}
2019-06-11 11:50:17 +02:00
impl Clean<Item> for ty::VariantDef {
fn clean(&self, cx: &mut DocContext<'_>) -> Item {
let kind = match self.ctor_kind {
CtorKind::Const => Variant::CLike,
CtorKind::Fn => Variant::Tuple(
2019-12-22 23:42:04 +01:00
self.fields.iter().map(|f| cx.tcx.type_of(f.did).clean(cx)).collect(),
),
CtorKind::Fictive => Variant::Struct(VariantStruct {
struct_type: CtorKind::Fictive,
2019-12-22 23:42:04 +01:00
fields_stripped: false,
fields: self
.fields
.iter()
.map(|field| {
let name = Some(field.ident.name);
let kind = StructFieldItem(cx.tcx.type_of(field.did).clean(cx));
let what_rustc_thinks =
Item::from_def_id_and_parts(field.did, name, kind, cx);
// don't show `pub` for fields, which are always public
Item { visibility: Visibility::Inherited, ..what_rustc_thinks }
2019-12-22 23:42:04 +01:00
})
.collect(),
}),
2014-05-24 01:14:54 +02:00
};
let what_rustc_thinks =
Item::from_def_id_and_parts(self.def_id, Some(self.ident.name), VariantItem(kind), cx);
// don't show `pub` for fields, which are always public
Item { visibility: Inherited, ..what_rustc_thinks }
2014-05-24 01:14:54 +02:00
}
}
impl Clean<Variant> for hir::VariantData<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Variant {
match self {
hir::VariantData::Struct(..) => Variant::Struct(self.clean(cx)),
2019-12-22 23:42:04 +01:00
hir::VariantData::Tuple(..) => {
Variant::Tuple(self.fields().iter().map(|x| x.ty.clean(cx)).collect())
2019-12-22 23:42:04 +01:00
}
hir::VariantData::Unit(..) => Variant::CLike,
}
}
}
impl Clean<Span> for rustc_span::Span {
fn clean(&self, _cx: &mut DocContext<'_>) -> Span {
Span::from_rustc_span(*self)
2013-08-15 22:28:54 +02:00
}
}
2019-12-01 16:08:58 +01:00
impl Clean<Path> for hir::Path<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Path {
2013-08-15 22:28:54 +02:00
Path {
global: self.is_global(),
res: self.res,
segments: if self.is_global() { &self.segments[1..] } else { &self.segments }.clean(cx),
}
}
}
2019-12-01 16:08:58 +01:00
impl Clean<GenericArgs> for hir::GenericArgs<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> GenericArgs {
if self.parenthesized {
2019-05-08 21:57:06 +02:00
let output = self.bindings[0].ty().clean(cx);
GenericArgs::Parenthesized {
inputs: self.inputs().clean(cx),
2019-12-22 23:42:04 +01:00
output: if output != Type::Tuple(Vec::new()) { Some(output) } else { None },
}
} else {
GenericArgs::AngleBracketed {
2019-12-22 23:42:04 +01:00
args: self
.args
.iter()
.map(|arg| match arg {
hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
GenericArg::Lifetime(lt.clean(cx))
2019-12-22 23:42:04 +01:00
}
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
hir::GenericArg::Type(ty) => GenericArg::Type(ty.clean(cx)),
hir::GenericArg::Const(ct) => GenericArg::Const(ct.clean(cx)),
2019-12-22 23:42:04 +01:00
})
.collect(),
bindings: self.bindings.clean(cx),
}
}
}
}
2019-12-01 16:08:58 +01:00
impl Clean<PathSegment> for hir::PathSegment<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> PathSegment {
PathSegment { name: self.ident.name, args: self.args().clean(cx) }
2013-08-15 22:28:54 +02:00
}
}
impl Clean<String> for Ident {
#[inline]
fn clean(&self, cx: &mut DocContext<'_>) -> String {
self.name.clean(cx)
}
}
2020-04-19 13:00:18 +02:00
impl Clean<String> for Symbol {
#[inline]
fn clean(&self, _: &mut DocContext<'_>) -> String {
self.to_string()
}
}
2019-12-01 16:08:58 +01:00
impl Clean<BareFunctionDecl> for hir::BareFnTy<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> BareFunctionDecl {
let (generic_params, decl) = enter_impl_trait(cx, |cx| {
(self.generic_params.clean(cx), (&*self.decl, self.param_names).clean(cx))
2018-05-03 15:24:50 +02:00
});
2019-12-22 23:42:04 +01:00
BareFunctionDecl { unsafety: self.unsafety, abi: self.abi, decl, generic_params }
2013-08-15 22:28:54 +02:00
}
}
impl Clean<Vec<Item>> for (&hir::Item<'_>, Option<Symbol>) {
fn clean(&self, cx: &mut DocContext<'_>) -> Vec<Item> {
use hir::ItemKind;
2020-11-21 16:10:03 +01:00
let (item, renamed) = self;
let def_id = item.def_id.to_def_id();
let mut name = renamed.unwrap_or_else(|| cx.tcx.hir().name(item.hir_id()));
cx.with_param_env(def_id, |cx| {
let kind = match item.kind {
2021-02-11 20:37:36 +01:00
ItemKind::Static(ty, mutability, body_id) => {
StaticItem(Static { type_: ty.clean(cx), mutability, expr: Some(body_id) })
}
ItemKind::Const(ty, body_id) => ConstantItem(Constant {
type_: ty.clean(cx),
2021-02-11 20:37:36 +01:00
expr: print_const_expr(cx.tcx, body_id),
value: print_evaluated_const(cx, def_id),
is_literal: is_literal_expr(cx, body_id.hir_id),
}),
ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {
bounds: ty.bounds.clean(cx),
generics: ty.generics.clean(cx),
}),
ItemKind::TyAlias(hir_ty, ref generics) => {
let rustdoc_ty = hir_ty.clean(cx);
2021-01-03 22:08:21 +01:00
let ty = hir_ty_to_ty(cx.tcx, hir_ty).clean(cx);
TypedefItem(
2021-01-03 22:08:21 +01:00
Typedef {
type_: rustdoc_ty,
generics: generics.clean(cx),
item_type: Some(ty),
},
false,
)
}
ItemKind::Enum(ref def, ref generics) => EnumItem(Enum {
variants: def.variants.iter().map(|v| v.clean(cx)).collect(),
generics: generics.clean(cx),
variants_stripped: false,
}),
ItemKind::TraitAlias(ref generics, bounds) => TraitAliasItem(TraitAlias {
2020-11-23 03:32:18 +01:00
generics: generics.clean(cx),
bounds: bounds.clean(cx),
}),
ItemKind::Union(ref variant_data, ref generics) => UnionItem(Union {
generics: generics.clean(cx),
fields: variant_data.fields().clean(cx),
fields_stripped: false,
}),
ItemKind::Struct(ref variant_data, ref generics) => StructItem(Struct {
struct_type: CtorKind::from_hir(variant_data),
generics: generics.clean(cx),
fields: variant_data.fields().clean(cx),
fields_stripped: false,
}),
ItemKind::Impl(ref impl_) => return clean_impl(impl_, item.hir_id(), cx),
// proc macros can have a name set by attributes
ItemKind::Fn(ref sig, ref generics, body_id) => {
clean_fn_or_proc_macro(item, sig, generics, body_id, &mut name, cx)
}
2021-01-14 20:49:58 +01:00
ItemKind::Trait(is_auto, unsafety, ref generics, ref bounds, ref item_ids) => {
let items = item_ids
.iter()
.map(|ti| cx.tcx.hir().trait_item(ti.id).clean(cx))
.collect();
TraitItem(Trait {
unsafety,
items,
generics: generics.clean(cx),
bounds: bounds.clean(cx),
is_auto: is_auto.clean(cx),
})
}
ItemKind::ExternCrate(orig_name) => {
return clean_extern_crate(item, name, orig_name, cx);
}
2021-01-14 20:49:58 +01:00
ItemKind::Use(path, kind) => {
return clean_use_statement(item, name, path, kind, cx);
}
_ => unreachable!("not yet converted"),
};
vec![Item::from_def_id_and_parts(def_id, Some(name), kind, cx)]
})
2013-08-15 22:28:54 +02:00
}
}
impl Clean<Item> for hir::Variant<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> Item {
let kind = VariantItem(self.data.clean(cx));
let what_rustc_thinks =
Item::from_hir_id_and_parts(self.id, Some(self.ident.name), kind, cx);
// don't show `pub` for variants, which are always public
Item { visibility: Inherited, ..what_rustc_thinks }
}
}
impl Clean<bool> for ty::ImplPolarity {
/// Returns whether the impl has negative polarity.
fn clean(&self, _: &mut DocContext<'_>) -> bool {
match self {
&ty::ImplPolarity::Positive |
// FIXME: do we want to do something else here?
&ty::ImplPolarity::Reservation => false,
&ty::ImplPolarity::Negative => true,
}
}
}
fn clean_impl(impl_: &hir::Impl<'_>, hir_id: hir::HirId, cx: &mut DocContext<'_>) -> Vec<Item> {
let tcx = cx.tcx;
2020-11-22 19:34:06 +01:00
let mut ret = Vec::new();
let trait_ = impl_.of_trait.clean(cx);
let items =
impl_.items.iter().map(|ii| tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>();
let def_id = tcx.hir().local_def_id(hir_id);
2020-11-22 19:34:06 +01: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.
if trait_.def_id() == tcx.lang_items().deref_trait() {
2020-11-22 19:34:06 +01:00
build_deref_target_impls(cx, &items, &mut ret);
}
let provided: FxHashSet<Symbol> = trait_
2021-01-15 15:36:15 +01:00
.def_id()
.map(|did| tcx.provided_trait_methods(did).map(|meth| meth.ident.name).collect())
2020-11-22 19:34:06 +01:00
.unwrap_or_default();
let for_ = impl_.self_ty.clean(cx);
let type_alias = for_.def_id().and_then(|did| match tcx.def_kind(did) {
DefKind::TyAlias => Some(tcx.type_of(did).clean(cx)),
2020-11-22 19:34:06 +01:00
_ => None,
});
let mut make_item = |trait_: Option<Type>, for_: Type, items: Vec<Item>| {
2020-11-22 19:34:06 +01:00
let kind = ImplItem(Impl {
unsafety: impl_.unsafety,
generics: impl_.generics.clean(cx),
2020-11-22 19:34:06 +01:00
provided_trait_methods: provided.clone(),
trait_,
for_,
items,
negative_polarity: tcx.impl_polarity(def_id).clean(cx),
2020-11-22 19:34:06 +01:00
synthetic: false,
blanket_impl: None,
2020-01-15 18:52:04 +01:00
});
Item::from_hir_id_and_parts(hir_id, None, kind, cx)
2020-11-22 19:34:06 +01:00
};
if let Some(type_alias) = type_alias {
ret.push(make_item(trait_.clone(), type_alias, items.clone()));
}
2020-11-22 19:34:06 +01:00
ret.push(make_item(trait_, for_, items));
ret
}
2020-11-23 03:51:57 +01:00
fn clean_extern_crate(
krate: &hir::Item<'_>,
name: Symbol,
orig_name: Option<Symbol>,
cx: &mut DocContext<'_>,
2020-11-23 03:51:57 +01:00
) -> Vec<Item> {
// this is the ID of the `extern crate` statement
let cnum = cx.tcx.extern_mod_stmt_cnum(krate.def_id).unwrap_or(LOCAL_CRATE);
2020-11-23 03:51:57 +01:00
// this is the ID of the crate itself
let crate_def_id = DefId { krate: cnum, index: CRATE_DEF_INDEX };
2021-01-24 13:17:54 +01:00
let attrs = cx.tcx.hir().attrs(krate.hir_id());
2020-11-23 03:51:57 +01:00
let please_inline = krate.vis.node.is_pub()
2021-01-24 13:17:54 +01:00
&& attrs.iter().any(|a| {
2020-11-23 03:51:57 +01:00
a.has_name(sym::doc)
&& match a.meta_item_list() {
Some(l) => attr::list_contains_name(&l, sym::inline),
None => false,
}
});
if please_inline {
let mut visited = FxHashSet::default();
2019-01-11 02:27:44 +01:00
2020-11-23 03:51:57 +01:00
let res = Res::Def(DefKind::Mod, crate_def_id);
if let Some(items) = inline::try_inline(
cx,
cx.tcx.parent_module(krate.hir_id()).to_def_id(),
2020-11-23 03:51:57 +01:00
res,
name,
2021-01-24 13:17:54 +01:00
Some(attrs),
2020-11-23 03:51:57 +01:00
&mut visited,
) {
return items;
}
}
2020-11-23 03:51:57 +01:00
// FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason
vec![Item {
name: Some(name),
2021-01-24 13:17:54 +01:00
attrs: box attrs.clean(cx),
2020-11-23 03:51:57 +01:00
source: krate.span.clean(cx),
def_id: crate_def_id,
visibility: krate.vis.clean(cx),
kind: box ExternCrateItem { src: orig_name },
2020-11-23 03:51:57 +01:00
}]
2013-08-15 22:28:54 +02:00
}
2021-01-14 20:49:58 +01:00
fn clean_use_statement(
import: &hir::Item<'_>,
name: Symbol,
path: &hir::Path<'_>,
kind: hir::UseKind,
cx: &mut DocContext<'_>,
2021-01-14 20:49:58 +01:00
) -> Vec<Item> {
// We need this comparison because some imports (for std types for example)
// are "inserted" as well but directly by the compiler and they should not be
// taken into account.
if import.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) {
return Vec::new();
}
2021-01-24 13:17:54 +01:00
let attrs = cx.tcx.hir().attrs(import.hir_id());
let inline_attr = attrs.lists(sym::doc).get_word_attr(sym::inline);
2021-01-14 20:49:58 +01:00
let pub_underscore = import.vis.node.is_pub() && name == kw::Underscore;
if pub_underscore {
if let Some(ref inline) = inline_attr {
rustc_errors::struct_span_err!(
cx.tcx.sess,
inline.span(),
E0780,
"anonymous imports cannot be inlined"
)
.span_label(import.span, "anonymous import")
.emit();
}
2021-01-14 20:49:58 +01:00
}
2021-01-14 20:49:58 +01:00
// We consider inlining the documentation of `pub use` statements, but we
// forcefully don't inline if this is not public or if the
// #[doc(no_inline)] attribute is present.
// Don't inline doc(hidden) imports so they can be stripped at a later stage.
let mut denied = !import.vis.node.is_pub()
|| pub_underscore
2021-01-24 13:17:54 +01:00
|| attrs.iter().any(|a| {
2021-01-14 20:49:58 +01:00
a.has_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)
2019-12-22 23:42:04 +01:00
}
2021-01-14 20:49:58 +01:00
None => false,
2018-06-16 01:16:43 +02:00
}
2021-01-14 20:49:58 +01:00
});
// Also check whether imports were asked to be inlined, in case we're trying to re-export a
// crate in Rust 2018+
let path = path.clean(cx);
let inner = if kind == hir::UseKind::Glob {
if !denied {
let mut visited = FxHashSet::default();
if let Some(items) = inline::try_inline_glob(cx, path.res, &mut visited) {
return items;
2018-06-16 01:16:43 +02:00
}
2021-01-14 20:49:58 +01:00
}
Import::new_glob(resolve_use_source(cx, path), true)
} else {
if inline_attr.is_none() {
2021-01-14 20:49:58 +01:00
if let Res::Def(DefKind::Mod, did) = path.res {
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;
}
}
2021-01-14 20:49:58 +01:00
}
if !denied {
let mut visited = FxHashSet::default();
if let Some(mut items) = inline::try_inline(
cx,
cx.tcx.parent_module(import.hir_id()).to_def_id(),
2021-01-14 20:49:58 +01:00
path.res,
name,
2021-01-24 13:17:54 +01:00
Some(attrs),
2021-01-14 20:49:58 +01:00
&mut visited,
) {
items.push(Item::from_def_id_and_parts(
import.def_id.to_def_id(),
2021-01-14 20:49:58 +01:00
None,
ImportItem(Import::new_simple(name, resolve_use_source(cx, path), false)),
cx,
2021-01-14 20:49:58 +01:00
));
return items;
}
2021-01-14 20:49:58 +01:00
}
Import::new_simple(name, resolve_use_source(cx, path), true)
};
2018-07-12 22:00:57 +02:00
vec![Item::from_def_id_and_parts(import.def_id.to_def_id(), None, ImportItem(inner), cx)]
2013-08-15 22:28:54 +02:00
}
impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Symbol>) {
fn clean(&self, cx: &mut DocContext<'_>) -> Item {
2020-11-22 20:03:02 +01:00
let (item, renamed) = self;
cx.with_param_env(item.def_id.to_def_id(), |cx| {
let kind = match item.kind {
hir::ForeignItemKind::Fn(ref decl, ref names, ref generics) => {
let abi = cx.tcx.hir().get_foreign_abi(item.hir_id());
let (generics, decl) = enter_impl_trait(cx, |cx| {
(generics.clean(cx), (&**decl, &names[..]).clean(cx))
});
ForeignFunctionItem(Function {
decl,
generics,
header: hir::FnHeader {
unsafety: hir::Unsafety::Unsafe,
abi,
constness: hir::Constness::NotConst,
asyncness: hir::IsAsync::NotAsync,
},
})
}
2021-02-11 20:37:36 +01:00
hir::ForeignItemKind::Static(ref ty, mutability) => {
ForeignStaticItem(Static { type_: ty.clean(cx), mutability, expr: None })
}
hir::ForeignItemKind::Type => ForeignTypeItem,
};
2018-07-12 22:00:57 +02:00
Item::from_hir_id_and_parts(
item.hir_id(),
Some(renamed.unwrap_or(item.ident.name)),
kind,
cx,
)
})
}
}
impl Clean<Item> for (&hir::MacroDef<'_>, Option<Symbol>) {
fn clean(&self, cx: &mut DocContext<'_>) -> Item {
2020-11-27 00:36:59 +01:00
let (item, renamed) = self;
let name = renamed.unwrap_or(item.ident.name);
2020-11-27 00:36:59 +01:00
let tts = item.ast.body.inner_tokens().trees().collect::<Vec<_>>();
// Extract the spans of all matchers. They represent the "interface" of the macro.
let matchers = tts.chunks(4).map(|arm| arm[0].span()).collect::<Vec<_>>();
let source = if item.ast.macro_rules {
format!(
"macro_rules! {} {{\n{}}}",
name,
matchers
.iter()
.map(|span| { format!(" {} => {{ ... }};\n", span.to_src(cx)) })
.collect::<String>(),
)
} else {
let vis = item.vis.clean(cx);
let def_id = item.def_id.to_def_id();
if matchers.len() <= 1 {
format!(
"{}macro {}{} {{\n ...\n}}",
2021-01-12 23:36:04 +01:00
vis.print_with_space(cx.tcx, def_id, &cx.cache),
name,
matchers.iter().map(|span| span.to_src(cx)).collect::<String>(),
)
} else {
format!(
"{}macro {} {{\n{}}}",
2021-01-12 23:36:04 +01:00
vis.print_with_space(cx.tcx, def_id, &cx.cache),
name,
matchers
2019-12-22 23:42:04 +01:00
.iter()
.map(|span| { format!(" {} => {{ ... }},\n", span.to_src(cx)) })
.collect::<String>(),
)
}
};
2020-11-27 00:36:59 +01:00
Item::from_hir_id_and_parts(
item.hir_id(),
Some(name),
MacroItem(Macro { source, imported_from: None }),
cx,
)
}
}
2019-12-01 16:08:58 +01:00
impl Clean<TypeBinding> for hir::TypeBinding<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> TypeBinding {
TypeBinding { name: self.ident.name, kind: self.kind.clean(cx) }
2019-05-08 21:57:06 +02:00
}
}
2019-12-01 16:08:58 +01:00
impl Clean<TypeBindingKind> for hir::TypeBindingKind<'_> {
fn clean(&self, cx: &mut DocContext<'_>) -> TypeBindingKind {
2019-05-08 21:57:06 +02:00
match *self {
2019-12-22 23:42:04 +01:00
hir::TypeBindingKind::Equality { ref ty } => {
TypeBindingKind::Equality { ty: ty.clean(cx) }
}
hir::TypeBindingKind::Constraint { ref bounds } => {
TypeBindingKind::Constraint { bounds: bounds.iter().map(|b| b.clean(cx)).collect() }
}
}
}
}
Generate documentation for auto-trait impls A new section is added to both both struct and trait doc pages. On struct/enum pages, a new 'Auto Trait Implementations' section displays any synthetic implementations for auto traits. Currently, this is only done for Send and Sync. On trait pages, a new 'Auto Implementors' section displays all types which automatically implement the trait. Effectively, this is a list of all public types in the standard library. Synthesized impls for a particular auto trait ('synthetic impls') take into account generic bounds. For example, a type 'struct Foo<T>(T)' will have 'impl<T> Send for Foo<T> where T: Send' generated for it. Manual implementations of auto traits are also taken into account. If we have the following types: 'struct Foo<T>(T)' 'struct Wrapper<T>(Foo<T>)' 'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes this sound somehow Then Wrapper will have the following impl generated: 'impl<T> Send for Wrapper<T>' reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send' to hold Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are taken into account by synthetic impls However, if a type can *never* implement a particular auto trait (e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be generated (in this case, 'impl<T> !Send for MyStruct<T>') All of this means that a user should be able to copy-paste a synthetic impl into their code, without any observable changes in behavior (assuming the rest of the program remains unchanged).
2017-11-22 22:16:55 +01:00
enum SimpleBound {
TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParamDef>, hir::TraitBoundModifier),
Outlives(Lifetime),
Generate documentation for auto-trait impls A new section is added to both both struct and trait doc pages. On struct/enum pages, a new 'Auto Trait Implementations' section displays any synthetic implementations for auto traits. Currently, this is only done for Send and Sync. On trait pages, a new 'Auto Implementors' section displays all types which automatically implement the trait. Effectively, this is a list of all public types in the standard library. Synthesized impls for a particular auto trait ('synthetic impls') take into account generic bounds. For example, a type 'struct Foo<T>(T)' will have 'impl<T> Send for Foo<T> where T: Send' generated for it. Manual implementations of auto traits are also taken into account. If we have the following types: 'struct Foo<T>(T)' 'struct Wrapper<T>(Foo<T>)' 'unsafe impl<T> Send for Wrapper<T>' // pretend that Wrapper<T> makes this sound somehow Then Wrapper will have the following impl generated: 'impl<T> Send for Wrapper<T>' reflecting the fact that 'T: Send' need not hold for 'Wrapper<T>: Send' to hold Lifetimes, HRTBS, and projections (e.g. '<T as Iterator>::Item') are taken into account by synthetic impls However, if a type can *never* implement a particular auto trait (e.g. 'struct MyStruct<T>(*const T)'), then a negative impl will be generated (in this case, 'impl<T> !Send for MyStruct<T>') All of this means that a user should be able to copy-paste a synthetic impl into their code, without any observable changes in behavior (assuming the rest of the program remains unchanged).
2017-11-22 22:16:55 +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 22:16:55 +01:00
match bound.clone() {
GenericBound::Outlives(l) => SimpleBound::Outlives(l),
GenericBound::TraitBound(t, mod_) => match t.trait_ {
2019-12-22 23:42:04 +01: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()
}),
2019-12-22 23:42:04 +01:00
t.generic_params,
mod_,
),
2018-02-10 20:34:46 +01:00
_ => panic!("Unexpected bound {:?}", bound),
2019-12-22 23:42:04 +01: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 22:16:55 +01:00
}
}
}