Skip to content

Commit 571771e

Browse files
authored
Rollup merge of rust-lang#103408 - compiler-errors:rpitit-rustdoc, r=GuillaumeGomez
Clean return-position `impl Trait` in traits correctly in rustdoc Fixes rust-lang#103403
2 parents c75e6f5 + def755e commit 571771e

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 {
@@ -1720,59 +1730,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
17201730
.iter()
17211731
.map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, substs))
17221732
.collect::<Vec<_>>();
1723-
let mut regions = vec![];
1724-
let mut has_sized = false;
1725-
let mut bounds = bounds
1726-
.iter()
1727-
.filter_map(|bound| {
1728-
let bound_predicate = bound.kind();
1729-
let trait_ref = match bound_predicate.skip_binder() {
1730-
ty::PredicateKind::Trait(tr) => bound_predicate.rebind(tr.trait_ref),
1731-
ty::PredicateKind::TypeOutlives(ty::OutlivesPredicate(_ty, reg)) => {
1732-
if let Some(r) = clean_middle_region(reg) {
1733-
regions.push(GenericBound::Outlives(r));
1734-
}
1735-
return None;
1736-
}
1737-
_ => return None,
1738-
};
1739-
1740-
if let Some(sized) = cx.tcx.lang_items().sized_trait() {
1741-
if trait_ref.def_id() == sized {
1742-
has_sized = true;
1743-
return None;
1744-
}
1745-
}
1746-
1747-
let bindings: ThinVec<_> = bounds
1748-
.iter()
1749-
.filter_map(|bound| {
1750-
if let ty::PredicateKind::Projection(proj) = bound.kind().skip_binder()
1751-
{
1752-
if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
1753-
Some(TypeBinding {
1754-
assoc: projection_to_path_segment(proj.projection_ty, cx),
1755-
kind: TypeBindingKind::Equality {
1756-
term: clean_middle_term(proj.term, cx),
1757-
},
1758-
})
1759-
} else {
1760-
None
1761-
}
1762-
} else {
1763-
None
1764-
}
1765-
})
1766-
.collect();
1767-
1768-
Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings))
1769-
})
1770-
.collect::<Vec<_>>();
1771-
bounds.extend(regions);
1772-
if !has_sized && !bounds.is_empty() {
1773-
bounds.insert(0, GenericBound::maybe_sized(cx));
1774-
}
1775-
ImplTrait(bounds)
1733+
clean_middle_opaque_bounds(cx, bounds)
17761734
}
17771735

17781736
ty::Closure(..) => panic!("Closure"),
@@ -1785,6 +1743,64 @@ pub(crate) fn clean_middle_ty<'tcx>(
17851743
}
17861744
}
17871745

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