Auto merge of #46384 - ollie27:rustdoc_inline_assoc, r=QuietMisdreavus
rustdoc: Fix issues with cross-crate inlined associated items * Visibility was missing from impl items. * Attributes and docs were missing from consts and types in impls. * Const default values were missing from traits. This unifies the code that handles associated items from impls and traits.
This commit is contained in:
commit
16ba4591d7
5 changed files with 158 additions and 97 deletions
|
@ -332,74 +332,10 @@ pub fn build_impl(cx: &DocContext, did: DefId, ret: &mut Vec<clean::Item>) {
|
|||
|
||||
let predicates = tcx.predicates_of(did);
|
||||
let trait_items = tcx.associated_items(did).filter_map(|item| {
|
||||
match item.kind {
|
||||
ty::AssociatedKind::Const => {
|
||||
let default = if item.defaultness.has_value() {
|
||||
Some(print_inlined_const(cx, item.def_id))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Some(clean::Item {
|
||||
name: Some(item.name.clean(cx)),
|
||||
inner: clean::AssociatedConstItem(
|
||||
tcx.type_of(item.def_id).clean(cx),
|
||||
default,
|
||||
),
|
||||
source: tcx.def_span(item.def_id).clean(cx),
|
||||
attrs: clean::Attributes::default(),
|
||||
visibility: None,
|
||||
stability: tcx.lookup_stability(item.def_id).clean(cx),
|
||||
deprecation: tcx.lookup_deprecation(item.def_id).clean(cx),
|
||||
def_id: item.def_id
|
||||
})
|
||||
}
|
||||
ty::AssociatedKind::Method => {
|
||||
if item.vis != ty::Visibility::Public && associated_trait.is_none() {
|
||||
return None
|
||||
}
|
||||
let mut cleaned = item.clean(cx);
|
||||
cleaned.inner = match cleaned.inner.clone() {
|
||||
clean::TyMethodItem(clean::TyMethod {
|
||||
unsafety, decl, generics, abi
|
||||
}) => {
|
||||
let constness = if tcx.is_const_fn(item.def_id) {
|
||||
hir::Constness::Const
|
||||
} else {
|
||||
hir::Constness::NotConst
|
||||
};
|
||||
|
||||
clean::MethodItem(clean::Method {
|
||||
unsafety,
|
||||
constness,
|
||||
decl,
|
||||
generics,
|
||||
abi,
|
||||
})
|
||||
}
|
||||
ref r => panic!("not a tymethod: {:?}", r),
|
||||
};
|
||||
Some(cleaned)
|
||||
}
|
||||
ty::AssociatedKind::Type => {
|
||||
let typedef = clean::Typedef {
|
||||
type_: tcx.type_of(item.def_id).clean(cx),
|
||||
generics: clean::Generics {
|
||||
lifetimes: vec![],
|
||||
type_params: vec![],
|
||||
where_predicates: vec![]
|
||||
}
|
||||
};
|
||||
Some(clean::Item {
|
||||
name: Some(item.name.clean(cx)),
|
||||
inner: clean::TypedefItem(typedef, true),
|
||||
source: tcx.def_span(item.def_id).clean(cx),
|
||||
attrs: clean::Attributes::default(),
|
||||
visibility: None,
|
||||
stability: tcx.lookup_stability(item.def_id).clean(cx),
|
||||
deprecation: tcx.lookup_deprecation(item.def_id).clean(cx),
|
||||
def_id: item.def_id
|
||||
})
|
||||
}
|
||||
if associated_trait.is_some() || item.vis == ty::Visibility::Public {
|
||||
Some(item.clean(cx))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}).collect::<Vec<_>>();
|
||||
let polarity = tcx.impl_polarity(did);
|
||||
|
|
|
@ -1595,7 +1595,12 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
|
|||
let inner = match self.kind {
|
||||
ty::AssociatedKind::Const => {
|
||||
let ty = cx.tcx.type_of(self.def_id);
|
||||
AssociatedConstItem(ty.clean(cx), None)
|
||||
let default = if self.defaultness.has_value() {
|
||||
Some(inline::print_inlined_const(cx, self.def_id))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
AssociatedConstItem(ty.clean(cx), default)
|
||||
}
|
||||
ty::AssociatedKind::Method => {
|
||||
let generics = (cx.tcx.generics_of(self.def_id),
|
||||
|
@ -1626,18 +1631,21 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
|
|||
}
|
||||
|
||||
let provided = match self.container {
|
||||
ty::ImplContainer(_) => false,
|
||||
ty::ImplContainer(_) => true,
|
||||
ty::TraitContainer(_) => self.defaultness.has_value()
|
||||
};
|
||||
if provided {
|
||||
let constness = if cx.tcx.is_const_fn(self.def_id) {
|
||||
hir::Constness::Const
|
||||
} else {
|
||||
hir::Constness::NotConst
|
||||
};
|
||||
MethodItem(Method {
|
||||
unsafety: sig.unsafety(),
|
||||
generics,
|
||||
decl,
|
||||
abi: sig.abi(),
|
||||
|
||||
// trait methods cannot (currently, at least) be const
|
||||
constness: hir::Constness::NotConst,
|
||||
constness,
|
||||
})
|
||||
} else {
|
||||
TyMethodItem(TyMethod {
|
||||
|
@ -1651,14 +1659,14 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
|
|||
ty::AssociatedKind::Type => {
|
||||
let my_name = self.name.clean(cx);
|
||||
|
||||
let mut bounds = if let ty::TraitContainer(did) = self.container {
|
||||
if let ty::TraitContainer(did) = self.container {
|
||||
// When loading a cross-crate associated type, the bounds for this type
|
||||
// are actually located on the trait/impl itself, so we need to load
|
||||
// all of the generics from there and then look for bounds that are
|
||||
// applied to this associated type in question.
|
||||
let predicates = cx.tcx.predicates_of(did);
|
||||
let generics = (cx.tcx.generics_of(did), &predicates).clean(cx);
|
||||
generics.where_predicates.iter().filter_map(|pred| {
|
||||
let mut bounds = generics.where_predicates.iter().filter_map(|pred| {
|
||||
let (name, self_type, trait_, bounds) = match *pred {
|
||||
WherePredicate::BoundPredicate {
|
||||
ty: QPath { ref name, ref self_type, ref trait_ },
|
||||
|
@ -1676,34 +1684,45 @@ impl<'tcx> Clean<Item> for ty::AssociatedItem {
|
|||
_ => return None,
|
||||
}
|
||||
Some(bounds)
|
||||
}).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>()
|
||||
} else {
|
||||
vec![]
|
||||
};
|
||||
}).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>();
|
||||
// Our Sized/?Sized bound didn't get handled when creating the generics
|
||||
// because we didn't actually get our whole set of bounds until just now
|
||||
// (some of them may have come from the trait). If we do have a sized
|
||||
// bound, we remove it, and if we don't then we add the `?Sized` bound
|
||||
// at the end.
|
||||
match bounds.iter().position(|b| b.is_sized_bound(cx)) {
|
||||
Some(i) => { bounds.remove(i); }
|
||||
None => bounds.push(TyParamBound::maybe_sized(cx)),
|
||||
}
|
||||
|
||||
// Our Sized/?Sized bound didn't get handled when creating the generics
|
||||
// because we didn't actually get our whole set of bounds until just now
|
||||
// (some of them may have come from the trait). If we do have a sized
|
||||
// bound, we remove it, and if we don't then we add the `?Sized` bound
|
||||
// at the end.
|
||||
match bounds.iter().position(|b| b.is_sized_bound(cx)) {
|
||||
Some(i) => { bounds.remove(i); }
|
||||
None => bounds.push(TyParamBound::maybe_sized(cx)),
|
||||
let ty = if self.defaultness.has_value() {
|
||||
Some(cx.tcx.type_of(self.def_id))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
AssociatedTypeItem(bounds, ty.clean(cx))
|
||||
} else {
|
||||
TypedefItem(Typedef {
|
||||
type_: cx.tcx.type_of(self.def_id).clean(cx),
|
||||
generics: Generics {
|
||||
lifetimes: Vec::new(),
|
||||
type_params: Vec::new(),
|
||||
where_predicates: Vec::new(),
|
||||
},
|
||||
}, true)
|
||||
}
|
||||
|
||||
let ty = if self.defaultness.has_value() {
|
||||
Some(cx.tcx.type_of(self.def_id))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
AssociatedTypeItem(bounds, ty.clean(cx))
|
||||
}
|
||||
};
|
||||
|
||||
let visibility = match self.container {
|
||||
ty::ImplContainer(_) => self.vis.clean(cx),
|
||||
ty::TraitContainer(_) => None,
|
||||
};
|
||||
|
||||
Item {
|
||||
name: Some(self.name.clean(cx)),
|
||||
visibility: Some(Inherited),
|
||||
visibility,
|
||||
stability: get_stability(cx, self.def_id),
|
||||
deprecation: get_deprecation(cx, self.def_id),
|
||||
def_id: self.def_id,
|
||||
|
|
|
@ -2621,7 +2621,8 @@ fn assoc_const(w: &mut fmt::Formatter,
|
|||
ty: &clean::Type,
|
||||
_default: Option<&String>,
|
||||
link: AssocItemLink) -> fmt::Result {
|
||||
write!(w, "const <a href='{}' class=\"constant\"><b>{}</b></a>: {}",
|
||||
write!(w, "{}const <a href='{}' class=\"constant\"><b>{}</b></a>: {}",
|
||||
VisSpace(&it.visibility),
|
||||
naive_assoc_href(it, link),
|
||||
it.name.as_ref().unwrap(),
|
||||
ty)?;
|
||||
|
|
57
src/test/rustdoc/inline_cross/assoc-items.rs
Normal file
57
src/test/rustdoc/inline_cross/assoc-items.rs
Normal file
|
@ -0,0 +1,57 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
// aux-build:assoc-items.rs
|
||||
// build-aux-docs
|
||||
// ignore-cross-compile
|
||||
|
||||
#![crate_name = "foo"]
|
||||
|
||||
extern crate assoc_items;
|
||||
|
||||
// @has foo/struct.MyStruct.html
|
||||
// @!has - 'PrivateConst'
|
||||
// @has - '//*[@id="associatedconstant.PublicConst"]' 'pub const PublicConst: u8'
|
||||
// @has - '//*[@class="docblock"]' 'PublicConst: u8 = 123'
|
||||
// @has - '//*[@class="docblock"]' 'docs for PublicConst'
|
||||
// @!has - 'private_method'
|
||||
// @has - '//*[@id="method.public_method"]' 'pub fn public_method()'
|
||||
// @has - '//*[@class="docblock"]' 'docs for public_method'
|
||||
// @has - '//*[@id="associatedconstant.ConstNoDefault"]' 'const ConstNoDefault: i16'
|
||||
// @has - '//*[@class="docblock"]' 'ConstNoDefault: i16 = -123'
|
||||
// @has - '//*[@class="docblock"]' 'dox for ConstNoDefault'
|
||||
// @has - '//*[@id="associatedconstant.ConstWithDefault"]' 'const ConstWithDefault: u16'
|
||||
// @has - '//*[@class="docblock"]' 'ConstWithDefault: u16 = 12345'
|
||||
// @has - '//*[@class="docblock"]' 'docs for ConstWithDefault'
|
||||
// @has - '//*[@id="associatedtype.TypeNoDefault"]' 'type TypeNoDefault = i32'
|
||||
// @has - '//*[@class="docblock"]' 'dox for TypeNoDefault'
|
||||
// @has - '//*[@id="associatedtype.TypeWithDefault"]' 'type TypeWithDefault = u32'
|
||||
// @has - '//*[@class="docblock"]' 'docs for TypeWithDefault'
|
||||
// @has - '//*[@id="method.method_no_default"]' 'fn method_no_default()'
|
||||
// @has - '//*[@class="docblock"]' 'dox for method_no_default'
|
||||
// @has - '//*[@id="method.method_with_default"]' 'fn method_with_default()'
|
||||
// @has - '//*[@class="docblock"]' 'docs for method_with_default'
|
||||
pub use assoc_items::MyStruct;
|
||||
|
||||
// @has foo/trait.MyTrait.html
|
||||
// @has - '//*[@id="associatedconstant.ConstNoDefault"]' 'const ConstNoDefault: i16'
|
||||
// @has - '//*[@class="docblock"]' 'docs for ConstNoDefault'
|
||||
// @has - '//*[@id="associatedconstant.ConstWithDefault"]' 'const ConstWithDefault: u16'
|
||||
// @has - '//*[@class="docblock"]' 'ConstWithDefault: u16 = 12345'
|
||||
// @has - '//*[@class="docblock"]' 'docs for ConstWithDefault'
|
||||
// @has - '//*[@id="associatedtype.TypeNoDefault"]' 'type TypeNoDefault'
|
||||
// @has - '//*[@class="docblock"]' 'docs for TypeNoDefault'
|
||||
// @has - '//*[@id="associatedtype.TypeWithDefault"]' 'type TypeWithDefault = u32'
|
||||
// @has - '//*[@class="docblock"]' 'docs for TypeWithDefault'
|
||||
// @has - '//*[@id="tymethod.method_no_default"]' 'fn method_no_default()'
|
||||
// @has - '//*[@class="docblock"]' 'docs for method_no_default'
|
||||
// @has - '//*[@id="method.method_with_default"]' 'fn method_with_default()'
|
||||
// @has - '//*[@class="docblock"]' 'docs for method_with_default'
|
||||
pub use assoc_items::MyTrait;
|
48
src/test/rustdoc/inline_cross/auxiliary/assoc-items.rs
Normal file
48
src/test/rustdoc/inline_cross/auxiliary/assoc-items.rs
Normal file
|
@ -0,0 +1,48 @@
|
|||
// Copyright 2017 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.
|
||||
|
||||
#![feature(associated_type_defaults)]
|
||||
|
||||
pub struct MyStruct;
|
||||
|
||||
impl MyStruct {
|
||||
/// docs for PrivateConst
|
||||
const PrivateConst: i8 = -123;
|
||||
/// docs for PublicConst
|
||||
pub const PublicConst: u8 = 123;
|
||||
/// docs for private_method
|
||||
fn private_method() {}
|
||||
/// docs for public_method
|
||||
pub fn public_method() {}
|
||||
}
|
||||
|
||||
pub trait MyTrait {
|
||||
/// docs for ConstNoDefault
|
||||
const ConstNoDefault: i16;
|
||||
/// docs for ConstWithDefault
|
||||
const ConstWithDefault: u16 = 12345;
|
||||
/// docs for TypeNoDefault
|
||||
type TypeNoDefault;
|
||||
/// docs for TypeWithDefault
|
||||
type TypeWithDefault = u32;
|
||||
/// docs for method_no_default
|
||||
fn method_no_default();
|
||||
/// docs for method_with_default
|
||||
fn method_with_default() {}
|
||||
}
|
||||
|
||||
impl MyTrait for MyStruct {
|
||||
/// dox for ConstNoDefault
|
||||
const ConstNoDefault: i16 = -12345;
|
||||
/// dox for TypeNoDefault
|
||||
type TypeNoDefault = i32;
|
||||
/// dox for method_no_default
|
||||
fn method_no_default() {}
|
||||
}
|
Loading…
Reference in a new issue