mirror of
https://github.com/rust-lang/rust.git
synced 2025-04-13 04:26:48 +00:00
Auto merge of #48399 - GuillaumeGomez:rollup, r=GuillaumeGomez
Rollup of 12 pull requests - Successful merges: #47379, #47833, #48106, #48198, #48314, #48325, #48335, #48352, #48354, #48360, #48382, #48397 - Failed merges:
This commit is contained in:
commit
b1f8e6fb06
6
.mailmap
6
.mailmap
@ -95,9 +95,9 @@ Herman J. Radtke III <herman@hermanradtke.com> Herman J. Radtke III <hermanradtk
|
||||
Ilyong Cho <ilyoan@gmail.com>
|
||||
Ivan Ivaschenko <defuz.net@gmail.com>
|
||||
J. J. Weber <jjweber@gmail.com>
|
||||
Jakub Bukaj <jakub@jakub.cc>
|
||||
Jakub Bukaj <jakub@jakub.cc> <jakubw@jakubw.net>
|
||||
Jakub Bukaj <jakub@jakub.cc> Jakub Bukaj <jakub.bukaj@yahoo.com>
|
||||
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub@jakub.cc>
|
||||
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakubw@jakubw.net>
|
||||
Jakub Adam Wieczorek <jakub.adam.wieczorek@gmail.com> <jakub.bukaj@yahoo.com>
|
||||
James Deng <cnjamesdeng@gmail.com> <cnJamesDeng@gmail.com>
|
||||
James Miller <bladeon@gmail.com> <james@aatch.net>
|
||||
James Perry <james.austin.perry@gmail.com>
|
||||
|
8
src/Cargo.lock
generated
8
src/Cargo.lock
generated
@ -1086,7 +1086,7 @@ dependencies = [
|
||||
"log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"memchr 2.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"open 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pulldown-cmark 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"regex 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"serde_derive 1.0.27 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -1383,7 +1383,7 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "pulldown-cmark"
|
||||
version = "0.1.0"
|
||||
version = "0.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
dependencies = [
|
||||
"bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
@ -2104,7 +2104,7 @@ dependencies = [
|
||||
name = "rustdoc"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"pulldown-cmark 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
"tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||
]
|
||||
|
||||
@ -2886,7 +2886,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
"checksum pest 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0a6dda33d67c26f0aac90d324ab2eb7239c819fc7b2552fe9faa4fe88441edc8"
|
||||
"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903"
|
||||
"checksum pulldown-cmark 0.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "378e941dbd392c101f2cb88097fa4d7167bc421d4b88de3ff7dbee503bc3233b"
|
||||
"checksum pulldown-cmark 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a656fdb8b6848f896df5e478a0eb9083681663e37dcb77dd16981ff65329fe8b"
|
||||
"checksum pulldown-cmark 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d6fdf85cda6cadfae5428a54661d431330b312bc767ddbc57adbedc24da66e32"
|
||||
"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4"
|
||||
"checksum quine-mc_cluskey 0.2.4 (registry+https://github.com/rust-lang/crates.io-index)" = "07589615d719a60c8dd8a4622e7946465dfef20d1a428f969e3443e7386d5f45"
|
||||
"checksum quote 0.3.15 (registry+https://github.com/rust-lang/crates.io-index)" = "7a6e920b65c65f10b2ae65c831a81a073a89edd28c7cce89475bff467ab4167a"
|
||||
|
@ -343,7 +343,7 @@ impl Ordering {
|
||||
/// v.sort_by_key(|&num| (num > 3, Reverse(num)));
|
||||
/// assert_eq!(v, vec![3, 2, 1, 6, 5, 4]);
|
||||
/// ```
|
||||
#[derive(PartialEq, Eq, Debug)]
|
||||
#[derive(PartialEq, Eq, Debug, Copy, Clone)]
|
||||
#[stable(feature = "reverse_cmp_key", since = "1.19.0")]
|
||||
pub struct Reverse<T>(#[stable(feature = "reverse_cmp_key", since = "1.19.0")] pub T);
|
||||
|
||||
|
@ -168,7 +168,7 @@ pub trait Iterator {
|
||||
/// This function might panic if the iterator has more than [`usize::MAX`]
|
||||
/// elements.
|
||||
///
|
||||
/// [`usize::MAX`]: ../../std/isize/constant.MAX.html
|
||||
/// [`usize::MAX`]: ../../std/usize/constant.MAX.html
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
@ -1209,7 +1209,7 @@ Basic usage:
|
||||
```
|
||||
", $Feature, "let x: ", stringify!($SelfT), " = 2; // or any other integer type
|
||||
|
||||
assert_eq!(x.pow(4), 16);",
|
||||
assert_eq!(x.pow(5), 32);",
|
||||
$EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
@ -2364,7 +2364,7 @@ assert_eq!(0x10", stringify!($SelfT), ".overflowing_shr(132), (0x1, true));", $E
|
||||
Basic usage:
|
||||
|
||||
```
|
||||
", $Feature, "assert_eq!(2", stringify!($SelfT), ".pow(4), 16);", $EndFeature, "
|
||||
", $Feature, "assert_eq!(2", stringify!($SelfT), ".pow(5), 32);", $EndFeature, "
|
||||
```"),
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[inline]
|
||||
|
@ -72,6 +72,10 @@ impl DefPathTable {
|
||||
index
|
||||
}
|
||||
|
||||
pub fn next_id(&self, address_space: DefIndexAddressSpace) -> DefIndex {
|
||||
DefIndex::from_array_index(self.index_to_key[address_space.index()].len(), address_space)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub fn def_key(&self, index: DefIndex) -> DefKey {
|
||||
self.index_to_key[index.address_space().index()]
|
||||
|
@ -180,7 +180,7 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
|
||||
// for each body-id in this map, which will process the
|
||||
// obligations within. This is expected to be done 'late enough'
|
||||
// that all type inference variables have been bound and so forth.
|
||||
region_obligations: RefCell<Vec<(ast::NodeId, RegionObligation<'tcx>)>>,
|
||||
pub region_obligations: RefCell<Vec<(ast::NodeId, RegionObligation<'tcx>)>>,
|
||||
}
|
||||
|
||||
/// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
|
||||
@ -1555,11 +1555,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
|
||||
InferOk { value, obligations }
|
||||
}
|
||||
|
||||
fn borrow_region_constraints(&self) -> RefMut<'_, RegionConstraintCollector<'tcx>> {
|
||||
pub fn borrow_region_constraints(&self) -> RefMut<'_, RegionConstraintCollector<'tcx>> {
|
||||
RefMut::map(
|
||||
self.region_constraints.borrow_mut(),
|
||||
|c| c.as_mut().expect("region constraints already solved"))
|
||||
}
|
||||
|
||||
/// Clears the selection, evaluation, and projection cachesThis is useful when
|
||||
/// repeatedly attemping to select an Obligation while changing only
|
||||
/// its ParamEnv, since FulfillmentContext doesn't use 'probe'
|
||||
pub fn clear_caches(&self) {
|
||||
self.selection_cache.clear();
|
||||
self.evaluation_cache.clear();
|
||||
self.projection_cache.borrow_mut().clear();
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'gcx, 'tcx> TypeTrace<'tcx> {
|
||||
|
@ -82,7 +82,7 @@ pub type VarOrigins = IndexVec<RegionVid, RegionVariableOrigin>;
|
||||
/// Describes constraints between the region variables and other
|
||||
/// regions, as well as other conditions that must be verified, or
|
||||
/// assumptions that can be made.
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct RegionConstraintData<'tcx> {
|
||||
/// Constraints of the form `A <= B`, where either `A` or `B` can
|
||||
/// be a region variable (or neither, as it happens).
|
||||
@ -142,7 +142,7 @@ pub enum Constraint<'tcx> {
|
||||
/// outlive `RS`. Therefore verify that `R <= RS[i]` for some
|
||||
/// `i`. Inference variables may be involved (but this verification
|
||||
/// step doesn't influence inference).
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Verify<'tcx> {
|
||||
pub kind: GenericKind<'tcx>,
|
||||
pub origin: SubregionOrigin<'tcx>,
|
||||
@ -159,7 +159,7 @@ pub enum GenericKind<'tcx> {
|
||||
/// When we introduce a verification step, we wish to test that a
|
||||
/// particular region (let's call it `'min`) meets some bound.
|
||||
/// The bound is described the by the following grammar:
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub enum VerifyBound<'tcx> {
|
||||
/// B = exists {R} --> some 'r in {R} must outlive 'min
|
||||
///
|
||||
@ -288,6 +288,10 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
|
||||
&self.var_origins
|
||||
}
|
||||
|
||||
pub fn region_constraint_data(&self) -> &RegionConstraintData<'tcx> {
|
||||
&self.data
|
||||
}
|
||||
|
||||
/// Once all the constraints have been gathered, extract out the final data.
|
||||
///
|
||||
/// Not legal during a snapshot.
|
||||
|
@ -32,8 +32,8 @@ use syntax_pos::{Span, DUMMY_SP};
|
||||
pub use self::coherence::{orphan_check, overlapping_impls, OrphanCheckErr, OverlapResult};
|
||||
pub use self::fulfill::FulfillmentContext;
|
||||
pub use self::project::MismatchedProjectionTypes;
|
||||
pub use self::project::{normalize, normalize_projection_type, Normalized};
|
||||
pub use self::project::{ProjectionCache, ProjectionCacheSnapshot, Reveal};
|
||||
pub use self::project::{normalize, normalize_projection_type, poly_project_and_unify_type};
|
||||
pub use self::project::{ProjectionCache, ProjectionCacheSnapshot, Reveal, Normalized};
|
||||
pub use self::object_safety::ObjectSafetyViolation;
|
||||
pub use self::object_safety::MethodViolationCode;
|
||||
pub use self::on_unimplemented::{OnUnimplementedDirective, OnUnimplementedNote};
|
||||
|
@ -1596,6 +1596,10 @@ impl<'tcx> ProjectionCache<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.map.clear();
|
||||
}
|
||||
|
||||
pub fn snapshot(&mut self) -> ProjectionCacheSnapshot {
|
||||
ProjectionCacheSnapshot { snapshot: self.map.snapshot() }
|
||||
}
|
||||
|
@ -93,6 +93,11 @@ pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
|
||||
inferred_obligations: SnapshotVec<InferredObligationsSnapshotVecDelegate<'tcx>>,
|
||||
|
||||
intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>,
|
||||
|
||||
/// Controls whether or not to filter out negative impls when selecting.
|
||||
/// This is used in librustdoc to distinguish between the lack of an impl
|
||||
/// and a negative impl
|
||||
allow_negative_impls: bool
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
@ -424,6 +429,7 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
intercrate: None,
|
||||
inferred_obligations: SnapshotVec::new(),
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls: false,
|
||||
}
|
||||
}
|
||||
|
||||
@ -436,6 +442,20 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
intercrate: Some(mode),
|
||||
inferred_obligations: SnapshotVec::new(),
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_negative(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
|
||||
allow_negative_impls: bool) -> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
debug!("with_negative({:?})", allow_negative_impls);
|
||||
SelectionContext {
|
||||
infcx,
|
||||
freshener: infcx.freshener(),
|
||||
intercrate: None,
|
||||
inferred_obligations: SnapshotVec::new(),
|
||||
intercrate_ambiguity_causes: None,
|
||||
allow_negative_impls,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1086,7 +1106,8 @@ impl<'cx, 'gcx, 'tcx> SelectionContext<'cx, 'gcx, 'tcx> {
|
||||
fn filter_negative_impls(&self, candidate: SelectionCandidate<'tcx>)
|
||||
-> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
|
||||
if let ImplCandidate(def_id) = candidate {
|
||||
if self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative {
|
||||
if !self.allow_negative_impls &&
|
||||
self.tcx().impl_polarity(def_id) == hir::ImplPolarity::Negative {
|
||||
return Err(Unimplemented)
|
||||
}
|
||||
}
|
||||
@ -3337,6 +3358,10 @@ impl<'tcx> SelectionCache<'tcx> {
|
||||
hashmap: RefCell::new(FxHashMap())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
*self.hashmap.borrow_mut() = FxHashMap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> EvaluationCache<'tcx> {
|
||||
@ -3345,6 +3370,10 @@ impl<'tcx> EvaluationCache<'tcx> {
|
||||
hashmap: RefCell::new(FxHashMap())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&self) {
|
||||
*self.hashmap.borrow_mut() = FxHashMap()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'o,'tcx> TraitObligationStack<'o,'tcx> {
|
||||
|
@ -45,6 +45,11 @@ impl<K, V> SnapshotMap<K, V>
|
||||
}
|
||||
}
|
||||
|
||||
pub fn clear(&mut self) {
|
||||
self.map.clear();
|
||||
self.undo_log.clear();
|
||||
}
|
||||
|
||||
pub fn insert(&mut self, key: K, value: V) -> bool {
|
||||
match self.map.insert(key.clone(), value) {
|
||||
None => {
|
||||
|
@ -325,6 +325,8 @@ Erroneous code example:
|
||||
extern crate core;
|
||||
|
||||
struct core;
|
||||
|
||||
fn main() {}
|
||||
```
|
||||
|
||||
There are two possible solutions:
|
||||
|
@ -337,7 +337,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
|
||||
scope_expr_id,
|
||||
span,
|
||||
&format!("the type of this value must be known in this context"));
|
||||
&format!("type annotations needed"));
|
||||
}
|
||||
} else {
|
||||
let t = self.structurally_resolved_type(span, final_ty);
|
||||
|
@ -5052,9 +5052,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
|
||||
ty
|
||||
} else {
|
||||
if !self.is_tainted_by_errors() {
|
||||
type_error_struct!(self.tcx.sess, sp, ty, E0619,
|
||||
"the type of this value must be known in this context")
|
||||
.emit();
|
||||
self.need_type_info((**self).body_id, sp, ty);
|
||||
}
|
||||
self.demand_suptype(sp, self.tcx.types.err, ty);
|
||||
self.tcx.types.err
|
||||
|
@ -4368,12 +4368,13 @@ i_am_a_function();
|
||||
"##,
|
||||
|
||||
E0619: r##"
|
||||
#### Note: this error code is no longer emitted by the compiler.
|
||||
The type-checker needed to know the type of an expression, but that type had not
|
||||
yet been inferred.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0619
|
||||
```compile_fail
|
||||
let mut x = vec![];
|
||||
match x.pop() {
|
||||
Some(v) => {
|
||||
|
@ -10,5 +10,5 @@ path = "lib.rs"
|
||||
doctest = false
|
||||
|
||||
[dependencies]
|
||||
pulldown-cmark = { version = "0.1.0", default-features = false }
|
||||
pulldown-cmark = { version = "0.1.2", default-features = false }
|
||||
tempdir = "0.3"
|
||||
|
1492
src/librustdoc/clean/auto_trait.rs
Normal file
1492
src/librustdoc/clean/auto_trait.rs
Normal file
File diff suppressed because it is too large
Load Diff
@ -25,7 +25,7 @@ use syntax_pos::Span;
|
||||
|
||||
use html::escape::Escape;
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, PartialEq)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq, Hash)]
|
||||
pub enum Cfg {
|
||||
/// Accepts all configurations.
|
||||
True,
|
||||
|
@ -12,8 +12,8 @@
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use std::io;
|
||||
use std::iter::once;
|
||||
use std::rc::Rc;
|
||||
use std::iter::once;
|
||||
|
||||
use syntax::ast;
|
||||
use rustc::hir;
|
||||
@ -25,7 +25,7 @@ use rustc::util::nodemap::FxHashSet;
|
||||
|
||||
use core::{DocContext, DocAccessLevels};
|
||||
use doctree;
|
||||
use clean::{self, GetDefId};
|
||||
use clean::{self, GetDefId, get_auto_traits_with_def_id};
|
||||
|
||||
use super::Clean;
|
||||
|
||||
@ -50,7 +50,7 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name)
|
||||
let inner = match def {
|
||||
Def::Trait(did) => {
|
||||
record_extern_fqn(cx, did, clean::TypeKind::Trait);
|
||||
ret.extend(build_impls(cx, did));
|
||||
ret.extend(build_impls(cx, did, false));
|
||||
clean::TraitItem(build_external_trait(cx, did))
|
||||
}
|
||||
Def::Fn(did) => {
|
||||
@ -59,27 +59,27 @@ pub fn try_inline(cx: &DocContext, def: Def, name: ast::Name)
|
||||
}
|
||||
Def::Struct(did) => {
|
||||
record_extern_fqn(cx, did, clean::TypeKind::Struct);
|
||||
ret.extend(build_impls(cx, did));
|
||||
ret.extend(build_impls(cx, did, true));
|
||||
clean::StructItem(build_struct(cx, did))
|
||||
}
|
||||
Def::Union(did) => {
|
||||
record_extern_fqn(cx, did, clean::TypeKind::Union);
|
||||
ret.extend(build_impls(cx, did));
|
||||
ret.extend(build_impls(cx, did, true));
|
||||
clean::UnionItem(build_union(cx, did))
|
||||
}
|
||||
Def::TyAlias(did) => {
|
||||
record_extern_fqn(cx, did, clean::TypeKind::Typedef);
|
||||
ret.extend(build_impls(cx, did));
|
||||
ret.extend(build_impls(cx, did, false));
|
||||
clean::TypedefItem(build_type_alias(cx, did), false)
|
||||
}
|
||||
Def::Enum(did) => {
|
||||
record_extern_fqn(cx, did, clean::TypeKind::Enum);
|
||||
ret.extend(build_impls(cx, did));
|
||||
ret.extend(build_impls(cx, did, true));
|
||||
clean::EnumItem(build_enum(cx, did))
|
||||
}
|
||||
Def::TyForeign(did) => {
|
||||
record_extern_fqn(cx, did, clean::TypeKind::Foreign);
|
||||
ret.extend(build_impls(cx, did));
|
||||
ret.extend(build_impls(cx, did, false));
|
||||
clean::ForeignTypeItem
|
||||
}
|
||||
// Never inline enum variants but leave them shown as re-exports.
|
||||
@ -125,6 +125,11 @@ pub fn load_attrs(cx: &DocContext, did: DefId) -> clean::Attributes {
|
||||
/// These names are used later on by HTML rendering to generate things like
|
||||
/// source links back to the original item.
|
||||
pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
|
||||
if did.is_local() {
|
||||
debug!("record_extern_fqn(did={:?}, kind+{:?}): def_id is local, aborting", did, kind);
|
||||
return;
|
||||
}
|
||||
|
||||
let crate_name = cx.tcx.crate_name(did.krate).to_string();
|
||||
let relative = cx.tcx.def_path(did).data.into_iter().filter_map(|elem| {
|
||||
// extern blocks have an empty name
|
||||
@ -144,6 +149,7 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
|
||||
}
|
||||
|
||||
pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait {
|
||||
let auto_trait = cx.tcx.trait_def(did).has_auto_impl;
|
||||
let trait_items = cx.tcx.associated_items(did).map(|item| item.clean(cx)).collect();
|
||||
let predicates = cx.tcx.predicates_of(did);
|
||||
let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
|
||||
@ -152,6 +158,7 @@ pub fn build_external_trait(cx: &DocContext, did: DefId) -> clean::Trait {
|
||||
let is_spotlight = load_attrs(cx, did).has_doc_flag("spotlight");
|
||||
let is_auto = cx.tcx.trait_is_auto(did);
|
||||
clean::Trait {
|
||||
auto: auto_trait,
|
||||
unsafety: cx.tcx.trait_def(did).unsafety,
|
||||
generics,
|
||||
items: trait_items,
|
||||
@ -227,7 +234,7 @@ fn build_type_alias(cx: &DocContext, did: DefId) -> clean::Typedef {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_impls(cx: &DocContext, did: DefId) -> Vec<clean::Item> {
|
||||
pub fn build_impls(cx: &DocContext, did: DefId, auto_traits: bool) -> Vec<clean::Item> {
|
||||
let tcx = cx.tcx;
|
||||
let mut impls = Vec::new();
|
||||
|
||||
@ -235,6 +242,16 @@ pub fn build_impls(cx: &DocContext, did: DefId) -> Vec<clean::Item> {
|
||||
build_impl(cx, did, &mut impls);
|
||||
}
|
||||
|
||||
if auto_traits {
|
||||
let auto_impls = get_auto_traits_with_def_id(cx, did);
|
||||
let mut renderinfo = cx.renderinfo.borrow_mut();
|
||||
|
||||
let new_impls: Vec<clean::Item> = auto_impls.into_iter()
|
||||
.filter(|i| renderinfo.inlined.insert(i.def_id)).collect();
|
||||
|
||||
impls.extend(new_impls);
|
||||
}
|
||||
|
||||
// If this is the first time we've inlined something from another crate, then
|
||||
// we inline *all* impls from all the crates into this crate. Note that there's
|
||||
// currently no way for us to filter this based on type, and we likely need
|
||||
@ -347,13 +364,14 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
|
||||
|
||||
ret.push(clean::Item {
|
||||
inner: clean::ImplItem(clean::Impl {
|
||||
unsafety: hir::Unsafety::Normal, // FIXME: this should be decoded
|
||||
unsafety: hir::Unsafety::Normal,
|
||||
generics: (tcx.generics_of(did), &predicates).clean(cx),
|
||||
provided_trait_methods: provided,
|
||||
trait_,
|
||||
for_,
|
||||
generics: (tcx.generics_of(did), &predicates).clean(cx),
|
||||
items: trait_items,
|
||||
polarity: Some(polarity.clean(cx)),
|
||||
synthetic: false,
|
||||
}),
|
||||
source: tcx.def_span(did).clean(cx),
|
||||
name: None,
|
||||
|
@ -26,31 +26,41 @@ use syntax::codemap::Spanned;
|
||||
use syntax::feature_gate::UnstableFeatures;
|
||||
use syntax::ptr::P;
|
||||
use syntax::symbol::keywords;
|
||||
use syntax::symbol::Symbol;
|
||||
use syntax_pos::{self, DUMMY_SP, Pos, FileName};
|
||||
|
||||
use rustc::middle::const_val::ConstVal;
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::middle::resolve_lifetime as rl;
|
||||
use rustc::ty::fold::TypeFolder;
|
||||
use rustc::middle::lang_items;
|
||||
use rustc::hir::def::{Def, CtorKind};
|
||||
use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use rustc::hir::{self, HirVec};
|
||||
use rustc::hir::def::{self, Def, CtorKind};
|
||||
use rustc::hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
|
||||
use rustc::hir::def_id::DefIndexAddressSpace;
|
||||
use rustc::traits;
|
||||
use rustc::ty::subst::Substs;
|
||||
use rustc::ty::{self, Ty, AdtKind};
|
||||
use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
|
||||
use rustc::middle::stability;
|
||||
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
||||
use rustc_typeck::hir_ty_to_ty;
|
||||
|
||||
use rustc::hir;
|
||||
use rustc::infer::{InferCtxt, RegionObligation};
|
||||
use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
|
||||
use rustc::traits::*;
|
||||
use std::collections::hash_map::Entry;
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt;
|
||||
|
||||
use rustc_const_math::ConstInt;
|
||||
use std::default::Default;
|
||||
use std::{mem, slice, vec};
|
||||
use std::iter::FromIterator;
|
||||
use std::iter::{FromIterator, once};
|
||||
use std::rc::Rc;
|
||||
use std::cell::RefCell;
|
||||
use std::sync::Arc;
|
||||
use std::u32;
|
||||
|
||||
use core::DocContext;
|
||||
use core::{self, DocContext};
|
||||
use doctree;
|
||||
use visit_ast;
|
||||
use html::item_type::ItemType;
|
||||
@ -59,8 +69,14 @@ use html::markdown::markdown_links;
|
||||
pub mod inline;
|
||||
pub mod cfg;
|
||||
mod simplify;
|
||||
mod auto_trait;
|
||||
|
||||
use self::cfg::Cfg;
|
||||
use self::auto_trait::AutoTraitFinder;
|
||||
|
||||
thread_local!(static MAX_DEF_ID: RefCell<FxHashMap<CrateNum, DefId>> = RefCell::new(FxHashMap()));
|
||||
|
||||
const FN_OUTPUT_NAME: &'static str = "Output";
|
||||
|
||||
// extract the stability index for a node from tcx, if possible
|
||||
fn get_stability(cx: &DocContext, def_id: DefId) -> Option<Stability> {
|
||||
@ -282,7 +298,7 @@ impl Clean<ExternalCrate> for CrateNum {
|
||||
/// Anything with a source location and set of attributes and, optionally, a
|
||||
/// name. That is, anything that can be documented. This doesn't correspond
|
||||
/// directly to the AST's concept of an item; it's a strict superset.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable)]
|
||||
pub struct Item {
|
||||
/// Stringified span
|
||||
pub source: Span,
|
||||
@ -296,6 +312,26 @@ pub struct Item {
|
||||
pub deprecation: Option<Deprecation>,
|
||||
}
|
||||
|
||||
impl fmt::Debug for Item {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
|
||||
|
||||
let fake = MAX_DEF_ID.with(|m| m.borrow().get(&self.def_id.krate)
|
||||
.map(|id| self.def_id >= *id).unwrap_or(false));
|
||||
let def_id: &fmt::Debug = if fake { &"**FAKE**" } else { &self.def_id };
|
||||
|
||||
fmt.debug_struct("Item")
|
||||
.field("source", &self.source)
|
||||
.field("name", &self.name)
|
||||
.field("attrs", &self.attrs)
|
||||
.field("inner", &self.inner)
|
||||
.field("visibility", &self.visibility)
|
||||
.field("def_id", def_id)
|
||||
.field("stability", &self.stability)
|
||||
.field("deprecation", &self.deprecation)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl Item {
|
||||
/// Finds the `doc` attribute as a NameValue and returns the corresponding
|
||||
/// value found.
|
||||
@ -492,9 +528,9 @@ impl Clean<Item> for doctree::Module {
|
||||
let mut items: Vec<Item> = vec![];
|
||||
items.extend(self.extern_crates.iter().map(|x| x.clean(cx)));
|
||||
items.extend(self.imports.iter().flat_map(|x| x.clean(cx)));
|
||||
items.extend(self.structs.iter().map(|x| x.clean(cx)));
|
||||
items.extend(self.unions.iter().map(|x| x.clean(cx)));
|
||||
items.extend(self.enums.iter().map(|x| x.clean(cx)));
|
||||
items.extend(self.structs.iter().flat_map(|x| x.clean(cx)));
|
||||
items.extend(self.unions.iter().flat_map(|x| x.clean(cx)));
|
||||
items.extend(self.enums.iter().flat_map(|x| x.clean(cx)));
|
||||
items.extend(self.fns.iter().map(|x| x.clean(cx)));
|
||||
items.extend(self.foreigns.iter().flat_map(|x| x.clean(cx)));
|
||||
items.extend(self.mods.iter().map(|x| x.clean(cx)));
|
||||
@ -601,7 +637,7 @@ impl<I: IntoIterator<Item=ast::NestedMetaItem>> NestedAttributesExt for I {
|
||||
/// Included files are kept separate from inline doc comments so that proper line-number
|
||||
/// information can be given when a doctest fails. Sugared doc comments and "raw" doc comments are
|
||||
/// kept separate because of issue #42760.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum DocFragment {
|
||||
// FIXME #44229 (misdreavus): sugared and raw doc comments can be brought back together once
|
||||
// hoedown is completely removed from rustdoc.
|
||||
@ -653,7 +689,7 @@ impl<'a> FromIterator<&'a DocFragment> for String {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug, Default)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Default, Hash)]
|
||||
pub struct Attributes {
|
||||
pub doc_strings: Vec<DocFragment>,
|
||||
pub other_attrs: Vec<ast::Attribute>,
|
||||
@ -1008,7 +1044,7 @@ fn resolve(cx: &DocContext, path_str: &str, is_val: bool) -> Result<(Def, Option
|
||||
|
||||
/// Resolve a string as a macro
|
||||
fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
|
||||
use syntax::ext::base::MacroKind;
|
||||
use syntax::ext::base::{MacroKind, SyntaxExtension};
|
||||
use syntax::ext::hygiene::Mark;
|
||||
let segment = ast::PathSegment {
|
||||
identifier: ast::Ident::from_str(path_str),
|
||||
@ -1025,7 +1061,11 @@ fn macro_resolve(cx: &DocContext, path_str: &str) -> Option<Def> {
|
||||
let res = resolver
|
||||
.resolve_macro_to_def_inner(mark, &path, MacroKind::Bang, false);
|
||||
if let Ok(def) = res {
|
||||
Some(def)
|
||||
if let SyntaxExtension::DeclMacro(..) = *resolver.get_macro(def) {
|
||||
Some(def)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else if let Some(def) = resolver.all_macros.get(&path_str.into()) {
|
||||
Some(*def)
|
||||
} else {
|
||||
@ -1177,7 +1217,7 @@ impl Clean<Attributes> for [ast::Attribute] {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct TyParam {
|
||||
pub name: String,
|
||||
pub did: DefId,
|
||||
@ -1212,7 +1252,7 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum TyParamBound {
|
||||
RegionBound(Lifetime),
|
||||
TraitBound(PolyTrait, hir::TraitBoundModifier)
|
||||
@ -1245,6 +1285,21 @@ impl TyParamBound {
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
fn get_poly_trait(&self) -> Option<PolyTrait> {
|
||||
if let TyParamBound::TraitBound(ref p, _) = *self {
|
||||
return Some(p.clone())
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
fn get_trait_type(&self) -> Option<Type> {
|
||||
|
||||
if let TyParamBound::TraitBound(PolyTrait { ref trait_, .. }, _) = *self {
|
||||
return Some(trait_.clone());
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<TyParamBound> for hir::TyParamBound {
|
||||
@ -1363,7 +1418,7 @@ impl<'tcx> Clean<Option<Vec<TyParamBound>>> for Substs<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct Lifetime(String);
|
||||
|
||||
impl Lifetime {
|
||||
@ -1380,17 +1435,19 @@ impl Lifetime {
|
||||
|
||||
impl Clean<Lifetime> for hir::Lifetime {
|
||||
fn clean(&self, cx: &DocContext) -> Lifetime {
|
||||
let hir_id = cx.tcx.hir.node_to_hir_id(self.id);
|
||||
let def = cx.tcx.named_region(hir_id);
|
||||
match def {
|
||||
Some(rl::Region::EarlyBound(_, node_id, _)) |
|
||||
Some(rl::Region::LateBound(_, node_id, _)) |
|
||||
Some(rl::Region::Free(_, node_id)) => {
|
||||
if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() {
|
||||
return lt;
|
||||
if self.id != ast::DUMMY_NODE_ID {
|
||||
let hir_id = cx.tcx.hir.node_to_hir_id(self.id);
|
||||
let def = cx.tcx.named_region(hir_id);
|
||||
match def {
|
||||
Some(rl::Region::EarlyBound(_, node_id, _)) |
|
||||
Some(rl::Region::LateBound(_, node_id, _)) |
|
||||
Some(rl::Region::Free(_, node_id)) => {
|
||||
if let Some(lt) = cx.lt_substs.borrow().get(&node_id).cloned() {
|
||||
return lt;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
Lifetime(self.name.name().to_string())
|
||||
}
|
||||
@ -1437,7 +1494,7 @@ impl Clean<Option<Lifetime>> for ty::RegionKind {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum WherePredicate {
|
||||
BoundPredicate { ty: Type, bounds: Vec<TyParamBound> },
|
||||
RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>},
|
||||
@ -1562,7 +1619,7 @@ impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum GenericParam {
|
||||
Lifetime(Lifetime),
|
||||
Type(TyParam),
|
||||
@ -1577,7 +1634,8 @@ impl Clean<GenericParam> for hir::GenericParam {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug, Default)]
|
||||
// maybe use a Generic enum and use Vec<Generic>?
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Default, Hash)]
|
||||
pub struct Generics {
|
||||
pub params: Vec<GenericParam>,
|
||||
pub where_predicates: Vec<WherePredicate>,
|
||||
@ -1747,7 +1805,7 @@ impl Clean<Item> for doctree::Function {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct FnDecl {
|
||||
pub inputs: Arguments,
|
||||
pub output: FunctionRetTy,
|
||||
@ -1765,7 +1823,7 @@ impl FnDecl {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct Arguments {
|
||||
pub values: Vec<Argument>,
|
||||
}
|
||||
@ -1840,7 +1898,7 @@ impl<'a, 'tcx> Clean<FnDecl> for (DefId, ty::PolyFnSig<'tcx>) {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct Argument {
|
||||
pub type_: Type,
|
||||
pub name: String,
|
||||
@ -1870,7 +1928,7 @@ impl Argument {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum FunctionRetTy {
|
||||
Return(Type),
|
||||
DefaultReturn,
|
||||
@ -1896,6 +1954,7 @@ impl GetDefId for FunctionRetTy {
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
pub struct Trait {
|
||||
pub auto: bool,
|
||||
pub unsafety: hir::Unsafety,
|
||||
pub items: Vec<Item>,
|
||||
pub generics: Generics,
|
||||
@ -1917,6 +1976,7 @@ impl Clean<Item> for doctree::Trait {
|
||||
stability: self.stab.clean(cx),
|
||||
deprecation: self.depr.clean(cx),
|
||||
inner: TraitItem(Trait {
|
||||
auto: self.is_auto.clean(cx),
|
||||
unsafety: self.unsafety,
|
||||
items: self.items.clean(cx),
|
||||
generics: self.generics.clean(cx),
|
||||
@ -2158,7 +2218,7 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
|
||||
}
|
||||
|
||||
/// A trait reference, which may have higher ranked lifetimes.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct PolyTrait {
|
||||
pub trait_: Type,
|
||||
pub generic_params: Vec<GenericParam>,
|
||||
@ -2167,7 +2227,7 @@ pub struct PolyTrait {
|
||||
/// A representation of a Type suitable for hyperlinking purposes. Ideally one can get the original
|
||||
/// type out of the AST/TyCtxt given one of these, if more information is needed. Most importantly
|
||||
/// it does not preserve mutability or boxes.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum Type {
|
||||
/// structs/enums/traits (most that'd be an hir::TyPath)
|
||||
ResolvedPath {
|
||||
@ -2782,10 +2842,13 @@ pub struct Union {
|
||||
pub fields_stripped: bool,
|
||||
}
|
||||
|
||||
impl Clean<Item> for doctree::Struct {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
Item {
|
||||
name: Some(self.name.clean(cx)),
|
||||
impl Clean<Vec<Item>> for doctree::Struct {
|
||||
fn clean(&self, cx: &DocContext) -> Vec<Item> {
|
||||
let name = self.name.clean(cx);
|
||||
let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
|
||||
|
||||
ret.push(Item {
|
||||
name: Some(name),
|
||||
attrs: self.attrs.clean(cx),
|
||||
source: self.whence.clean(cx),
|
||||
def_id: cx.tcx.hir.local_def_id(self.id),
|
||||
@ -2798,14 +2861,19 @@ impl Clean<Item> for doctree::Struct {
|
||||
fields: self.fields.clean(cx),
|
||||
fields_stripped: false,
|
||||
}),
|
||||
}
|
||||
});
|
||||
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
impl Clean<Item> for doctree::Union {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
Item {
|
||||
name: Some(self.name.clean(cx)),
|
||||
impl Clean<Vec<Item>> for doctree::Union {
|
||||
fn clean(&self, cx: &DocContext) -> Vec<Item> {
|
||||
let name = self.name.clean(cx);
|
||||
let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
|
||||
|
||||
ret.push(Item {
|
||||
name: Some(name),
|
||||
attrs: self.attrs.clean(cx),
|
||||
source: self.whence.clean(cx),
|
||||
def_id: cx.tcx.hir.local_def_id(self.id),
|
||||
@ -2818,7 +2886,9 @@ impl Clean<Item> for doctree::Union {
|
||||
fields: self.fields.clean(cx),
|
||||
fields_stripped: false,
|
||||
}),
|
||||
}
|
||||
});
|
||||
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
@ -2849,10 +2919,13 @@ pub struct Enum {
|
||||
pub variants_stripped: bool,
|
||||
}
|
||||
|
||||
impl Clean<Item> for doctree::Enum {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
Item {
|
||||
name: Some(self.name.clean(cx)),
|
||||
impl Clean<Vec<Item>> for doctree::Enum {
|
||||
fn clean(&self, cx: &DocContext) -> Vec<Item> {
|
||||
let name = self.name.clean(cx);
|
||||
let mut ret = get_auto_traits_with_node_id(cx, self.id, name.clone());
|
||||
|
||||
ret.push(Item {
|
||||
name: Some(name),
|
||||
attrs: self.attrs.clean(cx),
|
||||
source: self.whence.clean(cx),
|
||||
def_id: cx.tcx.hir.local_def_id(self.id),
|
||||
@ -2864,7 +2937,9 @@ impl Clean<Item> for doctree::Enum {
|
||||
generics: self.generics.clean(cx),
|
||||
variants_stripped: false,
|
||||
}),
|
||||
}
|
||||
});
|
||||
|
||||
ret
|
||||
}
|
||||
}
|
||||
|
||||
@ -2989,7 +3064,7 @@ impl Clean<Span> for syntax_pos::Span {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct Path {
|
||||
pub global: bool,
|
||||
pub def: Def,
|
||||
@ -3006,7 +3081,7 @@ impl Path {
|
||||
params: PathParameters::AngleBracketed {
|
||||
lifetimes: Vec::new(),
|
||||
types: Vec::new(),
|
||||
bindings: Vec::new()
|
||||
bindings: Vec::new(),
|
||||
}
|
||||
}]
|
||||
}
|
||||
@ -3027,7 +3102,7 @@ impl Clean<Path> for hir::Path {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub enum PathParameters {
|
||||
AngleBracketed {
|
||||
lifetimes: Vec<Lifetime>,
|
||||
@ -3062,7 +3137,7 @@ impl Clean<PathParameters> for hir::PathParameters {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct PathSegment {
|
||||
pub name: String,
|
||||
pub params: PathParameters,
|
||||
@ -3077,6 +3152,50 @@ impl Clean<PathSegment> for hir::PathSegment {
|
||||
}
|
||||
}
|
||||
|
||||
fn strip_type(ty: Type) -> Type {
|
||||
match ty {
|
||||
Type::ResolvedPath { path, typarams, did, is_generic } => {
|
||||
Type::ResolvedPath { path: strip_path(&path), typarams, did, is_generic }
|
||||
}
|
||||
Type::Tuple(inner_tys) => {
|
||||
Type::Tuple(inner_tys.iter().map(|t| strip_type(t.clone())).collect())
|
||||
}
|
||||
Type::Slice(inner_ty) => Type::Slice(Box::new(strip_type(*inner_ty))),
|
||||
Type::Array(inner_ty, s) => Type::Array(Box::new(strip_type(*inner_ty)), s),
|
||||
Type::Unique(inner_ty) => Type::Unique(Box::new(strip_type(*inner_ty))),
|
||||
Type::RawPointer(m, inner_ty) => Type::RawPointer(m, Box::new(strip_type(*inner_ty))),
|
||||
Type::BorrowedRef { lifetime, mutability, type_ } => {
|
||||
Type::BorrowedRef { lifetime, mutability, type_: Box::new(strip_type(*type_)) }
|
||||
}
|
||||
Type::QPath { name, self_type, trait_ } => {
|
||||
Type::QPath {
|
||||
name,
|
||||
self_type: Box::new(strip_type(*self_type)), trait_: Box::new(strip_type(*trait_))
|
||||
}
|
||||
}
|
||||
_ => ty
|
||||
}
|
||||
}
|
||||
|
||||
fn strip_path(path: &Path) -> Path {
|
||||
let segments = path.segments.iter().map(|s| {
|
||||
PathSegment {
|
||||
name: s.name.clone(),
|
||||
params: PathParameters::AngleBracketed {
|
||||
lifetimes: Vec::new(),
|
||||
types: Vec::new(),
|
||||
bindings: Vec::new(),
|
||||
}
|
||||
}
|
||||
}).collect();
|
||||
|
||||
Path {
|
||||
global: path.global,
|
||||
def: path.def.clone(),
|
||||
segments,
|
||||
}
|
||||
}
|
||||
|
||||
fn qpath_to_string(p: &hir::QPath) -> String {
|
||||
let segments = match *p {
|
||||
hir::QPath::Resolved(_, ref path) => &path.segments,
|
||||
@ -3125,7 +3244,7 @@ impl Clean<Item> for doctree::Typedef {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Debug, Hash)]
|
||||
pub struct BareFunctionDecl {
|
||||
pub unsafety: hir::Unsafety,
|
||||
pub generic_params: Vec<GenericParam>,
|
||||
@ -3198,7 +3317,7 @@ impl Clean<Item> for doctree::Constant {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Copy)]
|
||||
#[derive(Debug, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Hash)]
|
||||
pub enum Mutability {
|
||||
Mutable,
|
||||
Immutable,
|
||||
@ -3213,7 +3332,7 @@ impl Clean<Mutability> for hir::Mutability {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Copy, Debug)]
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Copy, Debug, Hash)]
|
||||
pub enum ImplPolarity {
|
||||
Positive,
|
||||
Negative,
|
||||
@ -3237,6 +3356,20 @@ pub struct Impl {
|
||||
pub for_: Type,
|
||||
pub items: Vec<Item>,
|
||||
pub polarity: Option<ImplPolarity>,
|
||||
pub synthetic: bool,
|
||||
}
|
||||
|
||||
pub fn get_auto_traits_with_node_id(cx: &DocContext, id: ast::NodeId, name: String) -> Vec<Item> {
|
||||
let finder = AutoTraitFinder { cx };
|
||||
finder.get_with_node_id(id, name)
|
||||
}
|
||||
|
||||
pub fn get_auto_traits_with_def_id(cx: &DocContext, id: DefId) -> Vec<Item> {
|
||||
let finder = AutoTraitFinder {
|
||||
cx,
|
||||
};
|
||||
|
||||
finder.get_with_def_id(id)
|
||||
}
|
||||
|
||||
impl Clean<Vec<Item>> for doctree::Impl {
|
||||
@ -3274,7 +3407,8 @@ impl Clean<Vec<Item>> for doctree::Impl {
|
||||
for_: self.for_.clean(cx),
|
||||
items,
|
||||
polarity: Some(self.polarity.clean(cx)),
|
||||
}),
|
||||
synthetic: false,
|
||||
})
|
||||
});
|
||||
ret
|
||||
}
|
||||
@ -3294,7 +3428,7 @@ fn build_deref_target_impls(cx: &DocContext,
|
||||
let primitive = match *target {
|
||||
ResolvedPath { did, .. } if did.is_local() => continue,
|
||||
ResolvedPath { did, .. } => {
|
||||
ret.extend(inline::build_impls(cx, did));
|
||||
ret.extend(inline::build_impls(cx, did, true));
|
||||
continue
|
||||
}
|
||||
_ => match target.primitive_type() {
|
||||
@ -3514,7 +3648,11 @@ fn print_const_expr(cx: &DocContext, body: hir::BodyId) -> String {
|
||||
fn resolve_type(cx: &DocContext,
|
||||
path: Path,
|
||||
id: ast::NodeId) -> Type {
|
||||
debug!("resolve_type({:?},{:?})", path, id);
|
||||
if id == ast::DUMMY_NODE_ID {
|
||||
debug!("resolve_type({:?})", path);
|
||||
} else {
|
||||
debug!("resolve_type({:?},{:?})", path, id);
|
||||
}
|
||||
|
||||
let is_generic = match path.def {
|
||||
Def::PrimTy(p) => match p {
|
||||
@ -3669,7 +3807,7 @@ impl Clean<Deprecation> for attr::Deprecation {
|
||||
}
|
||||
|
||||
/// An equality constraint on an associated type, e.g. `A=Bar` in `Foo<A=Bar>`
|
||||
#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Debug)]
|
||||
#[derive(Clone, PartialEq, Eq, RustcDecodable, RustcEncodable, Debug, Hash)]
|
||||
pub struct TypeBinding {
|
||||
pub name: String,
|
||||
pub ty: Type
|
||||
@ -3683,3 +3821,182 @@ impl Clean<TypeBinding> for hir::TypeBinding {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn def_id_to_path(cx: &DocContext, did: DefId, name: Option<String>) -> Vec<String> {
|
||||
let crate_name = name.unwrap_or_else(|| cx.tcx.crate_name(did.krate).to_string());
|
||||
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
|
||||
}
|
||||
});
|
||||
once(crate_name).chain(relative).collect()
|
||||
}
|
||||
|
||||
// Start of code copied from rust-clippy
|
||||
|
||||
pub fn get_trait_def_id(tcx: &TyCtxt, path: &[&str], use_local: bool) -> Option<DefId> {
|
||||
if use_local {
|
||||
path_to_def_local(tcx, path)
|
||||
} else {
|
||||
path_to_def(tcx, path)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path_to_def_local(tcx: &TyCtxt, path: &[&str]) -> Option<DefId> {
|
||||
let krate = tcx.hir.krate();
|
||||
let mut items = krate.module.item_ids.clone();
|
||||
let mut path_it = path.iter().peekable();
|
||||
|
||||
loop {
|
||||
let segment = match path_it.next() {
|
||||
Some(segment) => segment,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
for item_id in mem::replace(&mut items, HirVec::new()).iter() {
|
||||
let item = tcx.hir.expect_item(item_id.id);
|
||||
if item.name == *segment {
|
||||
if path_it.peek().is_none() {
|
||||
return Some(tcx.hir.local_def_id(item_id.id))
|
||||
}
|
||||
|
||||
items = match &item.node {
|
||||
&hir::ItemMod(ref m) => m.item_ids.clone(),
|
||||
_ => panic!("Unexpected item {:?} in path {:?} path")
|
||||
};
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn path_to_def(tcx: &TyCtxt, path: &[&str]) -> Option<DefId> {
|
||||
let crates = tcx.crates();
|
||||
|
||||
let krate = crates
|
||||
.iter()
|
||||
.find(|&&krate| tcx.crate_name(krate) == path[0]);
|
||||
|
||||
if let Some(krate) = krate {
|
||||
let krate = DefId {
|
||||
krate: *krate,
|
||||
index: CRATE_DEF_INDEX,
|
||||
};
|
||||
let mut items = tcx.item_children(krate);
|
||||
let mut path_it = path.iter().skip(1).peekable();
|
||||
|
||||
loop {
|
||||
let segment = match path_it.next() {
|
||||
Some(segment) => segment,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
for item in mem::replace(&mut items, Rc::new(vec![])).iter() {
|
||||
if item.ident.name == *segment {
|
||||
if path_it.peek().is_none() {
|
||||
return match item.def {
|
||||
def::Def::Trait(did) => Some(did),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
items = tcx.item_children(item.def.def_id());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn get_path_for_type(tcx: TyCtxt, def_id: DefId, def_ctor: fn(DefId) -> Def) -> hir::Path {
|
||||
struct AbsolutePathBuffer {
|
||||
names: Vec<String>,
|
||||
}
|
||||
|
||||
impl ty::item_path::ItemPathBuffer for AbsolutePathBuffer {
|
||||
fn root_mode(&self) -> &ty::item_path::RootMode {
|
||||
const ABSOLUTE: &'static ty::item_path::RootMode = &ty::item_path::RootMode::Absolute;
|
||||
ABSOLUTE
|
||||
}
|
||||
|
||||
fn push(&mut self, text: &str) {
|
||||
self.names.push(text.to_owned());
|
||||
}
|
||||
}
|
||||
|
||||
let mut apb = AbsolutePathBuffer { names: vec![] };
|
||||
|
||||
tcx.push_item_path(&mut apb, def_id);
|
||||
|
||||
hir::Path {
|
||||
span: DUMMY_SP,
|
||||
def: def_ctor(def_id),
|
||||
segments: hir::HirVec::from_vec(apb.names.iter().map(|s| hir::PathSegment {
|
||||
name: ast::Name::intern(&s),
|
||||
parameters: None,
|
||||
infer_types: false,
|
||||
}).collect())
|
||||
}
|
||||
}
|
||||
|
||||
// End of code copied from rust-clippy
|
||||
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Copy, Clone, Debug)]
|
||||
enum RegionTarget<'tcx> {
|
||||
Region(Region<'tcx>),
|
||||
RegionVid(RegionVid)
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Clone)]
|
||||
struct RegionDeps<'tcx> {
|
||||
larger: FxHashSet<RegionTarget<'tcx>>,
|
||||
smaller: FxHashSet<RegionTarget<'tcx>>
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Debug)]
|
||||
enum SimpleBound {
|
||||
RegionBound(Lifetime),
|
||||
TraitBound(Vec<PathSegment>, Vec<SimpleBound>, Vec<GenericParam>, hir::TraitBoundModifier)
|
||||
}
|
||||
|
||||
enum AutoTraitResult {
|
||||
ExplicitImpl,
|
||||
PositiveImpl(Generics),
|
||||
NegativeImpl,
|
||||
}
|
||||
|
||||
impl AutoTraitResult {
|
||||
fn is_auto(&self) -> bool {
|
||||
match *self {
|
||||
AutoTraitResult::PositiveImpl(_) | AutoTraitResult::NegativeImpl => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<TyParamBound> for SimpleBound {
|
||||
fn from(bound: TyParamBound) -> Self {
|
||||
match bound.clone() {
|
||||
TyParamBound::RegionBound(l) => SimpleBound::RegionBound(l),
|
||||
TyParamBound::TraitBound(t, mod_) => match t.trait_ {
|
||||
Type::ResolvedPath { path, typarams, .. } => {
|
||||
SimpleBound::TraitBound(path.segments,
|
||||
typarams
|
||||
.map_or_else(|| Vec::new(), |v| v.iter()
|
||||
.map(|p| SimpleBound::from(p.clone()))
|
||||
.collect()),
|
||||
t.generic_params,
|
||||
mod_)
|
||||
}
|
||||
_ => panic!("Unexpected bound {:?}", bound),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,13 +11,14 @@
|
||||
use rustc_lint;
|
||||
use rustc_driver::{self, driver, target_features, abort_on_err};
|
||||
use rustc::session::{self, config};
|
||||
use rustc::hir::def_id::DefId;
|
||||
use rustc::hir::def_id::{DefId, CrateNum};
|
||||
use rustc::hir::def::Def;
|
||||
use rustc::middle::cstore::CrateStore;
|
||||
use rustc::middle::privacy::AccessLevels;
|
||||
use rustc::ty::{self, TyCtxt, AllArenas};
|
||||
use rustc::hir::map as hir_map;
|
||||
use rustc::lint;
|
||||
use rustc::util::nodemap::FxHashMap;
|
||||
use rustc::util::nodemap::{FxHashMap, FxHashSet};
|
||||
use rustc_resolve as resolve;
|
||||
use rustc_metadata::creader::CrateLoader;
|
||||
use rustc_metadata::cstore::CStore;
|
||||
@ -48,6 +49,8 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
|
||||
pub resolver: &'a RefCell<resolve::Resolver<'rcx>>,
|
||||
/// The stack of module NodeIds up till this point
|
||||
pub mod_ids: RefCell<Vec<NodeId>>,
|
||||
pub crate_name: Option<String>,
|
||||
pub cstore: Rc<CrateStore>,
|
||||
pub populated_all_crate_impls: Cell<bool>,
|
||||
// Note that external items for which `doc(hidden)` applies to are shown as
|
||||
// non-reachable while local items aren't. This is because we're reusing
|
||||
@ -65,6 +68,11 @@ pub struct DocContext<'a, 'tcx: 'a, 'rcx: 'a> {
|
||||
pub ty_substs: RefCell<FxHashMap<Def, clean::Type>>,
|
||||
/// Table node id of lifetime parameter definition -> substituted lifetime
|
||||
pub lt_substs: RefCell<FxHashMap<DefId, clean::Lifetime>>,
|
||||
pub send_trait: Option<DefId>,
|
||||
pub fake_def_ids: RefCell<FxHashMap<CrateNum, DefId>>,
|
||||
pub all_fake_def_ids: RefCell<FxHashSet<DefId>>,
|
||||
/// Maps (type_id, trait_id) -> auto trait impl
|
||||
pub generated_synthetics: RefCell<FxHashSet<(DefId, DefId)>>
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'rcx> DocContext<'a, 'tcx, 'rcx> {
|
||||
@ -107,6 +115,7 @@ pub fn run_core(search_paths: SearchPaths,
|
||||
triple: Option<String>,
|
||||
maybe_sysroot: Option<PathBuf>,
|
||||
allow_warnings: bool,
|
||||
crate_name: Option<String>,
|
||||
force_unstable_if_unmarked: bool) -> (clean::Crate, RenderInfo)
|
||||
{
|
||||
// Parse, resolve, and typecheck the given crate.
|
||||
@ -230,9 +239,17 @@ pub fn run_core(search_paths: SearchPaths,
|
||||
.collect()
|
||||
};
|
||||
|
||||
let send_trait = if crate_name == Some("core".to_string()) {
|
||||
clean::get_trait_def_id(&tcx, &["marker", "Send"], true)
|
||||
} else {
|
||||
clean::get_trait_def_id(&tcx, &["core", "marker", "Send"], false)
|
||||
};
|
||||
|
||||
let ctxt = DocContext {
|
||||
tcx,
|
||||
resolver: &resolver,
|
||||
crate_name,
|
||||
cstore: cstore.clone(),
|
||||
populated_all_crate_impls: Cell::new(false),
|
||||
access_levels: RefCell::new(access_levels),
|
||||
external_traits: Default::default(),
|
||||
@ -240,6 +257,10 @@ pub fn run_core(search_paths: SearchPaths,
|
||||
ty_substs: Default::default(),
|
||||
lt_substs: Default::default(),
|
||||
mod_ids: Default::default(),
|
||||
send_trait: send_trait,
|
||||
fake_def_ids: RefCell::new(FxHashMap()),
|
||||
all_fake_def_ids: RefCell::new(FxHashSet()),
|
||||
generated_synthetics: RefCell::new(FxHashSet()),
|
||||
};
|
||||
debug!("crate: {:?}", tcx.hir.krate());
|
||||
|
||||
|
@ -210,6 +210,7 @@ pub struct Trait {
|
||||
pub depr: Option<attr::Deprecation>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Impl {
|
||||
pub unsafety: hir::Unsafety,
|
||||
pub polarity: hir::ImplPolarity,
|
||||
|
@ -471,18 +471,21 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector, position: Sp
|
||||
break 'main;
|
||||
}
|
||||
}
|
||||
let offset = offset.unwrap_or(0);
|
||||
let lines = test_s.lines().map(|l| map_line(l).for_code());
|
||||
let text = lines.collect::<Vec<&str>>().join("\n");
|
||||
nb_lines += doc[prev_offset..offset].lines().count();
|
||||
let line = tests.get_line() + (nb_lines - 1);
|
||||
let filename = tests.get_filename();
|
||||
tests.add_test(text.to_owned(),
|
||||
block_info.should_panic, block_info.no_run,
|
||||
block_info.ignore, block_info.test_harness,
|
||||
block_info.compile_fail, block_info.error_codes,
|
||||
line, filename, block_info.allow_fail);
|
||||
prev_offset = offset;
|
||||
if let Some(offset) = offset {
|
||||
let lines = test_s.lines().map(|l| map_line(l).for_code());
|
||||
let text = lines.collect::<Vec<&str>>().join("\n");
|
||||
nb_lines += doc[prev_offset..offset].lines().count();
|
||||
let line = tests.get_line() + (nb_lines - 1);
|
||||
let filename = tests.get_filename();
|
||||
tests.add_test(text.to_owned(),
|
||||
block_info.should_panic, block_info.no_run,
|
||||
block_info.ignore, block_info.test_harness,
|
||||
block_info.compile_fail, block_info.error_codes,
|
||||
line, filename, block_info.allow_fail);
|
||||
prev_offset = offset;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Event::Start(Tag::Header(level)) => {
|
||||
register_header = Some(level as u32);
|
||||
@ -591,7 +594,15 @@ impl<'a> fmt::Display for Markdown<'a> {
|
||||
opts.insert(OPTION_ENABLE_TABLES);
|
||||
opts.insert(OPTION_ENABLE_FOOTNOTES);
|
||||
|
||||
let p = Parser::new_ext(md, opts);
|
||||
let replacer = |_: &str, s: &str| {
|
||||
if let Some(&(_, ref replace)) = links.into_iter().find(|link| &*link.0 == s) {
|
||||
Some((replace.clone(), s.to_owned()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let p = Parser::new_with_broken_link_callback(md, opts, Some(&replacer));
|
||||
|
||||
let mut s = String::with_capacity(md.len() * 3 / 2);
|
||||
|
||||
@ -662,7 +673,16 @@ impl<'a> fmt::Display for MarkdownSummaryLine<'a> {
|
||||
// This is actually common enough to special-case
|
||||
if md.is_empty() { return Ok(()) }
|
||||
|
||||
let p = Parser::new(md);
|
||||
let replacer = |_: &str, s: &str| {
|
||||
if let Some(&(_, ref replace)) = links.into_iter().find(|link| &*link.0 == s) {
|
||||
Some((replace.clone(), s.to_owned()))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
};
|
||||
|
||||
let p = Parser::new_with_broken_link_callback(md, Options::empty(),
|
||||
Some(&replacer));
|
||||
|
||||
let mut s = String::new();
|
||||
|
||||
@ -731,18 +751,30 @@ pub fn markdown_links(md: &str) -> Vec<String> {
|
||||
opts.insert(OPTION_ENABLE_TABLES);
|
||||
opts.insert(OPTION_ENABLE_FOOTNOTES);
|
||||
|
||||
let p = Parser::new_ext(md, opts);
|
||||
|
||||
let iter = Footnotes::new(HeadingLinks::new(p, None));
|
||||
let mut links = vec![];
|
||||
let shortcut_links = RefCell::new(vec![]);
|
||||
|
||||
for ev in iter {
|
||||
if let Event::Start(Tag::Link(dest, _)) = ev {
|
||||
debug!("found link: {}", dest);
|
||||
links.push(dest.into_owned());
|
||||
{
|
||||
let push = |_: &str, s: &str| {
|
||||
shortcut_links.borrow_mut().push(s.to_owned());
|
||||
None
|
||||
};
|
||||
let p = Parser::new_with_broken_link_callback(md, opts,
|
||||
Some(&push));
|
||||
|
||||
let iter = Footnotes::new(HeadingLinks::new(p, None));
|
||||
|
||||
for ev in iter {
|
||||
if let Event::Start(Tag::Link(dest, _)) = ev {
|
||||
debug!("found link: {}", dest);
|
||||
links.push(dest.into_owned());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut shortcut_links = shortcut_links.into_inner();
|
||||
links.extend(shortcut_links.drain(..));
|
||||
|
||||
links
|
||||
}
|
||||
|
||||
|
@ -37,7 +37,7 @@ pub use self::ExternalLocation::*;
|
||||
use std::borrow::Cow;
|
||||
use std::cell::RefCell;
|
||||
use std::cmp::Ordering;
|
||||
use std::collections::{BTreeMap, HashSet};
|
||||
use std::collections::{BTreeMap, HashSet, VecDeque};
|
||||
use std::default::Default;
|
||||
use std::error;
|
||||
use std::fmt::{self, Display, Formatter, Write as FmtWrite};
|
||||
@ -270,6 +270,18 @@ pub struct Cache {
|
||||
/// generating explicit hyperlinks to other crates.
|
||||
pub external_paths: FxHashMap<DefId, (Vec<String>, ItemType)>,
|
||||
|
||||
/// Maps local def ids of exported types to fully qualified paths.
|
||||
/// Unlike 'paths', this mapping ignores any renames that occur
|
||||
/// due to 'use' statements.
|
||||
///
|
||||
/// This map is used when writing out the special 'implementors'
|
||||
/// javascript file. By using the exact path that the type
|
||||
/// is declared with, we ensure that each path will be identical
|
||||
/// to the path used if the corresponding type is inlined. By
|
||||
/// doing this, we can detect duplicate impls on a trait page, and only display
|
||||
/// the impl for the inlined type.
|
||||
pub exact_paths: FxHashMap<DefId, Vec<String>>,
|
||||
|
||||
/// This map contains information about all known traits of this crate.
|
||||
/// Implementations of a crate should inherit the documentation of the
|
||||
/// parent trait if no extra documentation is specified, and default methods
|
||||
@ -322,6 +334,7 @@ pub struct RenderInfo {
|
||||
pub inlined: FxHashSet<DefId>,
|
||||
pub external_paths: ::core::ExternalPaths,
|
||||
pub external_typarams: FxHashMap<DefId, String>,
|
||||
pub exact_paths: FxHashMap<DefId, Vec<String>>,
|
||||
pub deref_trait_did: Option<DefId>,
|
||||
pub deref_mut_trait_did: Option<DefId>,
|
||||
pub owned_box_did: Option<DefId>,
|
||||
@ -436,7 +449,9 @@ fn init_ids() -> FxHashMap<String, usize> {
|
||||
"required-methods",
|
||||
"provided-methods",
|
||||
"implementors",
|
||||
"synthetic-implementors",
|
||||
"implementors-list",
|
||||
"synthetic-implementors-list",
|
||||
"methods",
|
||||
"deref-methods",
|
||||
"implementations",
|
||||
@ -556,6 +571,7 @@ pub fn run(mut krate: clean::Crate,
|
||||
inlined: _,
|
||||
external_paths,
|
||||
external_typarams,
|
||||
exact_paths,
|
||||
deref_trait_did,
|
||||
deref_mut_trait_did,
|
||||
owned_box_did,
|
||||
@ -568,6 +584,7 @@ pub fn run(mut krate: clean::Crate,
|
||||
let mut cache = Cache {
|
||||
impls: FxHashMap(),
|
||||
external_paths,
|
||||
exact_paths,
|
||||
paths: FxHashMap(),
|
||||
implementors: FxHashMap(),
|
||||
stack: Vec::new(),
|
||||
@ -873,7 +890,10 @@ themePicker.onclick = function() {{
|
||||
// should add it.
|
||||
if !imp.impl_item.def_id.is_local() { continue }
|
||||
have_impls = true;
|
||||
write!(implementors, "{},", as_json(&imp.inner_impl().to_string())).unwrap();
|
||||
write!(implementors, "{{text:{},synthetic:{},types:{}}},",
|
||||
as_json(&imp.inner_impl().to_string()),
|
||||
imp.inner_impl().synthetic,
|
||||
as_json(&collect_paths_for_type(imp.inner_impl().for_.clone()))).unwrap();
|
||||
}
|
||||
implementors.push_str("];");
|
||||
|
||||
@ -1856,8 +1876,7 @@ fn item_module(w: &mut fmt::Formatter, cx: &Context,
|
||||
item: &clean::Item, items: &[clean::Item]) -> fmt::Result {
|
||||
document(w, cx, item)?;
|
||||
|
||||
let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped())
|
||||
.collect::<Vec<usize>>();
|
||||
let mut indices = (0..items.len()).filter(|i| !items[*i].is_stripped()).collect::<Vec<usize>>();
|
||||
|
||||
// the order of item types in the listing
|
||||
fn reorder(ty: ItemType) -> u8 {
|
||||
@ -2201,6 +2220,50 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
document(w, cx, it)
|
||||
}
|
||||
|
||||
fn render_implementor(cx: &Context, implementor: &Impl, w: &mut fmt::Formatter,
|
||||
implementor_dups: &FxHashMap<&str, (DefId, bool)>) -> Result<(), fmt::Error> {
|
||||
write!(w, "<li>")?;
|
||||
if let Some(l) = (Item { cx, item: &implementor.impl_item }).src_href() {
|
||||
write!(w, "<div class='out-of-band'>")?;
|
||||
write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
|
||||
l, "goto source code")?;
|
||||
write!(w, "</div>")?;
|
||||
}
|
||||
write!(w, "<code>")?;
|
||||
// If there's already another implementor that has the same abbridged name, use the
|
||||
// full path, for example in `std::iter::ExactSizeIterator`
|
||||
let use_absolute = match implementor.inner_impl().for_ {
|
||||
clean::ResolvedPath { ref path, is_generic: false, .. } |
|
||||
clean::BorrowedRef {
|
||||
type_: box clean::ResolvedPath { ref path, is_generic: false, .. },
|
||||
..
|
||||
} => implementor_dups[path.last_name()].1,
|
||||
_ => false,
|
||||
};
|
||||
fmt_impl_for_trait_page(&implementor.inner_impl(), w, use_absolute)?;
|
||||
for it in &implementor.inner_impl().items {
|
||||
if let clean::TypedefItem(ref tydef, _) = it.inner {
|
||||
write!(w, "<span class=\"where fmt-newline\"> ")?;
|
||||
assoc_type(w, it, &vec![], Some(&tydef.type_), AssocItemLink::Anchor(None))?;
|
||||
write!(w, ";</span>")?;
|
||||
}
|
||||
}
|
||||
writeln!(w, "</code></li>")?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn render_impls(cx: &Context, w: &mut fmt::Formatter,
|
||||
traits: Vec<&&Impl>,
|
||||
containing_item: &clean::Item) -> Result<(), fmt::Error> {
|
||||
for i in &traits {
|
||||
let did = i.trait_did().unwrap();
|
||||
let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods);
|
||||
render_impl(w, cx, i, assoc_link,
|
||||
RenderMode::Normal, containing_item.stable_since(), true)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
t: &clean::Trait) -> fmt::Result {
|
||||
let mut bounds = String::new();
|
||||
@ -2380,6 +2443,16 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
</h2>
|
||||
<ul class='item-list' id='implementors-list'>
|
||||
";
|
||||
|
||||
let synthetic_impl_header = "
|
||||
<h2 id='synthetic-implementors' class='small-section-header'>
|
||||
Auto implementors<a href='#synthetic-implementors' class='anchor'></a>
|
||||
</h2>
|
||||
<ul class='item-list' id='synthetic-implementors-list'>
|
||||
";
|
||||
|
||||
let mut synthetic_types = Vec::new();
|
||||
|
||||
if let Some(implementors) = cache.implementors.get(&it.def_id) {
|
||||
// The DefId is for the first Type found with that name. The bool is
|
||||
// if any Types with the same name but different DefId have been found.
|
||||
@ -2405,6 +2478,11 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
.partition::<Vec<_>, _>(|i| i.inner_impl().for_.def_id()
|
||||
.map_or(true, |d| cache.paths.contains_key(&d)));
|
||||
|
||||
|
||||
let (synthetic, concrete) = local.iter()
|
||||
.partition::<Vec<_>, _>(|i| i.inner_impl().synthetic);
|
||||
|
||||
|
||||
if !foreign.is_empty() {
|
||||
write!(w, "
|
||||
<h2 id='foreign-impls' class='small-section-header'>
|
||||
@ -2422,42 +2500,35 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
|
||||
}
|
||||
|
||||
write!(w, "{}", impl_header)?;
|
||||
for implementor in concrete {
|
||||
render_implementor(cx, implementor, w, &implementor_dups)?;
|
||||
}
|
||||
write!(w, "</ul>")?;
|
||||
|
||||
for implementor in local {
|
||||
write!(w, "<li>")?;
|
||||
if let Some(l) = (Item { cx, item: &implementor.impl_item }).src_href() {
|
||||
write!(w, "<div class='out-of-band'>")?;
|
||||
write!(w, "<a class='srclink' href='{}' title='{}'>[src]</a>",
|
||||
l, "goto source code")?;
|
||||
write!(w, "</div>")?;
|
||||
if t.auto {
|
||||
write!(w, "{}", synthetic_impl_header)?;
|
||||
for implementor in synthetic {
|
||||
synthetic_types.extend(
|
||||
collect_paths_for_type(implementor.inner_impl().for_.clone())
|
||||
);
|
||||
render_implementor(cx, implementor, w, &implementor_dups)?;
|
||||
}
|
||||
write!(w, "<code>")?;
|
||||
// If there's already another implementor that has the same abbridged name, use the
|
||||
// full path, for example in `std::iter::ExactSizeIterator`
|
||||
let use_absolute = match implementor.inner_impl().for_ {
|
||||
clean::ResolvedPath { ref path, is_generic: false, .. } |
|
||||
clean::BorrowedRef {
|
||||
type_: box clean::ResolvedPath { ref path, is_generic: false, .. },
|
||||
..
|
||||
} => implementor_dups[path.last_name()].1,
|
||||
_ => false,
|
||||
};
|
||||
fmt_impl_for_trait_page(&implementor.inner_impl(), w, use_absolute)?;
|
||||
for it in &implementor.inner_impl().items {
|
||||
if let clean::TypedefItem(ref tydef, _) = it.inner {
|
||||
write!(w, "<span class=\"where fmt-newline\"> ")?;
|
||||
assoc_type(w, it, &vec![], Some(&tydef.type_), AssocItemLink::Anchor(None))?;
|
||||
write!(w, ";</span>")?;
|
||||
}
|
||||
}
|
||||
writeln!(w, "</code></li>")?;
|
||||
write!(w, "</ul>")?;
|
||||
}
|
||||
} else {
|
||||
// even without any implementations to write in, we still want the heading and list, so the
|
||||
// implementors javascript file pulled in below has somewhere to write the impls into
|
||||
write!(w, "{}", impl_header)?;
|
||||
write!(w, "</ul>")?;
|
||||
|
||||
if t.auto {
|
||||
write!(w, "{}", synthetic_impl_header)?;
|
||||
write!(w, "</ul>")?;
|
||||
}
|
||||
}
|
||||
write!(w, "</ul>")?;
|
||||
write!(w, r#"<script type="text/javascript">window.inlined_types=new Set({});</script>"#,
|
||||
as_json(&synthetic_types))?;
|
||||
|
||||
write!(w, r#"<script type="text/javascript" async
|
||||
src="{root_path}/implementors/{path}/{ty}.{name}.js">
|
||||
</script>"#,
|
||||
@ -3075,17 +3146,28 @@ fn render_assoc_items(w: &mut fmt::Formatter,
|
||||
}).is_some();
|
||||
render_deref_methods(w, cx, impl_, containing_item, has_deref_mut)?;
|
||||
}
|
||||
|
||||
let (synthetic, concrete) = traits
|
||||
.iter()
|
||||
.partition::<Vec<_>, _>(|t| t.inner_impl().synthetic);
|
||||
|
||||
write!(w, "
|
||||
<h2 id='implementations' class='small-section-header'>
|
||||
Trait Implementations<a href='#implementations' class='anchor'></a>
|
||||
</h2>
|
||||
<div id='implementations-list'>
|
||||
")?;
|
||||
for i in &traits {
|
||||
let did = i.trait_did().unwrap();
|
||||
let assoc_link = AssocItemLink::GotoSource(did, &i.inner_impl().provided_trait_methods);
|
||||
render_impl(w, cx, i, assoc_link,
|
||||
RenderMode::Normal, containing_item.stable_since(), true)?;
|
||||
}
|
||||
render_impls(cx, w, concrete, containing_item)?;
|
||||
write!(w, "</div>")?;
|
||||
|
||||
write!(w, "
|
||||
<h2 id='synthetic-implementations' class='small-section-header'>
|
||||
Auto Trait Implementations<a href='#synthetic-implementations' class='anchor'></a>
|
||||
</h2>
|
||||
<div id='synthetic-implementations-list'>
|
||||
")?;
|
||||
render_impls(cx, w, synthetic, containing_item)?;
|
||||
write!(w, "</div>")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@ -3586,32 +3668,48 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
|
||||
}
|
||||
}
|
||||
}
|
||||
let mut links = HashSet::new();
|
||||
let ret = v.iter()
|
||||
.filter_map(|i| {
|
||||
let is_negative_impl = is_negative_impl(i.inner_impl());
|
||||
if let Some(ref i) = i.inner_impl().trait_ {
|
||||
let i_display = format!("{:#}", i);
|
||||
let out = Escape(&i_display);
|
||||
let encoded = small_url_encode(&format!("{:#}", i));
|
||||
let generated = format!("<a href=\"#impl-{}\">{}{}</a>",
|
||||
encoded,
|
||||
if is_negative_impl { "!" } else { "" },
|
||||
out);
|
||||
if !links.contains(&generated) && links.insert(generated.clone()) {
|
||||
Some(generated)
|
||||
let format_impls = |impls: Vec<&Impl>| {
|
||||
let mut links = HashSet::new();
|
||||
impls.iter()
|
||||
.filter_map(|i| {
|
||||
let is_negative_impl = is_negative_impl(i.inner_impl());
|
||||
if let Some(ref i) = i.inner_impl().trait_ {
|
||||
let i_display = format!("{:#}", i);
|
||||
let out = Escape(&i_display);
|
||||
let encoded = small_url_encode(&format!("{:#}", i));
|
||||
let generated = format!("<a href=\"#impl-{}\">{}{}</a>",
|
||||
encoded,
|
||||
if is_negative_impl { "!" } else { "" },
|
||||
out);
|
||||
if links.insert(generated.clone()) {
|
||||
Some(generated)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect::<String>();
|
||||
if !ret.is_empty() {
|
||||
})
|
||||
.collect::<String>()
|
||||
};
|
||||
|
||||
let (synthetic, concrete) = v
|
||||
.iter()
|
||||
.partition::<Vec<_>, _>(|i| i.inner_impl().synthetic);
|
||||
|
||||
let concrete_format = format_impls(concrete);
|
||||
let synthetic_format = format_impls(synthetic);
|
||||
|
||||
if !concrete_format.is_empty() {
|
||||
out.push_str("<a class=\"sidebar-title\" href=\"#implementations\">\
|
||||
Trait Implementations</a>");
|
||||
out.push_str(&format!("<div class=\"sidebar-links\">{}</div>", ret));
|
||||
out.push_str(&format!("<div class=\"sidebar-links\">{}</div>", concrete_format));
|
||||
}
|
||||
|
||||
if !synthetic_format.is_empty() {
|
||||
out.push_str("<a class=\"sidebar-title\" href=\"#synthetic-implementations\">\
|
||||
Auto Trait Implementations</a>");
|
||||
out.push_str(&format!("<div class=\"sidebar-links\">{}</div>", synthetic_format));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3734,7 +3832,7 @@ fn sidebar_trait(fmt: &mut fmt::Formatter, it: &clean::Item,
|
||||
if let Some(implementors) = c.implementors.get(&it.def_id) {
|
||||
let res = implementors.iter()
|
||||
.filter(|i| i.inner_impl().for_.def_id()
|
||||
.map_or(false, |d| !c.paths.contains_key(&d)))
|
||||
.map_or(false, |d| !c.paths.contains_key(&d)))
|
||||
.filter_map(|i| {
|
||||
match extract_for_impl_name(&i.impl_item) {
|
||||
Some((ref name, ref url)) => {
|
||||
@ -3755,6 +3853,10 @@ fn sidebar_trait(fmt: &mut fmt::Formatter, it: &clean::Item,
|
||||
}
|
||||
|
||||
sidebar.push_str("<a class=\"sidebar-title\" href=\"#implementors\">Implementors</a>");
|
||||
if t.auto {
|
||||
sidebar.push_str("<a class=\"sidebar-title\" \
|
||||
href=\"#synthetic-implementors\">Auto Implementors</a>");
|
||||
}
|
||||
|
||||
sidebar.push_str(&sidebar_assoc_items(it));
|
||||
|
||||
@ -3969,6 +4071,66 @@ fn get_index_type(clean_type: &clean::Type) -> Type {
|
||||
t
|
||||
}
|
||||
|
||||
/// Returns a list of all paths used in the type.
|
||||
/// This is used to help deduplicate imported impls
|
||||
/// for reexported types. If any of the contained
|
||||
/// types are re-exported, we don't use the corresponding
|
||||
/// entry from the js file, as inlining will have already
|
||||
/// picked up the impl
|
||||
fn collect_paths_for_type(first_ty: clean::Type) -> Vec<String> {
|
||||
let mut out = Vec::new();
|
||||
let mut visited = FxHashSet();
|
||||
let mut work = VecDeque::new();
|
||||
let cache = cache();
|
||||
|
||||
work.push_back(first_ty);
|
||||
|
||||
while let Some(ty) = work.pop_front() {
|
||||
if !visited.insert(ty.clone()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
match ty {
|
||||
clean::Type::ResolvedPath { did, .. } => {
|
||||
let get_extern = || cache.external_paths.get(&did).map(|s| s.0.clone());
|
||||
let fqp = cache.exact_paths.get(&did).cloned().or_else(get_extern);
|
||||
|
||||
match fqp {
|
||||
Some(path) => {
|
||||
out.push(path.join("::"));
|
||||
},
|
||||
_ => {}
|
||||
};
|
||||
|
||||
},
|
||||
clean::Type::Tuple(tys) => {
|
||||
work.extend(tys.into_iter());
|
||||
},
|
||||
clean::Type::Slice(ty) => {
|
||||
work.push_back(*ty);
|
||||
}
|
||||
clean::Type::Array(ty, _) => {
|
||||
work.push_back(*ty);
|
||||
},
|
||||
clean::Type::Unique(ty) => {
|
||||
work.push_back(*ty);
|
||||
},
|
||||
clean::Type::RawPointer(_, ty) => {
|
||||
work.push_back(*ty);
|
||||
},
|
||||
clean::Type::BorrowedRef { type_, .. } => {
|
||||
work.push_back(*type_);
|
||||
},
|
||||
clean::Type::QPath { self_type, trait_, .. } => {
|
||||
work.push_back(*self_type);
|
||||
work.push_back(*trait_);
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
};
|
||||
out
|
||||
}
|
||||
|
||||
fn get_index_type_name(clean_type: &clean::Type, accept_generic: bool) -> Option<String> {
|
||||
match *clean_type {
|
||||
clean::ResolvedPath { ref path, .. } => {
|
||||
|
@ -1563,14 +1563,31 @@
|
||||
window.initSidebarItems = initSidebarItems;
|
||||
|
||||
window.register_implementors = function(imp) {
|
||||
var list = document.getElementById('implementors-list');
|
||||
var implementors = document.getElementById('implementors-list');
|
||||
var synthetic_implementors = document.getElementById('synthetic-implementors-list');
|
||||
|
||||
var libs = Object.getOwnPropertyNames(imp);
|
||||
for (var i = 0; i < libs.length; ++i) {
|
||||
if (libs[i] === currentCrate) { continue; }
|
||||
var structs = imp[libs[i]];
|
||||
|
||||
struct_loop:
|
||||
for (var j = 0; j < structs.length; ++j) {
|
||||
var struct = structs[j];
|
||||
|
||||
var list = struct.synthetic ? synthetic_implementors : implementors;
|
||||
|
||||
if (struct.synthetic) {
|
||||
for (var k = 0; k < struct.types.length; k++) {
|
||||
if (window.inlined_types.has(struct.types[k])) {
|
||||
continue struct_loop;
|
||||
}
|
||||
window.inlined_types.add(struct.types[k]);
|
||||
}
|
||||
}
|
||||
|
||||
var code = document.createElement('code');
|
||||
code.innerHTML = structs[j];
|
||||
code.innerHTML = struct.text;
|
||||
|
||||
var x = code.getElementsByTagName('a');
|
||||
for (var k = 0; k < x.length; k++) {
|
||||
|
@ -24,6 +24,7 @@
|
||||
#![feature(test)]
|
||||
#![feature(unicode)]
|
||||
#![feature(vec_remove_item)]
|
||||
#![feature(entry_and_modify)]
|
||||
|
||||
extern crate arena;
|
||||
extern crate getopts;
|
||||
@ -549,7 +550,8 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R {
|
||||
|
||||
let (mut krate, renderinfo) =
|
||||
core::run_core(paths, cfgs, externs, Input::File(cratefile), triple, maybe_sysroot,
|
||||
display_warnings, force_unstable_if_unmarked);
|
||||
display_warnings, crate_name.clone(),
|
||||
force_unstable_if_unmarked);
|
||||
|
||||
info!("finished with rustc");
|
||||
|
||||
|
@ -414,7 +414,8 @@ fn partition_source(s: &str) -> (String, String) {
|
||||
for line in s.lines() {
|
||||
let trimline = line.trim();
|
||||
let header = trimline.is_whitespace() ||
|
||||
trimline.starts_with("#![");
|
||||
trimline.starts_with("#![") ||
|
||||
trimline.starts_with("extern crate");
|
||||
if !header || after_header {
|
||||
after_header = true;
|
||||
after.push_str(line);
|
||||
@ -814,8 +815,8 @@ use asdf::qwop;
|
||||
assert_eq!(2+2, 4);";
|
||||
let expected =
|
||||
"#![allow(unused)]
|
||||
fn main() {
|
||||
extern crate asdf;
|
||||
fn main() {
|
||||
use asdf::qwop;
|
||||
assert_eq!(2+2, 4);
|
||||
}".to_string();
|
||||
|
@ -24,12 +24,12 @@ use rustc::hir::def_id::{DefId, LOCAL_CRATE};
|
||||
use rustc::middle::cstore::{LoadedMacro, CrateStore};
|
||||
use rustc::middle::privacy::AccessLevel;
|
||||
use rustc::ty::Visibility;
|
||||
use rustc::util::nodemap::FxHashSet;
|
||||
use rustc::util::nodemap::{FxHashSet, FxHashMap};
|
||||
|
||||
use rustc::hir;
|
||||
|
||||
use core;
|
||||
use clean::{self, AttributesExt, NestedAttributesExt};
|
||||
use clean::{self, AttributesExt, NestedAttributesExt, def_id_to_path};
|
||||
use doctree::*;
|
||||
|
||||
// looks to me like the first two of these are actually
|
||||
@ -41,7 +41,7 @@ use doctree::*;
|
||||
// framework from syntax?
|
||||
|
||||
pub struct RustdocVisitor<'a, 'tcx: 'a, 'rcx: 'a> {
|
||||
cstore: &'a CrateStore,
|
||||
pub cstore: &'a CrateStore,
|
||||
pub module: Module,
|
||||
pub attrs: hir::HirVec<ast::Attribute>,
|
||||
pub cx: &'a core::DocContext<'a, 'tcx, 'rcx>,
|
||||
@ -50,6 +50,7 @@ pub struct RustdocVisitor<'a, 'tcx: 'a, 'rcx: 'a> {
|
||||
/// Is the current module and all of its parents public?
|
||||
inside_public_path: bool,
|
||||
reexported_macros: FxHashSet<DefId>,
|
||||
exact_paths: Option<FxHashMap<DefId, Vec<String>>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
|
||||
@ -66,10 +67,21 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
|
||||
inlining: false,
|
||||
inside_public_path: true,
|
||||
reexported_macros: FxHashSet(),
|
||||
exact_paths: Some(FxHashMap()),
|
||||
cstore,
|
||||
}
|
||||
}
|
||||
|
||||
fn store_path(&mut self, did: DefId) {
|
||||
// We can't use the entry api, as that keeps the mutable borrow of self active
|
||||
// when we try to use cx
|
||||
let exact_paths = self.exact_paths.as_mut().unwrap();
|
||||
if exact_paths.get(&did).is_none() {
|
||||
let path = def_id_to_path(self.cx, did, self.cx.crate_name.clone());
|
||||
exact_paths.insert(did, path);
|
||||
}
|
||||
}
|
||||
|
||||
fn stability(&self, id: ast::NodeId) -> Option<attr::Stability> {
|
||||
self.cx.tcx.hir.opt_local_def_id(id)
|
||||
.and_then(|def_id| self.cx.tcx.lookup_stability(def_id)).cloned()
|
||||
@ -94,6 +106,8 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
|
||||
krate.exported_macros.iter().map(|def| self.visit_local_macro(def)).collect();
|
||||
self.module.macros.extend(macro_exports);
|
||||
self.module.is_crate = true;
|
||||
|
||||
self.cx.renderinfo.borrow_mut().exact_paths = self.exact_paths.take().unwrap();
|
||||
}
|
||||
|
||||
pub fn visit_variant_data(&mut self, item: &hir::Item,
|
||||
@ -371,6 +385,12 @@ impl<'a, 'tcx, 'rcx> RustdocVisitor<'a, 'tcx, 'rcx> {
|
||||
renamed: Option<ast::Name>, om: &mut Module) {
|
||||
debug!("Visiting item {:?}", item);
|
||||
let name = renamed.unwrap_or(item.name);
|
||||
|
||||
if item.vis == hir::Public {
|
||||
let def_id = self.cx.tcx.hir.local_def_id(item.id);
|
||||
self.store_path(def_id);
|
||||
}
|
||||
|
||||
match item.node {
|
||||
hir::ItemForeignMod(ref fm) => {
|
||||
// If inlining we only want to include public functions.
|
||||
|
@ -91,7 +91,7 @@ use sys;
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// ```ignore (extern-declaration)
|
||||
/// # fn main() {
|
||||
/// use std::ffi::CString;
|
||||
/// use std::os::raw::c_char;
|
||||
@ -150,7 +150,7 @@ pub struct CString {
|
||||
///
|
||||
/// Inspecting a foreign C string:
|
||||
///
|
||||
/// ```no_run
|
||||
/// ```ignore (extern-declaration)
|
||||
/// use std::ffi::CStr;
|
||||
/// use std::os::raw::c_char;
|
||||
///
|
||||
@ -164,7 +164,7 @@ pub struct CString {
|
||||
///
|
||||
/// Passing a Rust-originating C string:
|
||||
///
|
||||
/// ```no_run
|
||||
/// ```ignore (extern-declaration)
|
||||
/// use std::ffi::{CString, CStr};
|
||||
/// use std::os::raw::c_char;
|
||||
///
|
||||
@ -180,7 +180,7 @@ pub struct CString {
|
||||
///
|
||||
/// Converting a foreign C string into a Rust [`String`]:
|
||||
///
|
||||
/// ```no_run
|
||||
/// ```ignore (extern-declaration)
|
||||
/// use std::ffi::CStr;
|
||||
/// use std::os::raw::c_char;
|
||||
///
|
||||
@ -307,7 +307,7 @@ impl CString {
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// ```ignore (extern-declaration)
|
||||
/// use std::ffi::CString;
|
||||
/// use std::os::raw::c_char;
|
||||
///
|
||||
@ -389,7 +389,7 @@ impl CString {
|
||||
/// Create a `CString`, pass ownership to an `extern` function (via raw pointer), then retake
|
||||
/// ownership with `from_raw`:
|
||||
///
|
||||
/// ```no_run
|
||||
/// ```ignore (extern-declaration)
|
||||
/// use std::ffi::CString;
|
||||
/// use std::os::raw::c_char;
|
||||
///
|
||||
@ -882,7 +882,7 @@ impl CStr {
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// ```ignore (extern-declaration)
|
||||
/// # fn main() {
|
||||
/// use std::ffi::CStr;
|
||||
/// use std::os::raw::c_char;
|
||||
|
@ -1506,6 +1506,8 @@ pub trait BufRead: Read {
|
||||
/// error is encountered then `buf` may contain some bytes already read in
|
||||
/// the event that all data read so far was valid UTF-8.
|
||||
///
|
||||
/// [`read_until`]: #method.read_until
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// [`std::io::Cursor`][`Cursor`] is a type that implements `BufRead`. In
|
||||
|
@ -415,7 +415,7 @@ impl UnixStream {
|
||||
/// method.
|
||||
///
|
||||
/// [`None`]: ../../../../std/option/enum.Option.html#variant.None
|
||||
/// [`read`]: ../../../../std/io/trait.Write.html#tymethod.write
|
||||
/// [`write`]: ../../../../std/io/trait.Write.html#tymethod.write
|
||||
/// [`Duration`]: ../../../../std/time/struct.Duration.html
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -18,6 +18,6 @@ fn main() {
|
||||
let x = 0;
|
||||
let y = &x as *const _;
|
||||
let _ = y.is_null();
|
||||
//~^ error: the type of this value must be known in this context [tyvar_behind_raw_pointer]
|
||||
//~^ error: type annotations needed [tyvar_behind_raw_pointer]
|
||||
//~^^ warning: this was previously accepted
|
||||
}
|
||||
|
@ -11,7 +11,7 @@
|
||||
fn main() {
|
||||
return
|
||||
{ return () }
|
||||
//~^ ERROR the type of this value must be known in this context
|
||||
//~^ ERROR type annotations needed [E0282]
|
||||
()
|
||||
;
|
||||
}
|
||||
|
@ -10,5 +10,5 @@
|
||||
|
||||
fn main() {
|
||||
let x = panic!();
|
||||
x.clone(); //~ ERROR the type of this value must be known in this context
|
||||
x.clone(); //~ ERROR type annotations needed
|
||||
}
|
||||
|
@ -43,6 +43,6 @@ fn main() {
|
||||
fn another_fn_to_avoid_suppression() {
|
||||
match Default::default()
|
||||
{
|
||||
[] => {} //~ ERROR the type of this value
|
||||
[] => {} //~ ERROR type annotations needed
|
||||
};
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ fn main() {
|
||||
let x;
|
||||
|
||||
match x {
|
||||
(..) => {} //~ ERROR the type of this value must be known in this context
|
||||
(..) => {} //~ ERROR type annotations needed
|
||||
_ => {}
|
||||
}
|
||||
|
||||
|
@ -24,7 +24,7 @@ fn a() {
|
||||
match closure0.take() {
|
||||
Some(c) => {
|
||||
return c();
|
||||
//~^ ERROR the type of this value must be known in this context
|
||||
//~^ ERROR type annotations needed
|
||||
}
|
||||
None => { }
|
||||
}
|
||||
|
@ -11,7 +11,8 @@
|
||||
// @has issue_33054/impls/struct.Foo.html
|
||||
// @has - '//code' 'impl Foo'
|
||||
// @has - '//code' 'impl Bar for Foo'
|
||||
// @count - '//*[@class="impl"]' 2
|
||||
// @count - '//*[@id="implementations-list"]/*[@class="impl"]' 1
|
||||
// @count - '//*[@id="main"]/*[@class="impl"]' 1
|
||||
// @has issue_33054/impls/bar/trait.Bar.html
|
||||
// @has - '//code' 'impl Bar for Foo'
|
||||
// @count - '//*[@class="struct"]' 1
|
||||
|
@ -77,3 +77,15 @@ pub trait SoAmbiguous {}
|
||||
|
||||
#[allow(bad_style)]
|
||||
pub fn SoAmbiguous() {}
|
||||
|
||||
|
||||
// @has - '//a/@href' '../intra_links/struct.ThisType.html'
|
||||
// @has - '//a/@href' '../intra_links/struct.ThisType.html#method.this_method'
|
||||
// @has - '//a/@href' '../intra_links/enum.ThisEnum.html'
|
||||
// @has - '//a/@href' '../intra_links/enum.ThisEnum.html#ThisVariant.v'
|
||||
/// Shortcut links for:
|
||||
/// * [`ThisType`]
|
||||
/// * [`ThisType::this_method`]
|
||||
/// * [ThisEnum]
|
||||
/// * [ThisEnum::ThisVariant]
|
||||
pub struct SomeOtherType;
|
||||
|
@ -17,5 +17,5 @@ mod inner {
|
||||
pub trait Blah { }
|
||||
|
||||
// @count issue_21474/struct.What.html \
|
||||
// '//*[@class="impl"]' 1
|
||||
// '//*[@id="implementations-list"]/*[@class="impl"]' 1
|
||||
pub struct What;
|
||||
|
@ -14,12 +14,12 @@ pub trait Bar<T, U> {}
|
||||
|
||||
// @has 'foo/struct.Foo1.html'
|
||||
pub struct Foo1;
|
||||
// @count - '//*[@class="impl"]' 1
|
||||
// @count - '//*[@id="implementations-list"]/*[@class="impl"]' 1
|
||||
// @has - '//*[@class="impl"]' "impl Bar<Foo1, &'static Foo1> for Foo1"
|
||||
impl Bar<Foo1, &'static Foo1> for Foo1 {}
|
||||
|
||||
// @has 'foo/struct.Foo2.html'
|
||||
pub struct Foo2;
|
||||
// @count - '//*[@class="impl"]' 1
|
||||
// @count - '//*[@id="implementations-list"]/*[@class="impl"]' 1
|
||||
// @has - '//*[@class="impl"]' "impl Bar<&'static Foo2, Foo2> for u8"
|
||||
impl Bar<&'static Foo2, Foo2> for u8 {}
|
||||
|
@ -1,4 +1,4 @@
|
||||
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
@ -8,12 +8,16 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn main() {
|
||||
let x;
|
||||
// compile-flags:--test
|
||||
|
||||
match x {
|
||||
(..) => {} //~ ERROR E0619
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
//! This is a doc comment
|
||||
//!
|
||||
//! ```rust
|
||||
//! fn main() {}
|
||||
//! ```
|
||||
//!
|
||||
//! With a trailing code fence
|
||||
//! ```
|
||||
|
||||
/// Some foo function
|
||||
pub fn foo() {}
|
18
src/test/rustdoc/synthetic_auto/basic.rs
Normal file
18
src/test/rustdoc/synthetic_auto/basic.rs
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// @has basic/struct.Foo.html
|
||||
// @has - '//code' 'impl<T> Send for Foo<T> where T: Send'
|
||||
// @has - '//code' 'impl<T> Sync for Foo<T> where T: Sync'
|
||||
// @count - '//*[@id="implementations-list"]/*[@class="impl"]' 0
|
||||
// @count - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]' 2
|
||||
pub struct Foo<T> {
|
||||
field: T,
|
||||
}
|
52
src/test/rustdoc/synthetic_auto/complex.rs
Normal file
52
src/test/rustdoc/synthetic_auto/complex.rs
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
mod foo {
|
||||
pub trait MyTrait<'a> {
|
||||
type MyItem: ?Sized;
|
||||
}
|
||||
|
||||
pub struct Inner<'a, Q, R: ?Sized> {
|
||||
field: Q,
|
||||
field3: &'a u8,
|
||||
my_foo: Foo<Q>,
|
||||
field2: R,
|
||||
}
|
||||
|
||||
pub struct Outer<'a, T, K: ?Sized> {
|
||||
my_inner: Inner<'a, T, K>,
|
||||
}
|
||||
|
||||
pub struct Foo<T> {
|
||||
myfield: T,
|
||||
}
|
||||
}
|
||||
|
||||
// @has complex/struct.NotOuter.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'a, T, K: \
|
||||
// ?Sized> Send for NotOuter<'a, T, K> where K: for<'b> Fn((&'b bool, &'a u8)) \
|
||||
// -> &'b i8, T: MyTrait<'a>, <T as MyTrait<'a>>::MyItem: Copy, 'a: 'static"
|
||||
|
||||
pub use foo::{Foo, Inner as NotInner, MyTrait as NotMyTrait, Outer as NotOuter};
|
||||
|
||||
unsafe impl<T> Send for Foo<T>
|
||||
where
|
||||
T: NotMyTrait<'static>,
|
||||
{
|
||||
}
|
||||
|
||||
unsafe impl<'a, Q, R: ?Sized> Send for NotInner<'a, Q, R>
|
||||
where
|
||||
Q: NotMyTrait<'a>,
|
||||
<Q as NotMyTrait<'a>>::MyItem: Copy,
|
||||
R: for<'b> Fn((&'b bool, &'a u8)) -> &'b i8,
|
||||
Foo<Q>: Send,
|
||||
{
|
||||
}
|
28
src/test/rustdoc/synthetic_auto/lifetimes.rs
Normal file
28
src/test/rustdoc/synthetic_auto/lifetimes.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
pub struct Inner<'a, T: 'a> {
|
||||
field: &'a T,
|
||||
}
|
||||
|
||||
unsafe impl<'a, T> Send for Inner<'a, T>
|
||||
where
|
||||
'a: 'static,
|
||||
T: for<'b> Fn(&'b bool) -> &'a u8,
|
||||
{}
|
||||
|
||||
// @has lifetimes/struct.Foo.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'c, K> Send \
|
||||
// for Foo<'c, K> where K: for<'b> Fn(&'b bool) -> &'c u8, 'c: 'static"
|
||||
//
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'c, K> Sync \
|
||||
// for Foo<'c, K> where K: Sync"
|
||||
pub struct Foo<'c, K: 'c> {
|
||||
inner_field: Inner<'c, K>,
|
||||
}
|
24
src/test/rustdoc/synthetic_auto/manual.rs
Normal file
24
src/test/rustdoc/synthetic_auto/manual.rs
Normal file
@ -0,0 +1,24 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
// @has manual/struct.Foo.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' 'impl<T> Sync for \
|
||||
// Foo<T> where T: Sync'
|
||||
//
|
||||
// @has - '//*[@id="implementations-list"]/*[@class="impl"]/*/code' \
|
||||
// 'impl<T> Send for Foo<T>'
|
||||
//
|
||||
// @count - '//*[@id="implementations-list"]/*[@class="impl"]' 1
|
||||
// @count - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]' 1
|
||||
pub struct Foo<T> {
|
||||
field: T,
|
||||
}
|
||||
|
||||
unsafe impl<T> Send for Foo<T> {}
|
23
src/test/rustdoc/synthetic_auto/negative.rs
Normal file
23
src/test/rustdoc/synthetic_auto/negative.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
pub struct Inner<T: Copy> {
|
||||
field: *mut T,
|
||||
}
|
||||
|
||||
// @has negative/struct.Outer.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<T> !Send for \
|
||||
// Outer<T>"
|
||||
//
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<T> \
|
||||
// !Sync for Outer<T>"
|
||||
pub struct Outer<T: Copy> {
|
||||
inner_field: Inner<T>,
|
||||
}
|
28
src/test/rustdoc/synthetic_auto/nested.rs
Normal file
28
src/test/rustdoc/synthetic_auto/nested.rs
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
pub struct Inner<T> {
|
||||
field: T,
|
||||
}
|
||||
|
||||
unsafe impl<T> Send for Inner<T>
|
||||
where
|
||||
T: Copy,
|
||||
{
|
||||
}
|
||||
|
||||
// @has nested/struct.Foo.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' 'impl<T> Send for \
|
||||
// Foo<T> where T: Copy'
|
||||
//
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' \
|
||||
// 'impl<T> Sync for Foo<T> where T: Sync'
|
||||
pub struct Foo<T> {
|
||||
inner_field: Inner<T>,
|
||||
}
|
26
src/test/rustdoc/synthetic_auto/no-redundancy.rs
Normal file
26
src/test/rustdoc/synthetic_auto/no-redundancy.rs
Normal file
@ -0,0 +1,26 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
pub struct Inner<T> {
|
||||
field: T,
|
||||
}
|
||||
|
||||
unsafe impl<T> Send for Inner<T>
|
||||
where
|
||||
T: Copy + Send,
|
||||
{
|
||||
}
|
||||
|
||||
// @has no_redundancy/struct.Outer.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<T> Send for \
|
||||
// Outer<T> where T: Copy + Send"
|
||||
pub struct Outer<T> {
|
||||
inner_field: Inner<T>,
|
||||
}
|
43
src/test/rustdoc/synthetic_auto/project.rs
Normal file
43
src/test/rustdoc/synthetic_auto/project.rs
Normal file
@ -0,0 +1,43 @@
|
||||
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
pub struct Inner<'a, T: 'a> {
|
||||
field: &'a T,
|
||||
}
|
||||
|
||||
trait MyTrait {
|
||||
type MyItem;
|
||||
}
|
||||
|
||||
trait OtherTrait {}
|
||||
|
||||
unsafe impl<'a, T> Send for Inner<'a, T>
|
||||
where
|
||||
'a: 'static,
|
||||
T: MyTrait<MyItem = bool>,
|
||||
{
|
||||
}
|
||||
unsafe impl<'a, T> Sync for Inner<'a, T>
|
||||
where
|
||||
'a: 'static,
|
||||
T: MyTrait,
|
||||
<T as MyTrait>::MyItem: OtherTrait,
|
||||
{
|
||||
}
|
||||
|
||||
// @has project/struct.Foo.html
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'c, K> Send \
|
||||
// for Foo<'c, K> where K: MyTrait<MyItem = bool>, 'c: 'static"
|
||||
//
|
||||
// @has - '//*[@id="synthetic-implementations-list"]/*[@class="impl"]/*/code' "impl<'c, K> Sync \
|
||||
// for Foo<'c, K> where K: MyTrait, <K as MyTrait>::MyItem: OtherTrait, 'c: 'static,"
|
||||
pub struct Foo<'c, K: 'c> {
|
||||
inner_field: Inner<'c, K>,
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
error[E0619]: the type of this value must be known in this context
|
||||
--> $DIR/E0619.rs:15:9
|
||||
|
|
||||
15 | (..) => {} //~ ERROR E0619
|
||||
| ^^^^
|
||||
|
||||
error: aborting due to previous error
|
||||
|
@ -1,4 +1,4 @@
|
||||
warning: the type of this value must be known in this context
|
||||
warning: type annotations needed
|
||||
--> $DIR/inference-variable-behind-raw-pointer.rs:18:13
|
||||
|
|
||||
18 | if data.is_null() {}
|
||||
|
@ -15,11 +15,11 @@
|
||||
fn shines_a_beacon_through_the_darkness() {
|
||||
let x: Option<_> = None;
|
||||
x.unwrap().method_that_could_exist_on_some_type();
|
||||
//~^ ERROR 17:5: 17:15: the type of this value must be known in this context
|
||||
//~^ ERROR 17:5: 17:15: type annotations needed
|
||||
}
|
||||
|
||||
fn courier_to_des_moines_and_points_west(data: &[u32]) -> String {
|
||||
data.iter() //~ ERROR 22:5: 23:20: the type of this value must be known in this context
|
||||
data.iter() //~ ERROR 22:5: 23:20: type annotations needed
|
||||
.sum::<_>()
|
||||
.to_string()
|
||||
}
|
||||
|
@ -1,15 +1,17 @@
|
||||
error[E0619]: the type of this value must be known in this context
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/issue-42234-unknown-receiver-type.rs:17:5
|
||||
|
|
||||
16 | let x: Option<_> = None;
|
||||
| - consider giving `x` a type
|
||||
17 | x.unwrap().method_that_could_exist_on_some_type();
|
||||
| ^^^^^^^^^^
|
||||
| ^^^^^^^^^^ cannot infer type for `T`
|
||||
|
||||
error[E0619]: the type of this value must be known in this context
|
||||
error[E0282]: type annotations needed
|
||||
--> $DIR/issue-42234-unknown-receiver-type.rs:22:5
|
||||
|
|
||||
22 | / data.iter() //~ ERROR 22:5: 23:20: the type of this value must be known in this context
|
||||
22 | / data.iter() //~ ERROR 22:5: 23:20: type annotations needed
|
||||
23 | | .sum::<_>()
|
||||
| |___________________^
|
||||
| |___________________^ cannot infer type for `_`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user