Rollup merge of #103408 - compiler-errors:rpitit-rustdoc, r=GuillaumeGomez
Clean return-position `impl Trait` in traits correctly in rustdoc Fixes #103403
This commit is contained in:
commit
571771e54a
@ -415,6 +415,16 @@ fn clean_projection<'tcx>(
|
||||
cx: &mut DocContext<'tcx>,
|
||||
def_id: Option<DefId>,
|
||||
) -> Type {
|
||||
if cx.tcx.def_kind(ty.item_def_id) == DefKind::ImplTraitPlaceholder {
|
||||
let bounds = cx
|
||||
.tcx
|
||||
.explicit_item_bounds(ty.item_def_id)
|
||||
.iter()
|
||||
.map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, ty.substs))
|
||||
.collect::<Vec<_>>();
|
||||
return clean_middle_opaque_bounds(cx, bounds);
|
||||
}
|
||||
|
||||
let trait_ = clean_trait_ref_with_bindings(cx, ty.trait_ref(cx.tcx), ThinVec::new());
|
||||
let self_type = clean_middle_ty(ty.self_ty(), cx, None);
|
||||
let self_def_id = if let Some(def_id) = def_id {
|
||||
@ -1720,59 +1730,7 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
||||
.iter()
|
||||
.map(|(bound, _)| EarlyBinder(*bound).subst(cx.tcx, substs))
|
||||
.collect::<Vec<_>>();
|
||||
let mut regions = vec![];
|
||||
let mut has_sized = false;
|
||||
let mut bounds = bounds
|
||||
.iter()
|
||||
.filter_map(|bound| {
|
||||
let bound_predicate = bound.kind();
|
||||
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) = clean_middle_region(reg) {
|
||||
regions.push(GenericBound::Outlives(r));
|
||||
}
|
||||
return None;
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
if let Some(sized) = cx.tcx.lang_items().sized_trait() {
|
||||
if trait_ref.def_id() == sized {
|
||||
has_sized = true;
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let bindings: ThinVec<_> = bounds
|
||||
.iter()
|
||||
.filter_map(|bound| {
|
||||
if let ty::PredicateKind::Projection(proj) = bound.kind().skip_binder()
|
||||
{
|
||||
if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
|
||||
Some(TypeBinding {
|
||||
assoc: projection_to_path_segment(proj.projection_ty, cx),
|
||||
kind: TypeBindingKind::Equality {
|
||||
term: clean_middle_term(proj.term, cx),
|
||||
},
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
bounds.extend(regions);
|
||||
if !has_sized && !bounds.is_empty() {
|
||||
bounds.insert(0, GenericBound::maybe_sized(cx));
|
||||
}
|
||||
ImplTrait(bounds)
|
||||
clean_middle_opaque_bounds(cx, bounds)
|
||||
}
|
||||
|
||||
ty::Closure(..) => panic!("Closure"),
|
||||
@ -1785,6 +1743,64 @@ pub(crate) fn clean_middle_ty<'tcx>(
|
||||
}
|
||||
}
|
||||
|
||||
fn clean_middle_opaque_bounds<'tcx>(
|
||||
cx: &mut DocContext<'tcx>,
|
||||
bounds: Vec<ty::Predicate<'tcx>>,
|
||||
) -> Type {
|
||||
let mut regions = vec![];
|
||||
let mut has_sized = false;
|
||||
let mut bounds = bounds
|
||||
.iter()
|
||||
.filter_map(|bound| {
|
||||
let bound_predicate = bound.kind();
|
||||
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) = clean_middle_region(reg) {
|
||||
regions.push(GenericBound::Outlives(r));
|
||||
}
|
||||
return None;
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
if let Some(sized) = cx.tcx.lang_items().sized_trait() {
|
||||
if trait_ref.def_id() == sized {
|
||||
has_sized = true;
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
let bindings: ThinVec<_> = bounds
|
||||
.iter()
|
||||
.filter_map(|bound| {
|
||||
if let ty::PredicateKind::Projection(proj) = bound.kind().skip_binder() {
|
||||
if proj.projection_ty.trait_ref(cx.tcx) == trait_ref.skip_binder() {
|
||||
Some(TypeBinding {
|
||||
assoc: projection_to_path_segment(proj.projection_ty, cx),
|
||||
kind: TypeBindingKind::Equality {
|
||||
term: clean_middle_term(proj.term, cx),
|
||||
},
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
Some(clean_poly_trait_ref_with_bindings(cx, trait_ref, bindings))
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
bounds.extend(regions);
|
||||
if !has_sized && !bounds.is_empty() {
|
||||
bounds.insert(0, GenericBound::maybe_sized(cx));
|
||||
}
|
||||
ImplTrait(bounds)
|
||||
}
|
||||
|
||||
pub(crate) fn clean_field<'tcx>(field: &hir::FieldDef<'tcx>, cx: &mut DocContext<'tcx>) -> Item {
|
||||
let def_id = cx.tcx.hir().local_def_id(field.hir_id).to_def_id();
|
||||
clean_field_with_def_id(def_id, field.ident.name, clean_ty(field.ty, cx), cx)
|
||||
|
16
src/test/rustdoc/async-trait.rs
Normal file
16
src/test/rustdoc/async-trait.rs
Normal file
@ -0,0 +1,16 @@
|
||||
// aux-build:async-trait-dep.rs
|
||||
// edition:2021
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
extern crate async_trait_dep;
|
||||
|
||||
pub struct Oink {}
|
||||
|
||||
// @has 'async_trait/struct.Oink.html' '//h4[@class="code-header"]' "async fn woof()"
|
||||
impl async_trait_dep::Meow for Oink {
|
||||
async fn woof() {
|
||||
todo!()
|
||||
}
|
||||
}
|
9
src/test/rustdoc/auxiliary/async-trait-dep.rs
Normal file
9
src/test/rustdoc/auxiliary/async-trait-dep.rs
Normal file
@ -0,0 +1,9 @@
|
||||
// edition:2021
|
||||
|
||||
#![feature(async_fn_in_trait)]
|
||||
#![allow(incomplete_features)]
|
||||
|
||||
pub trait Meow {
|
||||
/// Who's a good dog?
|
||||
async fn woof();
|
||||
}
|
Loading…
Reference in New Issue
Block a user