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:
bors 2017-12-03 00:54:52 +00:00
commit 16ba4591d7
5 changed files with 158 additions and 97 deletions

View file

@ -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);

View file

@ -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,

View file

@ -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)?;