impl<'tcx> Clean<'tcx, Item> for DocModule<'tcx> {
fn clean(&self, cx: &mut DocContext<'tcx>) -> Item {
let mut items: Vec<Item> = vec![];
- items.extend(
- self.foreigns
- .iter()
- .map(|(item, renamed)| clean_maybe_renamed_foreign_item(cx, item, *renamed)),
- );
- items.extend(self.mods.iter().map(|x| x.clean(cx)));
+ let mut inserted = FxHashSet::default();
+ items.extend(self.foreigns.iter().map(|(item, renamed)| {
+ let item = clean_maybe_renamed_foreign_item(cx, item, *renamed);
+ if let Some(name) = item.name {
+ inserted.insert((item.type_(), name));
+ }
+ item
+ }));
+ items.extend(self.mods.iter().map(|x| {
+ inserted.insert((ItemType::Module, x.name));
+ x.clean(cx)
+ }));
// Split up imports from all other items.
//
// This covers the case where somebody does an import which should pull in an item,
// but there's already an item with the same namespace and same name. Rust gives
// priority to the not-imported one, so we should, too.
- let mut inserted = FxHashSet::default();
items.extend(self.items.iter().flat_map(|(item, renamed)| {
// First, lower everything other than imports.
if matches!(item.kind, hir::ItemKind::Use(..)) {
}
}
-impl<'tcx> Clean<'tcx, Attributes> for [ast::Attribute] {
- fn clean(&self, _cx: &mut DocContext<'_>) -> Attributes {
- Attributes::from_ast(self, None)
- }
-}
-
impl<'tcx> Clean<'tcx, Option<GenericBound>> for hir::GenericBound<'tcx> {
fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<GenericBound> {
Some(match *self {
- hir::GenericBound::Outlives(lt) => GenericBound::Outlives(lt.clean(cx)),
+ hir::GenericBound::Outlives(lt) => GenericBound::Outlives(clean_lifetime(lt, cx)),
hir::GenericBound::LangItemTrait(lang_item, span, _, generic_args) => {
let def_id = cx.tcx.require_lang_item(lang_item, Some(span));
}
}
-fn clean_trait_ref_with_bindings<'tcx>(
+pub(crate) fn clean_trait_ref_with_bindings<'tcx>(
cx: &mut DocContext<'tcx>,
trait_ref: ty::TraitRef<'tcx>,
bindings: &[TypeBinding],
path
}
-impl<'tcx> Clean<'tcx, Path> for ty::TraitRef<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> Path {
- clean_trait_ref_with_bindings(cx, *self, &[])
- }
-}
-
fn clean_poly_trait_ref_with_bindings<'tcx>(
cx: &mut DocContext<'tcx>,
poly_trait_ref: ty::PolyTraitRef<'tcx>,
}
}
-impl<'tcx> Clean<'tcx, Lifetime> for hir::Lifetime {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> Lifetime {
- let def = cx.tcx.named_region(self.hir_id);
- if let Some(
- rl::Region::EarlyBound(_, node_id)
- | rl::Region::LateBound(_, _, node_id)
- | rl::Region::Free(_, node_id),
- ) = def
- {
- if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
- return lt;
- }
+fn clean_lifetime<'tcx>(lifetime: hir::Lifetime, cx: &mut DocContext<'tcx>) -> Lifetime {
+ let def = cx.tcx.named_region(lifetime.hir_id);
+ if let Some(
+ rl::Region::EarlyBound(_, node_id)
+ | rl::Region::LateBound(_, _, node_id)
+ | rl::Region::Free(_, node_id),
+ ) = def
+ {
+ if let Some(lt) = cx.substs.get(&node_id).and_then(|p| p.as_lt()).cloned() {
+ return lt;
}
- Lifetime(self.name.ident().name)
}
+ Lifetime(lifetime.name.ident().name)
}
pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'tcx>) -> Constant {
}
}
-impl<'tcx> Clean<'tcx, Option<Lifetime>> for ty::Region<'tcx> {
- fn clean(&self, _cx: &mut DocContext<'_>) -> Option<Lifetime> {
- match **self {
- ty::ReStatic => Some(Lifetime::statik()),
- ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => {
- if name != kw::UnderscoreLifetime { Some(Lifetime(name)) } else { None }
- }
- ty::ReEarlyBound(ref data) => {
- if data.name != kw::UnderscoreLifetime {
- Some(Lifetime(data.name))
- } else {
- None
- }
- }
- ty::ReLateBound(..)
- | ty::ReFree(..)
- | ty::ReVar(..)
- | ty::RePlaceholder(..)
- | ty::ReEmpty(_)
- | ty::ReErased => {
- debug!("cannot clean region {:?}", self);
+pub(crate) fn clean_middle_region<'tcx>(region: ty::Region<'tcx>) -> Option<Lifetime> {
+ match *region {
+ ty::ReStatic => Some(Lifetime::statik()),
+ ty::ReLateBound(_, ty::BoundRegion { kind: ty::BrNamed(_, name), .. }) => {
+ if name != kw::UnderscoreLifetime { Some(Lifetime(name)) } else { None }
+ }
+ ty::ReEarlyBound(ref data) => {
+ if data.name != kw::UnderscoreLifetime {
+ Some(Lifetime(data.name))
+ } else {
None
}
}
+ ty::ReLateBound(..)
+ | ty::ReFree(..)
+ | ty::ReVar(..)
+ | ty::RePlaceholder(..)
+ | ty::ReEmpty(_)
+ | ty::ReErased => {
+ debug!("cannot clean region {:?}", region);
+ None
+ }
}
}
}
hir::WherePredicate::RegionPredicate(ref wrp) => WherePredicate::RegionPredicate {
- lifetime: wrp.lifetime.clean(cx),
+ lifetime: clean_lifetime(wrp.lifetime, cx),
bounds: wrp.bounds.iter().filter_map(|x| x.clean(cx)).collect(),
},
ty::PredicateKind::Trait(pred) => {
clean_poly_trait_predicate(bound_predicate.rebind(pred), cx)
}
- ty::PredicateKind::RegionOutlives(pred) => clean_region_outlives_predicate(pred, cx),
+ ty::PredicateKind::RegionOutlives(pred) => clean_region_outlives_predicate(pred),
ty::PredicateKind::TypeOutlives(pred) => clean_type_outlives_predicate(pred, cx),
ty::PredicateKind::Projection(pred) => Some(clean_projection_predicate(pred, cx)),
ty::PredicateKind::ConstEvaluatable(..) => None,
fn clean_region_outlives_predicate<'tcx>(
pred: ty::OutlivesPredicate<ty::Region<'tcx>, ty::Region<'tcx>>,
- cx: &mut DocContext<'tcx>,
) -> Option<WherePredicate> {
let ty::OutlivesPredicate(a, b) = pred;
}
Some(WherePredicate::RegionPredicate {
- lifetime: a.clean(cx).expect("failed to clean lifetime"),
- bounds: vec![GenericBound::Outlives(b.clean(cx).expect("failed to clean bounds"))],
+ lifetime: clean_middle_region(a).expect("failed to clean lifetime"),
+ bounds: vec![GenericBound::Outlives(
+ clean_middle_region(b).expect("failed to clean bounds"),
+ )],
})
}
Some(WherePredicate::BoundPredicate {
ty: clean_middle_ty(ty, cx, None),
- bounds: vec![GenericBound::Outlives(lt.clean(cx).expect("failed to clean lifetimes"))],
+ bounds: vec![GenericBound::Outlives(
+ clean_middle_region(lt).expect("failed to clean lifetimes"),
+ )],
bound_params: Vec::new(),
})
}
def_id: Option<DefId>,
) -> Type {
let lifted = ty.lift_to_tcx(cx.tcx).unwrap();
- let trait_ = lifted.trait_ref(cx.tcx).clean(cx);
+ let trait_ = clean_trait_ref_with_bindings(cx, lifted.trait_ref(cx.tcx), &[]);
let self_type = clean_middle_ty(ty.self_ty(), cx, None);
let self_def_id = if let Some(def_id) = def_id {
cx.tcx.opt_parent(def_id).or(Some(def_id))
.filter(|bp| !bp.in_where_clause)
.flat_map(|bp| bp.bounds)
.map(|bound| match bound {
- hir::GenericBound::Outlives(lt) => lt.clean(cx),
+ hir::GenericBound::Outlives(lt) => clean_lifetime(*lt, cx),
_ => panic!(),
})
.collect()
decl: &hir::FnDecl<'tcx>,
args: Arguments,
) -> FnDecl {
- FnDecl { inputs: args, output: decl.output.clean(cx), c_variadic: decl.c_variadic }
+ let output = match decl.output {
+ hir::FnRetTy::Return(typ) => Return(clean_ty(typ, cx)),
+ hir::FnRetTy::DefaultReturn(..) => DefaultReturn,
+ };
+ FnDecl { inputs: args, output, c_variadic: decl.c_variadic }
}
fn clean_fn_decl_from_did_and_sig<'tcx>(
}
}
-impl<'tcx> Clean<'tcx, FnRetTy> for hir::FnRetTy<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> FnRetTy {
- match *self {
- Self::Return(typ) => Return(clean_ty(typ, cx)),
- Self::DefaultReturn(..) => DefaultReturn,
- }
- }
-}
-
-impl<'tcx> Clean<'tcx, bool> for hir::IsAuto {
- fn clean(&self, _: &mut DocContext<'tcx>) -> bool {
- match *self {
- hir::IsAuto::Yes => true,
- hir::IsAuto::No => false,
- }
- }
-}
-
-impl<'tcx> Clean<'tcx, Path> for hir::TraitRef<'tcx> {
- fn clean(&self, cx: &mut DocContext<'tcx>) -> Path {
- let path = clean_path(self.path, cx);
- register_res(cx, path.res);
- path
- }
+fn clean_trait_ref<'tcx>(trait_ref: &hir::TraitRef<'tcx>, cx: &mut DocContext<'tcx>) -> Path {
+ let path = clean_path(trait_ref.path, cx);
+ register_res(cx, path.res);
+ path
}
impl<'tcx> Clean<'tcx, PolyTrait> for hir::PolyTraitRef<'tcx> {
fn clean(&self, cx: &mut DocContext<'tcx>) -> PolyTrait {
PolyTrait {
- trait_: self.trait_ref.clean(cx),
+ trait_: clean_trait_ref(&self.trait_ref, cx),
generic_params: self
.bound_generic_params
.iter()
});
if let Some(lt) = lifetime.cloned() {
let lt_def_id = cx.tcx.hir().local_def_id(param.hir_id);
- let cleaned = if !lt.is_elided() { lt.clean(cx) } else { Lifetime::elided() };
+ let cleaned =
+ if !lt.is_elided() { clean_lifetime(lt, cx) } else { Lifetime::elided() };
substs.insert(lt_def_id.to_def_id(), SubstParam::Lifetime(cleaned));
}
indices.lifetimes += 1;
// there's no case where it could cause the function to fail to compile.
let elided =
l.is_elided() || matches!(l.name, LifetimeName::Param(_, ParamName::Fresh));
- let lifetime = if elided { None } else { Some(l.clean(cx)) };
+ let lifetime = if elided { None } else { Some(clean_lifetime(*l, cx)) };
BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) }
}
TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))),
TyKind::Path(_) => clean_qpath(ty, cx),
TyKind::TraitObject(bounds, ref lifetime, _) => {
let bounds = bounds.iter().map(|bound| bound.clean(cx)).collect();
- let lifetime = if !lifetime.is_elided() { Some(lifetime.clean(cx)) } else { None };
+ let lifetime =
+ if !lifetime.is_elided() { Some(clean_lifetime(*lifetime, cx)) } else { None };
DynTrait(bounds, lifetime)
}
TyKind::BareFn(barefn) => BareFunction(Box::new(barefn.clean(cx))),
}
ty::RawPtr(mt) => RawPointer(mt.mutbl, Box::new(clean_middle_ty(mt.ty, cx, None))),
ty::Ref(r, ty, mutbl) => BorrowedRef {
- lifetime: r.clean(cx),
+ lifetime: clean_middle_region(r),
mutability: mutbl,
type_: Box::new(clean_middle_ty(ty, cx, None)),
},
// HACK: pick the first `did` as the `did` of the trait object. Someone
// might want to implement "native" support for marker-trait-only
// trait objects.
- let mut dids = obj.principal_def_id().into_iter().chain(obj.auto_traits());
- let did = dids
- .next()
+ let mut dids = obj.auto_traits();
+ let did = obj
+ .principal_def_id()
+ .or_else(|| dids.next())
.unwrap_or_else(|| panic!("found trait object `{:?}` with no traits?", this));
let substs = match obj.principal() {
Some(principal) => principal.skip_binder().substs,
inline::record_extern_fqn(cx, did, ItemType::Trait);
- let lifetime = reg.clean(cx);
- let mut bounds = vec![];
-
- for did in dids {
- let empty = cx.tcx.intern_substs(&[]);
- let path = external_path(cx, did, false, vec![], empty);
- inline::record_extern_fqn(cx, did, ItemType::Trait);
- let bound = PolyTrait { trait_: path, generic_params: Vec::new() };
- bounds.push(bound);
- }
+ let lifetime = clean_middle_region(*reg);
+ let mut bounds = dids
+ .map(|did| {
+ let empty = cx.tcx.intern_substs(&[]);
+ let path = external_path(cx, did, false, vec![], empty);
+ inline::record_extern_fqn(cx, did, ItemType::Trait);
+ PolyTrait { trait_: path, generic_params: Vec::new() }
+ })
+ .collect::<Vec<_>>();
- let mut bindings = vec![];
- for pb in obj.projection_bounds() {
- bindings.push(TypeBinding {
+ let bindings = obj
+ .projection_bounds()
+ .map(|pb| TypeBinding {
assoc: projection_to_path_segment(
pb.skip_binder()
.lift_to_tcx(cx.tcx)
kind: TypeBindingKind::Equality {
term: clean_middle_term(pb.skip_binder().term, cx),
},
- });
- }
+ })
+ .collect();
let path = external_path(cx, did, false, bindings, substs);
bounds.insert(0, PolyTrait { trait_: path, generic_params: Vec::new() });
let trait_ref = match bound_predicate.skip_binder() {
ty::PredicateKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
- if let Some(r) = reg.clean(cx) {
+ if let Some(r) = clean_middle_region(reg) {
regions.push(GenericBound::Outlives(r));
}
return None;
.iter()
.map(|arg| match arg {
hir::GenericArg::Lifetime(lt) if !lt.is_elided() => {
- GenericArg::Lifetime(lt.clean(cx))
+ GenericArg::Lifetime(clean_lifetime(*lt, cx))
}
hir::GenericArg::Lifetime(_) => GenericArg::Lifetime(Lifetime::elided()),
hir::GenericArg::Type(ty) => GenericArg::Type(clean_ty(ty, cx)),
) -> Vec<Item> {
let tcx = cx.tcx;
let mut ret = Vec::new();
- let trait_ = impl_.of_trait.as_ref().map(|t| t.clean(cx));
+ let trait_ = impl_.of_trait.as_ref().map(|t| clean_trait_ref(t, cx));
let items =
impl_.items.iter().map(|ii| tcx.hir().impl_item(ii.id).clean(cx)).collect::<Vec<_>>();
let def_id = tcx.hir().local_def_id(hir_id);
// FIXME: using `from_def_id_and_kind` breaks `rustdoc/masked` for some reason
vec![Item {
name: Some(name),
- attrs: Box::new(attrs.clean(cx)),
+ attrs: Box::new(Attributes::from_ast(attrs)),
item_id: crate_def_id.into(),
visibility: clean_visibility(ty_vis),
kind: Box::new(ExternCrateItem { src: orig_name }),