rustc: unify and simplify managing associated items.
This commit is contained in:
parent
da2ce22768
commit
de0ffadb67
45 changed files with 1035 additions and 1687 deletions
|
|
@ -163,7 +163,7 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
|
|||
pub fn build_external_trait<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||
did: DefId) -> clean::Trait {
|
||||
let def = tcx.lookup_trait_def(did);
|
||||
let trait_items = tcx.trait_items(did).clean(cx);
|
||||
let trait_items = tcx.associated_items(did).map(|item| item.clean(cx)).collect();
|
||||
let predicates = tcx.lookup_predicates(did);
|
||||
let generics = (def.generics, &predicates).clean(cx);
|
||||
let generics = filter_non_trait_generics(did, generics);
|
||||
|
|
@ -307,7 +307,6 @@ pub fn build_impls<'a, 'tcx>(cx: &DocContext,
|
|||
|
||||
for def_id in primitive_impls.iter().filter_map(|&def_id| def_id) {
|
||||
if !def_id.is_local() {
|
||||
tcx.populate_implementations_for_primitive_if_necessary(def_id);
|
||||
build_impl(cx, tcx, def_id, &mut impls);
|
||||
}
|
||||
}
|
||||
|
|
@ -367,21 +366,18 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
|
|||
}
|
||||
|
||||
let predicates = tcx.lookup_predicates(did);
|
||||
let trait_items = tcx.sess.cstore.impl_or_trait_items(did)
|
||||
.iter()
|
||||
.filter_map(|&did| {
|
||||
match tcx.impl_or_trait_item(did) {
|
||||
ty::ConstTraitItem(ref assoc_const) => {
|
||||
let did = assoc_const.def_id;
|
||||
let type_scheme = tcx.lookup_item_type(did);
|
||||
let default = if assoc_const.has_value {
|
||||
let trait_items = tcx.associated_items(did).filter_map(|item| {
|
||||
match item.kind {
|
||||
ty::AssociatedKind::Const => {
|
||||
let type_scheme = tcx.lookup_item_type(item.def_id);
|
||||
let default = if item.has_value {
|
||||
Some(pprust::expr_to_string(
|
||||
lookup_const_by_id(tcx, did, None).unwrap().0))
|
||||
lookup_const_by_id(tcx, item.def_id, None).unwrap().0))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Some(clean::Item {
|
||||
name: Some(assoc_const.name.clean(cx)),
|
||||
name: Some(item.name.clean(cx)),
|
||||
inner: clean::AssociatedConstItem(
|
||||
type_scheme.ty.clean(cx),
|
||||
default,
|
||||
|
|
@ -389,21 +385,21 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
|
|||
source: clean::Span::empty(),
|
||||
attrs: vec![],
|
||||
visibility: None,
|
||||
stability: tcx.lookup_stability(did).clean(cx),
|
||||
deprecation: tcx.lookup_deprecation(did).clean(cx),
|
||||
def_id: did
|
||||
stability: tcx.lookup_stability(item.def_id).clean(cx),
|
||||
deprecation: tcx.lookup_deprecation(item.def_id).clean(cx),
|
||||
def_id: item.def_id
|
||||
})
|
||||
}
|
||||
ty::MethodTraitItem(method) => {
|
||||
if method.vis != ty::Visibility::Public && associated_trait.is_none() {
|
||||
ty::AssociatedKind::Method => {
|
||||
if item.vis != ty::Visibility::Public && associated_trait.is_none() {
|
||||
return None
|
||||
}
|
||||
let mut item = method.clean(cx);
|
||||
item.inner = match item.inner.clone() {
|
||||
let mut cleaned = item.clean(cx);
|
||||
cleaned.inner = match cleaned.inner.clone() {
|
||||
clean::TyMethodItem(clean::TyMethod {
|
||||
unsafety, decl, generics, abi
|
||||
}) => {
|
||||
let constness = if tcx.sess.cstore.is_const_fn(did) {
|
||||
let constness = if tcx.sess.cstore.is_const_fn(item.def_id) {
|
||||
hir::Constness::Const
|
||||
} else {
|
||||
hir::Constness::NotConst
|
||||
|
|
@ -419,12 +415,11 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
|
|||
}
|
||||
_ => panic!("not a tymethod"),
|
||||
};
|
||||
Some(item)
|
||||
Some(cleaned)
|
||||
}
|
||||
ty::TypeTraitItem(ref assoc_ty) => {
|
||||
let did = assoc_ty.def_id;
|
||||
ty::AssociatedKind::Type => {
|
||||
let typedef = clean::Typedef {
|
||||
type_: assoc_ty.ty.unwrap().clean(cx),
|
||||
type_: tcx.lookup_item_type(item.def_id).ty.clean(cx),
|
||||
generics: clean::Generics {
|
||||
lifetimes: vec![],
|
||||
type_params: vec![],
|
||||
|
|
@ -432,14 +427,14 @@ pub fn build_impl<'a, 'tcx>(cx: &DocContext,
|
|||
}
|
||||
};
|
||||
Some(clean::Item {
|
||||
name: Some(assoc_ty.name.clean(cx)),
|
||||
name: Some(item.name.clean(cx)),
|
||||
inner: clean::TypedefItem(typedef, true),
|
||||
source: clean::Span::empty(),
|
||||
attrs: vec![],
|
||||
visibility: None,
|
||||
stability: tcx.lookup_stability(did).clean(cx),
|
||||
deprecation: tcx.lookup_deprecation(did).clean(cx),
|
||||
def_id: did
|
||||
stability: tcx.lookup_stability(item.def_id).clean(cx),
|
||||
deprecation: tcx.lookup_deprecation(item.def_id).clean(cx),
|
||||
def_id: item.def_id
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1338,47 +1338,116 @@ impl Clean<Item> for hir::ImplItem {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<Item> for ty::Method<'tcx> {
|
||||
impl<'tcx> Clean<Item> for ty::AssociatedItem {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
let generics = (self.generics, &self.predicates).clean(cx);
|
||||
let mut decl = (self.def_id, &self.fty.sig).clean(cx);
|
||||
match self.explicit_self {
|
||||
ty::ExplicitSelfCategory::ByValue => {
|
||||
decl.inputs.values[0].type_ = Infer;
|
||||
let inner = match self.kind {
|
||||
ty::AssociatedKind::Const => {
|
||||
let ty = cx.tcx().lookup_item_type(self.def_id).ty;
|
||||
AssociatedConstItem(ty.clean(cx), None)
|
||||
}
|
||||
ty::ExplicitSelfCategory::ByReference(..) => {
|
||||
match decl.inputs.values[0].type_ {
|
||||
BorrowedRef{ref mut type_, ..} => **type_ = Infer,
|
||||
_ => unreachable!(),
|
||||
ty::AssociatedKind::Method => {
|
||||
let generics = (cx.tcx().lookup_generics(self.def_id),
|
||||
&cx.tcx().lookup_predicates(self.def_id)).clean(cx);
|
||||
let fty = match cx.tcx().lookup_item_type(self.def_id).ty.sty {
|
||||
ty::TyFnDef(_, _, f) => f,
|
||||
_ => unreachable!()
|
||||
};
|
||||
let mut decl = (self.def_id, &fty.sig).clean(cx);
|
||||
|
||||
if self.method_has_self_argument {
|
||||
let self_ty = match self.container {
|
||||
ty::ImplContainer(def_id) => {
|
||||
cx.tcx().lookup_item_type(def_id).ty
|
||||
}
|
||||
ty::TraitContainer(_) => cx.tcx().mk_self_type()
|
||||
};
|
||||
let self_arg_ty = *fty.sig.input(0).skip_binder();
|
||||
if self_arg_ty == self_ty {
|
||||
decl.inputs.values[0].type_ = Infer;
|
||||
} else if let ty::TyRef(_, mt) = self_arg_ty.sty {
|
||||
if mt.ty == self_ty {
|
||||
match decl.inputs.values[0].type_ {
|
||||
BorrowedRef{ref mut type_, ..} => **type_ = Infer,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let provided = match self.container {
|
||||
ty::ImplContainer(_) => false,
|
||||
ty::TraitContainer(_) => self.has_value
|
||||
};
|
||||
if provided {
|
||||
MethodItem(Method {
|
||||
unsafety: fty.unsafety,
|
||||
generics: generics,
|
||||
decl: decl,
|
||||
abi: fty.abi,
|
||||
|
||||
// trait methods canot (currently, at least) be const
|
||||
constness: hir::Constness::NotConst,
|
||||
})
|
||||
} else {
|
||||
TyMethodItem(TyMethod {
|
||||
unsafety: fty.unsafety,
|
||||
generics: generics,
|
||||
decl: decl,
|
||||
abi: fty.abi,
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
let provided = match self.container {
|
||||
ty::ImplContainer(..) => false,
|
||||
ty::TraitContainer(did) => {
|
||||
cx.tcx().provided_trait_methods(did).iter().any(|m| {
|
||||
m.def_id == self.def_id
|
||||
})
|
||||
}
|
||||
};
|
||||
let inner = if provided {
|
||||
MethodItem(Method {
|
||||
unsafety: self.fty.unsafety,
|
||||
generics: generics,
|
||||
decl: decl,
|
||||
abi: self.fty.abi,
|
||||
ty::AssociatedKind::Type => {
|
||||
let my_name = self.name.clean(cx);
|
||||
|
||||
// trait methods canot (currently, at least) be const
|
||||
constness: hir::Constness::NotConst,
|
||||
})
|
||||
} else {
|
||||
TyMethodItem(TyMethod {
|
||||
unsafety: self.fty.unsafety,
|
||||
generics: generics,
|
||||
decl: decl,
|
||||
abi: self.fty.abi,
|
||||
})
|
||||
let mut bounds = 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 def = cx.tcx().lookup_trait_def(did);
|
||||
let predicates = cx.tcx().lookup_predicates(did);
|
||||
let generics = (def.generics, &predicates).clean(cx);
|
||||
generics.where_predicates.iter().filter_map(|pred| {
|
||||
let (name, self_type, trait_, bounds) = match *pred {
|
||||
WherePredicate::BoundPredicate {
|
||||
ty: QPath { ref name, ref self_type, ref trait_ },
|
||||
ref bounds
|
||||
} => (name, self_type, trait_, bounds),
|
||||
_ => return None,
|
||||
};
|
||||
if *name != my_name { return None }
|
||||
match **trait_ {
|
||||
ResolvedPath { did, .. } if did == self.container.id() => {}
|
||||
_ => return None,
|
||||
}
|
||||
match **self_type {
|
||||
Generic(ref s) if *s == "Self" => {}
|
||||
_ => return None,
|
||||
}
|
||||
Some(bounds)
|
||||
}).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>()
|
||||
} else {
|
||||
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)),
|
||||
}
|
||||
|
||||
let ty = if self.has_value {
|
||||
Some(cx.tcx().lookup_item_type(self.def_id).ty)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
AssociatedTypeItem(bounds, ty.clean(cx))
|
||||
}
|
||||
};
|
||||
|
||||
Item {
|
||||
|
|
@ -1394,16 +1463,6 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
match *self {
|
||||
ty::ConstTraitItem(ref cti) => cti.clean(cx),
|
||||
ty::MethodTraitItem(ref mti) => mti.clean(cx),
|
||||
ty::TypeTraitItem(ref tti) => tti.clean(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A trait reference, which may have higher ranked lifetimes.
|
||||
#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Debug)]
|
||||
pub struct PolyTrait {
|
||||
|
|
@ -2884,79 +2943,6 @@ impl Clean<Deprecation> for attr::Deprecation {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
Item {
|
||||
source: DUMMY_SP.clean(cx),
|
||||
name: Some(self.name.clean(cx)),
|
||||
attrs: Vec::new(),
|
||||
inner: AssociatedConstItem(self.ty.clean(cx), None),
|
||||
visibility: None,
|
||||
def_id: self.def_id,
|
||||
stability: None,
|
||||
deprecation: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> {
|
||||
fn clean(&self, cx: &DocContext) -> Item {
|
||||
let my_name = self.name.clean(cx);
|
||||
|
||||
let mut bounds = 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 def = cx.tcx().lookup_trait_def(did);
|
||||
let predicates = cx.tcx().lookup_predicates(did);
|
||||
let generics = (def.generics, &predicates).clean(cx);
|
||||
generics.where_predicates.iter().filter_map(|pred| {
|
||||
let (name, self_type, trait_, bounds) = match *pred {
|
||||
WherePredicate::BoundPredicate {
|
||||
ty: QPath { ref name, ref self_type, ref trait_ },
|
||||
ref bounds
|
||||
} => (name, self_type, trait_, bounds),
|
||||
_ => return None,
|
||||
};
|
||||
if *name != my_name { return None }
|
||||
match **trait_ {
|
||||
ResolvedPath { did, .. } if did == self.container.id() => {}
|
||||
_ => return None,
|
||||
}
|
||||
match **self_type {
|
||||
Generic(ref s) if *s == "Self" => {}
|
||||
_ => return None,
|
||||
}
|
||||
Some(bounds)
|
||||
}).flat_map(|i| i.iter().cloned()).collect::<Vec<_>>()
|
||||
} else {
|
||||
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)),
|
||||
}
|
||||
|
||||
Item {
|
||||
source: DUMMY_SP.clean(cx),
|
||||
name: Some(self.name.clean(cx)),
|
||||
attrs: inline::load_attrs(cx, cx.tcx(), self.def_id),
|
||||
inner: AssociatedTypeItem(bounds, self.ty.clean(cx)),
|
||||
visibility: self.vis.clean(cx),
|
||||
def_id: self.def_id,
|
||||
stability: cx.tcx().lookup_stability(self.def_id).clean(cx),
|
||||
deprecation: cx.tcx().lookup_deprecation(self.def_id).clean(cx),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn lang_struct(cx: &DocContext, did: Option<DefId>,
|
||||
t: ty::Ty, name: &str,
|
||||
fallback: fn(Box<Type>) -> Type) -> Type {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue