Skip to content

Commit def755e

Browse files
Clean middle RPITITs correctly in rustdoc
1 parent 289b2b8 commit def755e

File tree

3 files changed

+94
-53
lines changed

3 files changed

+94
-53
lines changed

src/librustdoc/clean/mod.rs

+69-53
Original file line numberDiff line numberDiff line change
@@ -415,6 +415,16 @@ fn clean_projection<'tcx>(
415415
cx: &mut DocContext<'tcx>,
416416
def_id: Option<DefId>,
417417
) -> Type {
418+
if cx.tcx.def_kind(ty.item_def_id) == DefKind::ImplTraitPlaceholder {
419+
let bounds = cx
420+
.tcx
421+
.explicit_item_bounds(ty.item_def_id)
422+
.iter()
423+
.map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.substs))
424+
.collect::<Vec<_>>();
425+
return clean_middle_opaque_bounds(cx, bounds);
426+
}
427+
418428
let trait_ = clean_trait_ref_with_bindings(cx, ty.trait_ref(cx.tcx), ThinVec::new());
419429
let self_type = clean_middle_ty(ty.self_ty(), cx, None);
420430
let self_def_id = if let Some(def_id) = def_id {
@@ -1715,59 +1725,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
17151725
.iter()
17161726
.map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, substs))
17171727
.collect::<Vec<_>>();
1718-
let mut regions = vec![];
1719-
let mut has_sized = false;
1720-
let mut bounds = bounds
1721-
.iter()
1722-
.filter_map(|bound| {
1723-
let bound_predicate = bound.kind();
1724-
let trait_ref = match bound_predicate.skip_binder() {
1725-
ty::PredicateKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
1726-
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
1727-
if let Some(r) = clean_middle_region(reg) {
1728-
regions.push(GenericBound::Outlives(r));
1729-
}
1730-
return None;
1731-
}
1732-
_ => return None,
1733-
};
1734-
1735-
if let Some(sized) = cx.tcx.lang_items().sized_trait() {
1736-
if trait_ref.def_id() == sized {
1737-
has_sized = true;
1738-
return None;
1739-
}
1740-
}
1741-
1742-
let bindings: ThinVec<_> = bounds
1743-
.iter()
1744-
.filter_map(|bound| {
1745-
if let ty::PredicateKind::Projection(proj) = bound.kind().skip_binder()
1746-
{
1747-
if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
1748-
Some(TypeBinding {
1749-
assoc: projection_to_path_segment(proj.projection_ty, cx),
1750-
kind: TypeBindingKind::Equality {
1751-
term: clean_middle_term(proj.term, cx),
1752-
},
1753-
})
1754-
} else {
1755-
None
1756-
}
1757-
} else {
1758-
None
1759-
}
1760-
})
1761-
.collect();
1762-
1763-
Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings))
1764-
})
1765-
.collect::<Vec<_>>();
1766-
bounds.extend(regions);
1767-
if !has_sized && !bounds.is_empty() {
1768-
bounds.insert(0, GenericBound::maybe_sized(cx));
1769-
}
1770-
ImplTrait(bounds)
1728+
clean_middle_opaque_bounds(cx, bounds)
17711729
}
17721730

17731731
ty::Closure(..) => panic!("Closure"),
@@ -1780,6 +1738,64 @@ pub(crate) fn clean_middle_ty<'tcx>(
17801738
}
17811739
}
17821740

1741+
fn clean_middle_opaque_bounds<'tcx>(
1742+
cx: &mut DocContext<'tcx>,
1743+
bounds: Vec<ty::Predicate<'tcx>>,
1744+
) -> Type {
1745+
let mut regions = vec![];
1746+
let mut has_sized = false;
1747+
let mut bounds = bounds
1748+
.iter()
1749+
.filter_map(|bound| {
1750+
let bound_predicate = bound.kind();
1751+
let trait_ref = match bound_predicate.skip_binder() {
1752+
ty::PredicateKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
1753+
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
1754+
if let Some(r) = clean_middle_region(reg) {
1755+
regions.push(GenericBound::Outlives(r));
1756+
}
1757+
return None;
1758+
}
1759+
_ => return None,
1760+
};
1761+
1762+
if let Some(sized) = cx.tcx.lang_items().sized_trait() {
1763+
if trait_ref.def_id() == sized {
1764+
has_sized = true;
1765+
return None;
1766+
}
1767+
}
1768+
1769+
let bindings: ThinVec<_> = bounds
1770+
.iter()
1771+
.filter_map(|bound| {
1772+
if let ty::PredicateKind::Projection(proj) = bound.kind().skip_binder() {
1773+
if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
1774+
Some(TypeBinding {
1775+
assoc: projection_to_path_segment(proj.projection_ty, cx),
1776+
kind: TypeBindingKind::Equality {
1777+
term: clean_middle_term(proj.term, cx),
1778+
},
1779+
})
1780+
} else {
1781+
None
1782+
}
1783+
} else {
1784+
None
1785+
}
1786+
})
1787+
.collect();
1788+
1789+
Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings))
1790+
})
1791+
.collect::<Vec<_>>();
1792+
bounds.extend(regions);
1793+
if !has_sized && !bounds.is_empty() {
1794+
bounds.insert(0, GenericBound::maybe_sized(cx));
1795+
}
1796+
ImplTrait(bounds)
1797+
}
1798+
17831799
pub(crate) fn clean_field<'tcx>(field: &hir::FieldDef<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
17841800
let def_id = cx.tcx.hir().local_def_id(field.hir_id).to_def_id();
17851801
clean_field_with_def_id(def_id, field.ident.name, clean_ty(field.ty, cx), cx)

src/test/rustdoc/async-trait.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// aux-build:async-trait-dep.rs
2+
// edition:2021
3+
4+
#![feature(async_fn_in_trait)]
5+
#![allow(incomplete_features)]
6+
7+
extern crate async_trait_dep;
8+
9+
pub struct Oink {}
10+
11+
// @has 'async_trait/struct.Oink.html' '//h4[@class="code-header"]' "async fn woof()"
12+
impl async_trait_dep::Meow for Oink {
13+
async fn woof() {
14+
todo!()
15+
}
16+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// edition:2021
2+
3+
#![feature(async_fn_in_trait)]
4+
#![allow(incomplete_features)]
5+
6+
pub trait Meow {
7+
/// Who's a good dog?
8+
async fn woof();
9+
}

0 commit comments

Comments
 (0)