2014-05-24 11:56:38 -07:00
|
|
|
//! Support for inlining external documentation into the current AST.
|
|
|
|
|
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::iter::once;
|
2015-04-07 16:18:49 -07:00
|
|
|
|
2014-05-24 11:56:38 -07:00
|
|
|
use syntax::ast;
|
2019-06-16 18:58:39 +03:00
|
|
|
use syntax::ext::base::MacroKind;
|
2019-05-08 13:21:18 +10:00
|
|
|
use syntax::symbol::sym;
|
2018-06-17 14:54:28 -05:00
|
|
|
use syntax_pos::Span;
|
2014-05-24 11:56:38 -07:00
|
|
|
|
2018-06-17 14:54:28 -05:00
|
|
|
use rustc::hir;
|
2019-04-20 19:36:05 +03:00
|
|
|
use rustc::hir::def::{Res, DefKind, CtorKind};
|
2016-03-29 12:54:26 +03:00
|
|
|
use rustc::hir::def_id::DefId;
|
2018-07-31 17:23:29 -06:00
|
|
|
use rustc_metadata::cstore::LoadedMacro;
|
2016-11-20 03:42:54 +02:00
|
|
|
use rustc::ty;
|
2016-11-08 14:02:55 +11:00
|
|
|
use rustc::util::nodemap::FxHashSet;
|
2016-03-30 13:43:36 +02:00
|
|
|
|
2019-07-24 17:26:21 -04:00
|
|
|
use crate::core::DocContext;
|
2019-02-23 16:40:07 +09:00
|
|
|
use crate::doctree;
|
|
|
|
use crate::clean::{
|
2018-07-29 15:39:51 +02:00
|
|
|
self,
|
|
|
|
GetDefId,
|
|
|
|
ToSource,
|
2019-07-20 16:34:41 -04:00
|
|
|
TypeKind
|
2018-07-29 15:39:51 +02:00
|
|
|
};
|
2014-05-24 11:56:38 -07:00
|
|
|
|
2016-05-03 13:09:42 +02:00
|
|
|
use super::Clean;
|
2014-05-24 11:56:38 -07: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
|
|
|
type Attrs<'hir> = rustc::ty::Attributes<'hir>;
|
|
|
|
|
2016-11-25 13:21:19 +02:00
|
|
|
/// Attempt to inline a definition into this AST.
|
2014-05-24 11:56:38 -07:00
|
|
|
///
|
2016-11-25 13:21:19 +02:00
|
|
|
/// This function will fetch the definition specified, and if it is
|
|
|
|
/// from another crate it will attempt to inline the documentation
|
|
|
|
/// from the other crate into this crate.
|
2014-05-24 11:56:38 -07:00
|
|
|
///
|
|
|
|
/// This is primarily used for `pub use` statements which are, in general,
|
|
|
|
/// implementation details. Inlining the documentation should help provide a
|
|
|
|
/// better experience when reading the documentation in this use case.
|
|
|
|
///
|
2016-11-25 13:21:19 +02:00
|
|
|
/// The returned value is `None` if the definition could not be inlined,
|
|
|
|
/// and `Some` of a vector of items if it was successfully expanded.
|
2019-02-23 17:02:57 +09:00
|
|
|
pub fn try_inline(
|
2018-12-08 20:30:23 +01:00
|
|
|
cx: &DocContext<'_>,
|
2019-04-20 19:36:05 +03:00
|
|
|
res: Res,
|
2019-02-23 17:02:57 +09:00
|
|
|
name: ast::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
|
|
|
attrs: Option<Attrs<'_>>,
|
2019-02-23 17:02:57 +09:00
|
|
|
visited: &mut FxHashSet<DefId>
|
2019-04-20 19:36:05 +03:00
|
|
|
) -> Option<Vec<clean::Item>> {
|
|
|
|
let did = if let Some(did) = res.opt_def_id() {
|
2019-02-01 11:17:33 -06:00
|
|
|
did
|
|
|
|
} else {
|
|
|
|
return None;
|
|
|
|
};
|
2015-08-16 06:32:28 -04:00
|
|
|
if did.is_local() { return None }
|
2014-05-24 11:56:38 -07:00
|
|
|
let mut ret = Vec::new();
|
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
|
|
|
|
|
|
|
let attrs_clone = attrs.clone();
|
|
|
|
|
2019-04-20 19:36:05 +03:00
|
|
|
let inner = match res {
|
|
|
|
Res::Def(DefKind::Trait, did) => {
|
2016-10-01 00:34:00 -04:00
|
|
|
record_extern_fqn(cx, did, clean::TypeKind::Trait);
|
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
|
|
|
ret.extend(build_impls(cx, did, attrs));
|
2016-11-20 03:42:54 +02:00
|
|
|
clean::TraitItem(build_external_trait(cx, did))
|
2014-05-24 11:56:38 -07:00
|
|
|
}
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::Def(DefKind::Fn, did) => {
|
2016-10-01 00:34:00 -04:00
|
|
|
record_extern_fqn(cx, did, clean::TypeKind::Function);
|
2016-11-20 03:42:54 +02:00
|
|
|
clean::FunctionItem(build_external_function(cx, did))
|
2014-05-24 11:56:38 -07:00
|
|
|
}
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::Def(DefKind::Struct, did) => {
|
2016-10-01 00:34:00 -04:00
|
|
|
record_extern_fqn(cx, did, clean::TypeKind::Struct);
|
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
|
|
|
ret.extend(build_impls(cx, did, attrs));
|
2016-11-20 03:42:54 +02:00
|
|
|
clean::StructItem(build_struct(cx, did))
|
2014-05-24 11:56:38 -07:00
|
|
|
}
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::Def(DefKind::Union, did) => {
|
2016-10-01 00:34:00 -04:00
|
|
|
record_extern_fqn(cx, did, clean::TypeKind::Union);
|
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
|
|
|
ret.extend(build_impls(cx, did, attrs));
|
2016-11-20 03:42:54 +02:00
|
|
|
clean::UnionItem(build_union(cx, did))
|
2016-08-10 21:00:17 +03:00
|
|
|
}
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::Def(DefKind::TyAlias, did) => {
|
2016-10-01 00:34:00 -04:00
|
|
|
record_extern_fqn(cx, did, clean::TypeKind::Typedef);
|
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
|
|
|
ret.extend(build_impls(cx, did, attrs));
|
2016-11-20 03:42:54 +02:00
|
|
|
clean::TypedefItem(build_type_alias(cx, did), false)
|
2014-09-16 09:13:00 +12:00
|
|
|
}
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::Def(DefKind::Enum, did) => {
|
2016-10-01 00:34:00 -04:00
|
|
|
record_extern_fqn(cx, did, clean::TypeKind::Enum);
|
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
|
|
|
ret.extend(build_impls(cx, did, attrs));
|
2016-11-20 03:42:54 +02:00
|
|
|
clean::EnumItem(build_enum(cx, did))
|
2014-05-24 11:56:38 -07:00
|
|
|
}
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::Def(DefKind::ForeignTy, did) => {
|
2017-11-15 17:31:23 +08:00
|
|
|
record_extern_fqn(cx, did, clean::TypeKind::Foreign);
|
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
|
|
|
ret.extend(build_impls(cx, did, attrs));
|
2017-11-15 17:31:23 +08:00
|
|
|
clean::ForeignTypeItem
|
|
|
|
}
|
2018-01-12 16:41:25 -05:00
|
|
|
// Never inline enum variants but leave them shown as re-exports.
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::Def(DefKind::Variant, _) => return None,
|
2018-01-12 16:41:25 -05:00
|
|
|
// Assume that enum variants and struct types are re-exported next to
|
2017-06-12 19:00:09 +01:00
|
|
|
// their constructors.
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) => return Some(Vec::new()),
|
|
|
|
Res::Def(DefKind::Mod, did) => {
|
2016-10-01 00:34:00 -04:00
|
|
|
record_extern_fqn(cx, did, clean::TypeKind::Module);
|
2018-04-28 21:56:38 +02:00
|
|
|
clean::ModuleItem(build_module(cx, did, visited))
|
2014-05-24 11:56:38 -07:00
|
|
|
}
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::Def(DefKind::Static, did) => {
|
2016-10-01 00:34:00 -04:00
|
|
|
record_extern_fqn(cx, did, clean::TypeKind::Static);
|
2019-04-19 23:32:26 +03:00
|
|
|
clean::StaticItem(build_static(cx, did, cx.tcx.is_mutable_static(did)))
|
2014-06-05 17:20:59 -07:00
|
|
|
}
|
2019-04-20 19:36:05 +03:00
|
|
|
Res::Def(DefKind::Const, did) => {
|
2016-10-01 00:34:00 -04:00
|
|
|
record_extern_fqn(cx, did, clean::TypeKind::Const);
|
2016-11-20 03:42:54 +02:00
|
|
|
clean::ConstantItem(build_const(cx, did))
|
2014-12-12 04:13:36 -08:00
|
|
|
}
|
2019-07-20 16:34:41 -04:00
|
|
|
Res::Def(DefKind::Macro(kind), did) => {
|
2018-09-25 16:15:32 -05:00
|
|
|
let mac = build_macro(cx, did, name);
|
2019-07-20 16:34:41 -04:00
|
|
|
|
|
|
|
let type_kind = match kind {
|
|
|
|
MacroKind::Bang => TypeKind::Macro,
|
|
|
|
MacroKind::Attr => TypeKind::Attr,
|
|
|
|
MacroKind::Derive => TypeKind::Derive
|
|
|
|
};
|
|
|
|
record_extern_fqn(cx, did, type_kind);
|
|
|
|
mac
|
2018-06-17 14:54:28 -05:00
|
|
|
}
|
2014-05-24 11:56:38 -07:00
|
|
|
_ => return None,
|
|
|
|
};
|
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
|
|
|
|
|
|
|
let target_attrs = load_attrs(cx, did);
|
|
|
|
let attrs = merge_attrs(cx, target_attrs, attrs_clone);
|
|
|
|
|
2016-04-07 05:59:02 +02:00
|
|
|
cx.renderinfo.borrow_mut().inlined.insert(did);
|
2014-05-24 11:56:38 -07:00
|
|
|
ret.push(clean::Item {
|
2017-05-22 02:05:16 +01:00
|
|
|
source: cx.tcx.def_span(did).clean(cx),
|
|
|
|
name: Some(name.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,
|
2017-08-06 22:54:09 -07:00
|
|
|
inner,
|
2019-09-12 22:32:12 -04:00
|
|
|
visibility: clean::Public,
|
2017-05-22 02:05:16 +01:00
|
|
|
stability: cx.tcx.lookup_stability(did).clean(cx),
|
|
|
|
deprecation: cx.tcx.lookup_deprecation(did).clean(cx),
|
2014-05-24 11:56:38 -07:00
|
|
|
def_id: did,
|
|
|
|
});
|
|
|
|
Some(ret)
|
|
|
|
}
|
|
|
|
|
2019-04-20 19:36:05 +03:00
|
|
|
pub fn try_inline_glob(cx: &DocContext<'_>, res: Res, visited: &mut FxHashSet<DefId>)
|
2018-06-15 18:16:43 -05:00
|
|
|
-> Option<Vec<clean::Item>>
|
|
|
|
{
|
2019-04-20 19:36:05 +03:00
|
|
|
if res == Res::Err { return None }
|
|
|
|
let did = res.def_id();
|
2018-06-15 18:16:43 -05:00
|
|
|
if did.is_local() { return None }
|
|
|
|
|
2019-04-20 19:36:05 +03:00
|
|
|
match res {
|
|
|
|
Res::Def(DefKind::Mod, did) => {
|
2018-06-15 18:16:43 -05:00
|
|
|
let m = build_module(cx, did, visited);
|
|
|
|
Some(m.items)
|
|
|
|
}
|
|
|
|
// glob imports on things like enums aren't inlined even for local exports, so just bail
|
|
|
|
_ => None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
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
|
|
|
pub fn load_attrs<'hir>(cx: &DocContext<'hir>, did: DefId) -> Attrs<'hir> {
|
|
|
|
cx.tcx.get_attrs(did)
|
2014-05-24 11:56:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Record an external fully qualified name in the external_paths cache.
|
|
|
|
///
|
|
|
|
/// These names are used later on by HTML rendering to generate things like
|
|
|
|
/// source links back to the original item.
|
2018-12-08 20:30:23 +01:00
|
|
|
pub fn record_extern_fqn(cx: &DocContext<'_>, did: DefId, kind: clean::TypeKind) {
|
2019-08-10 13:44:23 -04:00
|
|
|
let crate_name = cx.tcx.crate_name(did.krate).to_string();
|
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-11-20 03:42:54 +02:00
|
|
|
let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| {
|
|
|
|
// extern blocks have an empty name
|
|
|
|
let s = elem.data.to_string();
|
|
|
|
if !s.is_empty() {
|
|
|
|
Some(s)
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
});
|
2018-01-06 14:01:54 +05:30
|
|
|
let fqn = if let clean::TypeKind::Macro = kind {
|
2018-07-29 15:39:51 +02:00
|
|
|
vec![crate_name, relative.last().expect("relative was empty")]
|
2018-01-06 14:01:54 +05:30
|
|
|
} else {
|
|
|
|
once(crate_name).chain(relative).collect()
|
|
|
|
};
|
2018-08-14 14:44:45 -05:00
|
|
|
|
|
|
|
if did.is_local() {
|
|
|
|
cx.renderinfo.borrow_mut().exact_paths.insert(did, fqn);
|
|
|
|
} else {
|
|
|
|
cx.renderinfo.borrow_mut().external_paths.insert(did, (fqn, kind));
|
|
|
|
}
|
2014-05-24 11:56:38 -07:00
|
|
|
}
|
|
|
|
|
2018-12-08 20:30:23 +01:00
|
|
|
pub fn build_external_trait(cx: &DocContext<'_>, did: DefId) -> clean::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
|
|
|
let auto_trait = cx.tcx.trait_def(did).has_auto_impl;
|
2016-11-20 03:42:54 +02:00
|
|
|
let trait_items = cx.tcx.associated_items(did).map(|item| item.clean(cx)).collect();
|
2017-04-24 15:20:46 +03:00
|
|
|
let predicates = cx.tcx.predicates_of(did);
|
|
|
|
let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
|
2015-04-07 00:16:35 -07:00
|
|
|
let generics = filter_non_trait_generics(did, generics);
|
|
|
|
let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
|
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
|
|
|
let is_spotlight = load_attrs(cx, did).clean(cx).has_doc_flag(sym::spotlight);
|
2018-01-23 01:04:24 +00:00
|
|
|
let is_auto = cx.tcx.trait_is_auto(did);
|
2014-05-24 11:56:38 -07:00
|
|
|
clean::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: auto_trait,
|
2017-04-24 15:20:46 +03:00
|
|
|
unsafety: cx.tcx.trait_def(did).unsafety,
|
2017-08-06 22:54:09 -07:00
|
|
|
generics,
|
2015-03-10 12:28:44 +02:00
|
|
|
items: trait_items,
|
2015-04-07 00:16:35 -07:00
|
|
|
bounds: supertrait_bounds,
|
2017-10-04 15:51:35 -05:00
|
|
|
is_spotlight,
|
2018-01-23 01:04:24 +00:00
|
|
|
is_auto,
|
2014-05-24 11:56:38 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-08 20:30:23 +01:00
|
|
|
fn build_external_function(cx: &DocContext<'_>, did: DefId) -> clean::Function {
|
2017-05-13 17:11:52 +03:00
|
|
|
let sig = cx.tcx.fn_sig(did);
|
2015-11-19 16:27:17 +01:00
|
|
|
|
2018-10-24 23:34:54 +02:00
|
|
|
let constness = if cx.tcx.is_min_const_fn(did) {
|
2015-11-19 16:27:17 +01:00
|
|
|
hir::Constness::Const
|
|
|
|
} else {
|
|
|
|
hir::Constness::NotConst
|
|
|
|
};
|
2019-09-21 03:17:57 +00:00
|
|
|
let asyncness = cx.tcx.asyncness(did);
|
2017-04-24 15:20:46 +03:00
|
|
|
let predicates = cx.tcx.predicates_of(did);
|
2019-06-21 12:23:05 +09:00
|
|
|
let (generics, decl) = clean::enter_impl_trait(cx, || {
|
|
|
|
((cx.tcx.generics_of(did), &predicates).clean(cx), (did, sig).clean(cx))
|
|
|
|
});
|
2019-03-07 16:47:40 +01:00
|
|
|
let (all_types, ret_types) = clean::get_all_types(&generics, &decl, cx);
|
2014-05-24 11:56:38 -07:00
|
|
|
clean::Function {
|
2019-03-07 02:44:28 +01:00
|
|
|
decl,
|
|
|
|
generics,
|
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-07 02:44:28 +01:00
|
|
|
},
|
|
|
|
all_types,
|
2019-03-07 16:47:40 +01:00
|
|
|
ret_types,
|
2014-05-24 11:56:38 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-08 20:30:23 +01:00
|
|
|
fn build_enum(cx: &DocContext<'_>, did: DefId) -> clean::Enum {
|
2019-03-31 15:32:25 +02:00
|
|
|
let predicates = cx.tcx.explicit_predicates_of(did);
|
2016-09-19 23:49:01 +03:00
|
|
|
|
|
|
|
clean::Enum {
|
2017-04-24 15:20:46 +03:00
|
|
|
generics: (cx.tcx.generics_of(did), &predicates).clean(cx),
|
2016-09-19 23:49:01 +03:00
|
|
|
variants_stripped: false,
|
2017-04-24 15:20:46 +03:00
|
|
|
variants: cx.tcx.adt_def(did).variants.clean(cx),
|
2016-09-19 23:49:01 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-08 20:30:23 +01:00
|
|
|
fn build_struct(cx: &DocContext<'_>, did: DefId) -> clean::Struct {
|
2019-03-31 15:32:25 +02:00
|
|
|
let predicates = cx.tcx.explicit_predicates_of(did);
|
2018-01-07 22:41:41 +01:00
|
|
|
let variant = cx.tcx.adt_def(did).non_enum_variant();
|
2014-05-24 11:56:38 -07:00
|
|
|
|
|
|
|
clean::Struct {
|
2016-09-15 00:51:46 +03:00
|
|
|
struct_type: match variant.ctor_kind {
|
|
|
|
CtorKind::Fictive => doctree::Plain,
|
|
|
|
CtorKind::Fn => doctree::Tuple,
|
|
|
|
CtorKind::Const => doctree::Unit,
|
2014-05-24 11:56:38 -07:00
|
|
|
},
|
2017-04-24 15:20:46 +03:00
|
|
|
generics: (cx.tcx.generics_of(did), &predicates).clean(cx),
|
2015-08-02 22:52:50 +03:00
|
|
|
fields: variant.fields.clean(cx),
|
2014-05-24 11:56:38 -07:00
|
|
|
fields_stripped: false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-08 20:30:23 +01:00
|
|
|
fn build_union(cx: &DocContext<'_>, did: DefId) -> clean::Union {
|
2019-03-31 15:32:25 +02:00
|
|
|
let predicates = cx.tcx.explicit_predicates_of(did);
|
2018-01-07 22:41:41 +01:00
|
|
|
let variant = cx.tcx.adt_def(did).non_enum_variant();
|
2016-08-10 21:00:17 +03:00
|
|
|
|
|
|
|
clean::Union {
|
|
|
|
struct_type: doctree::Plain,
|
2017-04-24 15:20:46 +03:00
|
|
|
generics: (cx.tcx.generics_of(did), &predicates).clean(cx),
|
2016-08-10 21:00:17 +03:00
|
|
|
fields: variant.fields.clean(cx),
|
|
|
|
fields_stripped: false,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-08 20:30:23 +01:00
|
|
|
fn build_type_alias(cx: &DocContext<'_>, did: DefId) -> clean::Typedef {
|
2019-03-31 15:32:25 +02:00
|
|
|
let predicates = cx.tcx.explicit_predicates_of(did);
|
2014-05-24 11:56:38 -07:00
|
|
|
|
2016-09-19 23:49:01 +03:00
|
|
|
clean::Typedef {
|
2017-04-24 15:20:46 +03:00
|
|
|
type_: cx.tcx.type_of(did).clean(cx),
|
|
|
|
generics: (cx.tcx.generics_of(did), &predicates).clean(cx),
|
2016-09-19 23:49:01 +03:00
|
|
|
}
|
2014-05-24 11:56:38 -07: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
|
|
|
pub fn build_impls(cx: &DocContext<'_>, did: DefId, attrs: Option<Attrs<'_>>) -> Vec<clean::Item> {
|
2016-11-20 03:42:54 +02:00
|
|
|
let tcx = cx.tcx;
|
2014-05-24 11:56:38 -07:00
|
|
|
let mut impls = Vec::new();
|
|
|
|
|
2017-04-24 17:23:36 +03:00
|
|
|
for &did in tcx.inherent_impls(did).iter() {
|
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
|
|
|
build_impl(cx, did, attrs.clone(), &mut impls);
|
2014-05-24 11:56:38 -07:00
|
|
|
}
|
2017-03-20 18:35:16 -04:00
|
|
|
|
2016-04-20 17:30:26 +02:00
|
|
|
impls
|
2014-05-24 11:56:38 -07: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
|
|
|
fn merge_attrs(cx: &DocContext<'_>, attrs: Attrs<'_>, other_attrs: Option<Attrs<'_>>
|
|
|
|
) -> clean::Attributes {
|
|
|
|
let mut merged_attrs: Vec<ast::Attribute> = Vec::with_capacity(attrs.len());
|
|
|
|
// If we have additional attributes (from a re-export),
|
|
|
|
// always insert them first. This ensure that re-export
|
|
|
|
// doc comments show up before the original doc comments
|
|
|
|
// when we render them.
|
|
|
|
if let Some(a) = other_attrs {
|
|
|
|
merged_attrs.extend(a.iter().cloned());
|
|
|
|
}
|
|
|
|
merged_attrs.extend(attrs.to_vec());
|
|
|
|
merged_attrs.clean(cx)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build_impl(cx: &DocContext<'_>, did: DefId, attrs: Option<Attrs<'_>>,
|
|
|
|
ret: &mut Vec<clean::Item>
|
|
|
|
) {
|
2016-04-07 05:59:02 +02:00
|
|
|
if !cx.renderinfo.borrow_mut().inlined.insert(did) {
|
2015-04-13 16:23:32 -07:00
|
|
|
return
|
2014-06-01 11:16:18 -07: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
|
|
|
let attrs = merge_attrs(cx, load_attrs(cx, did), attrs);
|
|
|
|
|
|
|
|
|
2016-11-20 03:42:54 +02:00
|
|
|
let tcx = cx.tcx;
|
2015-11-22 21:02:04 +02:00
|
|
|
let associated_trait = tcx.impl_trait_ref(did);
|
2016-04-15 16:34:48 +02:00
|
|
|
|
|
|
|
// Only inline impl if the implemented trait is
|
|
|
|
// reachable in rustdoc generated documentation
|
2018-08-21 16:22:20 -05:00
|
|
|
if !did.is_local() {
|
|
|
|
if let Some(traitref) = associated_trait {
|
2019-07-24 17:26:21 -04:00
|
|
|
if !cx.renderinfo.borrow().access_levels.is_public(traitref.def_id) {
|
2018-08-21 16:22:20 -05:00
|
|
|
return
|
|
|
|
}
|
2014-07-25 08:26:17 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-02-15 12:16:36 +01:00
|
|
|
let for_ = if let Some(hir_id) = tcx.hir().as_local_hir_id(did) {
|
2019-06-14 18:58:55 +02:00
|
|
|
match tcx.hir().expect_item(hir_id).node {
|
2018-08-14 15:19:15 -05:00
|
|
|
hir::ItemKind::Impl(.., ref t, _) => {
|
|
|
|
t.clean(cx)
|
|
|
|
}
|
|
|
|
_ => panic!("did given to build_impl was not an impl"),
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
tcx.type_of(did).clean(cx)
|
|
|
|
};
|
2016-04-15 16:34:48 +02:00
|
|
|
|
|
|
|
// Only inline impl if the implementing type is
|
|
|
|
// reachable in rustdoc generated documentation
|
2018-08-21 16:22:20 -05:00
|
|
|
if !did.is_local() {
|
|
|
|
if let Some(did) = for_.def_id() {
|
2019-07-24 17:26:21 -04:00
|
|
|
if !cx.renderinfo.borrow().access_levels.is_public(did) {
|
2018-08-21 16:22:20 -05:00
|
|
|
return
|
|
|
|
}
|
2016-04-15 16:34:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-03-31 15:32:25 +02:00
|
|
|
let predicates = tcx.explicit_predicates_of(did);
|
2019-02-15 12:16:36 +01:00
|
|
|
let (trait_items, generics) = if let Some(hir_id) = tcx.hir().as_local_hir_id(did) {
|
2019-06-14 18:58:55 +02:00
|
|
|
match tcx.hir().expect_item(hir_id).node {
|
2018-08-14 17:38:41 -05:00
|
|
|
hir::ItemKind::Impl(.., ref gen, _, _, ref item_ids) => {
|
|
|
|
(
|
|
|
|
item_ids.iter()
|
2018-12-04 13:45:36 +01:00
|
|
|
.map(|ii| tcx.hir().impl_item(ii.id).clean(cx))
|
2018-08-14 17:38:41 -05:00
|
|
|
.collect::<Vec<_>>(),
|
|
|
|
gen.clean(cx),
|
|
|
|
)
|
2018-08-14 16:42:34 -05:00
|
|
|
}
|
|
|
|
_ => panic!("did given to build_impl was not an impl"),
|
2014-08-04 13:56:56 -07:00
|
|
|
}
|
2018-08-14 16:42:34 -05:00
|
|
|
} else {
|
2018-08-14 17:38:41 -05:00
|
|
|
(
|
|
|
|
tcx.associated_items(did).filter_map(|item| {
|
|
|
|
if associated_trait.is_some() || item.vis == ty::Visibility::Public {
|
|
|
|
Some(item.clean(cx))
|
|
|
|
} else {
|
|
|
|
None
|
|
|
|
}
|
|
|
|
}).collect::<Vec<_>>(),
|
2019-06-21 12:23:05 +09:00
|
|
|
clean::enter_impl_trait(cx, || {
|
|
|
|
(tcx.generics_of(did), &predicates).clean(cx)
|
|
|
|
}),
|
2018-08-14 17:38:41 -05:00
|
|
|
)
|
2018-08-14 16:42:34 -05:00
|
|
|
};
|
2017-04-24 15:20:46 +03:00
|
|
|
let polarity = tcx.impl_polarity(did);
|
2015-04-13 16:23:32 -07:00
|
|
|
let trait_ = associated_trait.clean(cx).map(|bound| {
|
|
|
|
match bound {
|
2018-06-14 12:23:46 +01:00
|
|
|
clean::GenericBound::TraitBound(polyt, _) => polyt.trait_,
|
|
|
|
clean::GenericBound::Outlives(..) => unreachable!(),
|
2015-04-13 16:23:32 -07:00
|
|
|
}
|
|
|
|
});
|
2017-08-31 09:19:33 -07:00
|
|
|
if trait_.def_id() == tcx.lang_items().deref_trait() {
|
2016-03-24 06:10:52 +01:00
|
|
|
super::build_deref_target_impls(cx, &trait_items, ret);
|
2015-04-13 16:23:32 -07:00
|
|
|
}
|
2018-01-10 07:05:30 +00:00
|
|
|
if let Some(trait_did) = trait_.def_id() {
|
|
|
|
record_extern_trait(cx, trait_did);
|
|
|
|
}
|
2016-03-24 06:10:52 +01:00
|
|
|
|
|
|
|
let provided = trait_.def_id().map(|did| {
|
2016-11-20 03:42:54 +02:00
|
|
|
tcx.provided_trait_methods(did)
|
2018-06-14 12:23:46 +01:00
|
|
|
.into_iter()
|
2018-06-10 22:24:24 +03:00
|
|
|
.map(|meth| meth.ident.to_string())
|
2018-06-14 12:23:46 +01:00
|
|
|
.collect()
|
2018-10-16 16:57:53 +02:00
|
|
|
}).unwrap_or_default();
|
2016-03-24 06:10:52 +01:00
|
|
|
|
2018-08-14 14:41:07 -05:00
|
|
|
debug!("build_impl: impl {:?} for {:?}", trait_.def_id(), for_.def_id());
|
|
|
|
|
2015-04-13 16:23:32 -07:00
|
|
|
ret.push(clean::Item {
|
2014-05-24 11:56:38 -07:00
|
|
|
inner: clean::ImplItem(clean::Impl {
|
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
|
|
|
unsafety: hir::Unsafety::Normal,
|
2018-08-14 17:38:41 -05:00
|
|
|
generics,
|
2016-03-24 06:10:52 +01:00
|
|
|
provided_trait_methods: provided,
|
2017-08-06 22:54:09 -07:00
|
|
|
trait_,
|
|
|
|
for_,
|
2014-08-04 13:56:56 -07:00
|
|
|
items: trait_items,
|
2016-09-19 23:49:01 +03:00
|
|
|
polarity: Some(polarity.clean(cx)),
|
2018-02-10 14:34:46 -05:00
|
|
|
synthetic: false,
|
2018-07-27 22:59:16 +02:00
|
|
|
blanket_impl: None,
|
2014-05-24 11:56:38 -07:00
|
|
|
}),
|
2016-11-29 08:15:16 +02:00
|
|
|
source: tcx.def_span(did).clean(cx),
|
2014-05-24 11:56:38 -07:00
|
|
|
name: None,
|
2017-08-06 22:54:09 -07:00
|
|
|
attrs,
|
2019-09-12 22:32:12 -04:00
|
|
|
visibility: clean::Inherited,
|
2016-03-17 00:15:31 +02:00
|
|
|
stability: tcx.lookup_stability(did).clean(cx),
|
|
|
|
deprecation: tcx.lookup_deprecation(did).clean(cx),
|
2014-05-24 11:56:38 -07:00
|
|
|
def_id: did,
|
2014-07-25 08:26:17 -07:00
|
|
|
});
|
2016-02-26 01:45:24 +01:00
|
|
|
}
|
2014-07-25 08:26:17 -07:00
|
|
|
|
2019-02-23 17:02:57 +09:00
|
|
|
fn build_module(
|
2018-12-08 20:30:23 +01:00
|
|
|
cx: &DocContext<'_>,
|
2019-02-23 17:02:57 +09:00
|
|
|
did: DefId,
|
|
|
|
visited: &mut FxHashSet<DefId>
|
|
|
|
) -> clean::Module {
|
2014-05-24 11:56:38 -07:00
|
|
|
let mut items = Vec::new();
|
2018-04-28 21:56:38 +02:00
|
|
|
fill_in(cx, did, &mut items, visited);
|
2014-07-25 10:37:23 -07:00
|
|
|
return clean::Module {
|
2017-08-06 22:54:09 -07:00
|
|
|
items,
|
2014-07-25 10:37:23 -07:00
|
|
|
is_crate: false,
|
|
|
|
};
|
2014-05-24 11:56:38 -07:00
|
|
|
|
2018-12-08 20:30:23 +01:00
|
|
|
fn fill_in(cx: &DocContext<'_>, did: DefId, items: &mut Vec<clean::Item>,
|
2018-04-28 21:56:38 +02:00
|
|
|
visited: &mut FxHashSet<DefId>) {
|
2018-01-12 16:41:25 -05:00
|
|
|
// If we're re-exporting a re-export it may actually re-export something in
|
2015-04-07 16:18:49 -07:00
|
|
|
// two namespaces, so the target may be listed twice. Make sure we only
|
|
|
|
// visit each node at most once.
|
2017-08-31 08:07:39 -07:00
|
|
|
for &item in cx.tcx.item_children(did).iter() {
|
2019-04-20 19:36:05 +03:00
|
|
|
let def_id = item.res.def_id();
|
2017-12-04 21:17:42 -08:00
|
|
|
if item.vis == ty::Visibility::Public {
|
2018-04-28 21:56:38 +02:00
|
|
|
if did == def_id || !visited.insert(def_id) { continue }
|
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(i) = try_inline(cx, item.res, item.ident.name, None, visited) {
|
2016-09-15 00:51:46 +03:00
|
|
|
items.extend(i)
|
2014-05-24 11:56:38 -07:00
|
|
|
}
|
|
|
|
}
|
2015-11-22 21:02:04 +02:00
|
|
|
}
|
2014-05-24 11:56:38 -07:00
|
|
|
}
|
|
|
|
}
|
2014-06-05 17:20:59 -07:00
|
|
|
|
2018-12-08 20:30:23 +01:00
|
|
|
pub fn print_inlined_const(cx: &DocContext<'_>, did: DefId) -> String {
|
2019-03-04 09:00:30 +01:00
|
|
|
if let Some(node_id) = cx.tcx.hir().as_local_hir_id(did) {
|
|
|
|
cx.tcx.hir().hir_to_pretty_string(node_id)
|
2018-08-07 11:30:57 -05:00
|
|
|
} else {
|
|
|
|
cx.tcx.rendered_const(did)
|
|
|
|
}
|
2016-12-27 11:15:26 +02:00
|
|
|
}
|
|
|
|
|
2018-12-08 20:30:23 +01:00
|
|
|
fn build_const(cx: &DocContext<'_>, did: DefId) -> clean::Constant {
|
2014-12-12 04:13:36 -08:00
|
|
|
clean::Constant {
|
2017-04-24 15:20:46 +03:00
|
|
|
type_: cx.tcx.type_of(did).clean(cx),
|
2016-12-27 11:15:26 +02:00
|
|
|
expr: print_inlined_const(cx, did)
|
2014-12-12 04:13:36 -08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-08 20:30:23 +01:00
|
|
|
fn build_static(cx: &DocContext<'_>, did: DefId, mutable: bool) -> clean::Static {
|
2014-06-05 17:20:59 -07:00
|
|
|
clean::Static {
|
2017-04-24 15:20:46 +03:00
|
|
|
type_: cx.tcx.type_of(did).clean(cx),
|
2014-06-05 17:20:59 -07:00
|
|
|
mutability: if mutable {clean::Mutable} else {clean::Immutable},
|
|
|
|
expr: "\n\n\n".to_string(), // trigger the "[definition]" links
|
|
|
|
}
|
|
|
|
}
|
2015-04-07 00:16:35 -07:00
|
|
|
|
2018-12-08 20:30:23 +01:00
|
|
|
fn build_macro(cx: &DocContext<'_>, did: DefId, name: ast::Name) -> clean::ItemEnum {
|
2018-06-17 14:54:28 -05:00
|
|
|
let imported_from = cx.tcx.original_crate_name(did.krate);
|
2018-09-25 14:56:43 -05:00
|
|
|
match cx.cstore.load_macro_untracked(did, cx.sess()) {
|
|
|
|
LoadedMacro::MacroDef(def) => {
|
|
|
|
let matchers: hir::HirVec<Span> = if let ast::ItemKind::MacroDef(ref def) = def.node {
|
|
|
|
let tts: Vec<_> = def.stream().into_trees().collect();
|
|
|
|
tts.chunks(4).map(|arm| arm[0].span()).collect()
|
|
|
|
} else {
|
|
|
|
unreachable!()
|
|
|
|
};
|
|
|
|
|
|
|
|
let source = format!("macro_rules! {} {{\n{}}}",
|
|
|
|
name.clean(cx),
|
|
|
|
matchers.iter().map(|span| {
|
|
|
|
format!(" {} => {{ ... }};\n", span.to_src(cx))
|
|
|
|
}).collect::<String>());
|
|
|
|
|
|
|
|
clean::MacroItem(clean::Macro {
|
|
|
|
source,
|
|
|
|
imported_from: Some(imported_from).clean(cx),
|
|
|
|
})
|
|
|
|
}
|
|
|
|
LoadedMacro::ProcMacro(ext) => {
|
|
|
|
clean::ProcMacroItem(clean::ProcMacro {
|
2019-06-16 18:58:39 +03:00
|
|
|
kind: ext.macro_kind(),
|
|
|
|
helpers: ext.helper_attrs.clean(cx),
|
2018-09-25 14:56:43 -05:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
2018-06-17 14:54:28 -05:00
|
|
|
}
|
|
|
|
|
2015-04-07 00:16:35 -07:00
|
|
|
/// A trait's generics clause actually contains all of the predicates for all of
|
|
|
|
/// its associated types as well. We specifically move these clauses to the
|
2017-08-11 00:16:18 +02:00
|
|
|
/// associated types instead when displaying, so when we're generating the
|
2015-04-07 00:16:35 -07:00
|
|
|
/// generics for the trait itself we need to be sure to remove them.
|
2016-06-13 20:10:32 +03:00
|
|
|
/// We also need to remove the implied "recursive" Self: Trait bound.
|
2015-04-07 00:16:35 -07:00
|
|
|
///
|
|
|
|
/// The inverse of this filtering logic can be found in the `Clean`
|
|
|
|
/// implementation for `AssociatedType`
|
2017-12-17 14:08:09 +01:00
|
|
|
fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean::Generics {
|
2016-06-13 20:10:32 +03:00
|
|
|
for pred in &mut g.where_predicates {
|
|
|
|
match *pred {
|
|
|
|
clean::WherePredicate::BoundPredicate {
|
|
|
|
ty: clean::Generic(ref s),
|
|
|
|
ref mut bounds
|
|
|
|
} if *s == "Self" => {
|
|
|
|
bounds.retain(|bound| {
|
|
|
|
match *bound {
|
2018-06-14 12:08:58 +01:00
|
|
|
clean::GenericBound::TraitBound(clean::PolyTrait {
|
2016-06-13 20:10:32 +03:00
|
|
|
trait_: clean::ResolvedPath { did, .. },
|
|
|
|
..
|
|
|
|
}, _) => did != trait_did,
|
|
|
|
_ => true
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
_ => {}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-04-07 00:16:35 -07:00
|
|
|
g.where_predicates.retain(|pred| {
|
|
|
|
match *pred {
|
|
|
|
clean::WherePredicate::BoundPredicate {
|
|
|
|
ty: clean::QPath {
|
|
|
|
self_type: box clean::Generic(ref s),
|
|
|
|
trait_: box clean::ResolvedPath { did, .. },
|
|
|
|
name: ref _name,
|
2016-06-13 20:10:32 +03:00
|
|
|
}, ref bounds
|
|
|
|
} => !(*s == "Self" && did == trait_did) && !bounds.is_empty(),
|
2015-04-07 00:16:35 -07:00
|
|
|
_ => true,
|
|
|
|
}
|
|
|
|
});
|
2016-10-01 16:47:43 -04:00
|
|
|
g
|
2015-04-07 00:16:35 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Supertrait bounds for a trait are also listed in the generics coming from
|
|
|
|
/// the metadata for a crate, so we want to separate those out and create a new
|
|
|
|
/// list of explicit supertrait bounds to render nicely.
|
|
|
|
fn separate_supertrait_bounds(mut g: clean::Generics)
|
2018-06-14 12:08:58 +01:00
|
|
|
-> (clean::Generics, Vec<clean::GenericBound>) {
|
2015-04-07 00:16:35 -07:00
|
|
|
let mut ty_bounds = Vec::new();
|
|
|
|
g.where_predicates.retain(|pred| {
|
|
|
|
match *pred {
|
|
|
|
clean::WherePredicate::BoundPredicate {
|
|
|
|
ty: clean::Generic(ref s),
|
|
|
|
ref bounds
|
|
|
|
} if *s == "Self" => {
|
|
|
|
ty_bounds.extend(bounds.iter().cloned());
|
|
|
|
false
|
|
|
|
}
|
|
|
|
_ => true,
|
|
|
|
}
|
|
|
|
});
|
|
|
|
(g, ty_bounds)
|
|
|
|
}
|
2018-01-10 07:05:30 +00:00
|
|
|
|
2018-12-08 20:30:23 +01:00
|
|
|
pub fn record_extern_trait(cx: &DocContext<'_>, did: DefId) {
|
2018-08-14 12:08:12 -05:00
|
|
|
if did.is_local() {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-02-21 18:33:42 -06:00
|
|
|
{
|
2019-08-10 15:20:21 -04:00
|
|
|
if cx.external_traits.borrow().contains_key(&did) ||
|
2018-09-01 21:20:39 -05:00
|
|
|
cx.active_extern_traits.borrow().contains(&did)
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2018-02-21 17:44:49 -06:00
|
|
|
}
|
|
|
|
|
2019-08-10 17:10:13 -04:00
|
|
|
cx.active_extern_traits.borrow_mut().insert(did);
|
2018-02-21 18:33:42 -06:00
|
|
|
|
2018-08-14 14:43:03 -05:00
|
|
|
debug!("record_extern_trait: {:?}", did);
|
2018-02-21 17:44:49 -06:00
|
|
|
let trait_ = build_external_trait(cx, did);
|
|
|
|
|
2019-08-10 17:10:13 -04:00
|
|
|
cx.external_traits.borrow_mut().insert(did, trait_);
|
|
|
|
cx.active_extern_traits.borrow_mut().remove(&did);
|
2018-01-10 07:05:30 +00:00
|
|
|
}
|