Skip to content

Commit 67de150

Browse files
committed
rustdoc: fix & clean up handling of cross-crate higher-ranked lifetimes
1 parent 085acd0 commit 67de150

File tree

11 files changed

+68
-105
lines changed

11 files changed

+68
-105
lines changed

src/librustdoc/clean/auto_trait.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -551,8 +551,8 @@ where
551551
WherePredicate::RegionPredicate { lifetime, bounds } => {
552552
lifetime_to_bounds.entry(lifetime).or_default().extend(bounds);
553553
}
554-
WherePredicate::EqPredicate { lhs, rhs, bound_params } => {
555-
match *lhs {
554+
WherePredicate::EqPredicate { lhs, rhs } => {
555+
match lhs {
556556
Type::QPath(box QPathData {
557557
ref assoc,
558558
ref self_type,
@@ -590,14 +590,13 @@ where
590590
GenericArgs::AngleBracketed { ref mut bindings, .. } => {
591591
bindings.push(TypeBinding {
592592
assoc: assoc.clone(),
593-
kind: TypeBindingKind::Equality { term: *rhs },
593+
kind: TypeBindingKind::Equality { term: rhs },
594594
});
595595
}
596596
GenericArgs::Parenthesized { .. } => {
597597
existing_predicates.push(WherePredicate::EqPredicate {
598598
lhs: lhs.clone(),
599599
rhs,
600-
bound_params,
601600
});
602601
continue; // If something other than a Fn ends up
603602
// with parentheses, leave it alone

src/librustdoc/clean/inline.rs

+5-12
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ use rustc_span::hygiene::MacroKind;
1818
use rustc_span::symbol::{kw, sym, Symbol};
1919

2020
use crate::clean::{
21-
self, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item, clean_middle_assoc_item,
22-
clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings, clean_ty,
23-
clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes,
21+
self, clean_bound_vars, clean_fn_decl_from_did_and_sig, clean_generics, clean_impl_item,
22+
clean_middle_assoc_item, clean_middle_field, clean_middle_ty, clean_trait_ref_with_bindings,
23+
clean_ty, clean_ty_alias_inner_type, clean_ty_generics, clean_variant_def, utils, Attributes,
2424
AttributesExt, ImplKind, ItemId, Type,
2525
};
2626
use crate::core::DocContext;
@@ -239,20 +239,13 @@ pub(crate) fn build_external_trait(cx: &mut DocContext<'_>, did: DefId) -> clean
239239

240240
fn build_external_function<'tcx>(cx: &mut DocContext<'tcx>, did: DefId) -> Box<clean::Function> {
241241
let sig = cx.tcx.fn_sig(did).instantiate_identity();
242-
243-
let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var {
244-
ty::BoundVariableKind::Region(ty::BrNamed(_, name)) if name != kw::UnderscoreLifetime => {
245-
Some(clean::GenericParamDef::lifetime(name))
246-
}
247-
_ => None,
248-
});
249-
250242
let predicates = cx.tcx.explicit_predicates_of(did);
243+
251244
let (generics, decl) = clean::enter_impl_trait(cx, |cx| {
252245
// NOTE: generics need to be cleaned before the decl!
253246
let mut generics = clean_ty_generics(cx, cx.tcx.generics_of(did), predicates);
254247
// FIXME: This does not place parameters in source order (late-bound ones come last)
255-
generics.params.extend(late_bound_regions);
248+
generics.params.extend(clean_bound_vars(sig.bound_vars()));
256249
let decl = clean_fn_decl_from_did_and_sig(cx, Some(did), sig);
257250
(generics, decl)
258251
});

src/librustdoc/clean/mod.rs

+37-57
Original file line numberDiff line numberDiff line change
@@ -232,20 +232,11 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
232232
poly_trait_ref: ty::PolyTraitRef<'tcx>,
233233
bindings: ThinVec<TypeBinding>,
234234
) -> GenericBound {
235-
// collect any late bound regions
236-
let late_bound_regions: Vec<_> = cx
237-
.tcx
238-
.collect_referenced_late_bound_regions(&poly_trait_ref)
239-
.into_iter()
240-
.filter_map(|br| match br {
241-
ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)),
242-
_ => None,
243-
})
244-
.collect();
245-
246-
let trait_ = clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings);
247235
GenericBound::TraitBound(
248-
PolyTrait { trait_, generic_params: late_bound_regions },
236+
PolyTrait {
237+
trait_: clean_trait_ref_with_bindings(cx, poly_trait_ref, bindings),
238+
generic_params: clean_bound_vars(poly_trait_ref.bound_vars()),
239+
},
249240
hir::TraitBoundModifier::None,
250241
)
251242
}
@@ -338,9 +329,8 @@ fn clean_where_predicate<'tcx>(
338329
},
339330

340331
hir::WherePredicate::EqPredicate(ref wrp) => WherePredicate::EqPredicate {
341-
lhs: Box::new(clean_ty(wrp.lhs_ty, cx)),
342-
rhs: Box::new(clean_ty(wrp.rhs_ty, cx).into()),
343-
bound_params: Vec::new(),
332+
lhs: clean_ty(wrp.lhs_ty, cx),
333+
rhs: clean_ty(wrp.rhs_ty, cx).into(),
344334
},
345335
})
346336
}
@@ -436,20 +426,9 @@ fn clean_projection_predicate<'tcx>(
436426
pred: ty::Binder<'tcx, ty::ProjectionPredicate<'tcx>>,
437427
cx: &mut DocContext<'tcx>,
438428
) -> WherePredicate {
439-
let late_bound_regions = cx
440-
.tcx
441-
.collect_referenced_late_bound_regions(&pred)
442-
.into_iter()
443-
.filter_map(|br| match br {
444-
ty::BrNamed(_, name) if br.is_named() => Some(GenericParamDef::lifetime(name)),
445-
_ => None,
446-
})
447-
.collect();
448-
449429
WherePredicate::EqPredicate {
450-
lhs: Box::new(clean_projection(pred.map_bound(|p| p.projection_ty), cx, None)),
451-
rhs: Box::new(clean_middle_term(pred.map_bound(|p| p.term), cx)),
452-
bound_params: late_bound_regions,
430+
lhs: clean_projection(pred.map_bound(|p| p.projection_ty), cx, None),
431+
rhs: clean_middle_term(pred.map_bound(|p| p.term), cx),
453432
}
454433
}
455434

@@ -703,8 +682,8 @@ pub(crate) fn clean_generics<'tcx>(
703682
}
704683
}
705684
}
706-
WherePredicate::EqPredicate { lhs, rhs, bound_params } => {
707-
eq_predicates.push(WherePredicate::EqPredicate { lhs, rhs, bound_params });
685+
WherePredicate::EqPredicate { lhs, rhs } => {
686+
eq_predicates.push(WherePredicate::EqPredicate { lhs, rhs });
708687
}
709688
}
710689
}
@@ -798,11 +777,9 @@ fn clean_ty_generics<'tcx>(
798777
})
799778
.collect::<ThinVec<GenericParamDef>>();
800779

801-
// param index -> [(trait DefId, associated type name & generics, term, higher-ranked params)]
802-
let mut impl_trait_proj = FxHashMap::<
803-
u32,
804-
Vec<(DefId, PathSegment, ty::Binder<'_, ty::Term<'_>>, Vec<GenericParamDef>)>,
805-
>::default();
780+
// param index -> [(trait DefId, associated type name & generics, term)]
781+
let mut impl_trait_proj =
782+
FxHashMap::<u32, Vec<(DefId, PathSegment, ty::Binder<'_, ty::Term<'_>>)>>::default();
806783

807784
let where_predicates = preds
808785
.predicates
@@ -854,11 +831,6 @@ fn clean_ty_generics<'tcx>(
854831
trait_did,
855832
name,
856833
proj.map_bound(|p| p.term),
857-
pred.get_bound_params()
858-
.into_iter()
859-
.flatten()
860-
.cloned()
861-
.collect(),
862834
));
863835
}
864836

@@ -894,9 +866,9 @@ fn clean_ty_generics<'tcx>(
894866

895867
let crate::core::ImplTraitParam::ParamIndex(idx) = param else { unreachable!() };
896868
if let Some(proj) = impl_trait_proj.remove(&idx) {
897-
for (trait_did, name, rhs, bound_params) in proj {
869+
for (trait_did, name, rhs) in proj {
898870
let rhs = clean_middle_term(rhs, cx);
899-
simplify::merge_bounds(cx, &mut bounds, bound_params, trait_did, name, &rhs);
871+
simplify::merge_bounds(cx, &mut bounds, trait_did, name, &rhs);
900872
}
901873
}
902874

@@ -1357,23 +1329,13 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
13571329
}
13581330
ty::AssocKind::Fn => {
13591331
let sig = tcx.fn_sig(assoc_item.def_id).instantiate_identity();
1360-
1361-
let late_bound_regions = sig.bound_vars().into_iter().filter_map(|var| match var {
1362-
ty::BoundVariableKind::Region(ty::BrNamed(_, name))
1363-
if name != kw::UnderscoreLifetime =>
1364-
{
1365-
Some(GenericParamDef::lifetime(name))
1366-
}
1367-
_ => None,
1368-
});
1369-
13701332
let mut generics = clean_ty_generics(
13711333
cx,
13721334
tcx.generics_of(assoc_item.def_id),
13731335
tcx.explicit_predicates_of(assoc_item.def_id),
13741336
);
13751337
// FIXME: This does not place parameters in source order (late-bound ones come last)
1376-
generics.params.extend(late_bound_regions);
1338+
generics.params.extend(clean_bound_vars(sig.bound_vars()));
13771339

13781340
let mut decl = clean_fn_decl_from_did_and_sig(cx, Some(assoc_item.def_id), sig);
13791341

@@ -2109,9 +2071,11 @@ pub(crate) fn clean_middle_ty<'tcx>(
21092071
// FIXME: should we merge the outer and inner binders somehow?
21102072
let sig = bound_ty.skip_binder().fn_sig(cx.tcx);
21112073
let decl = clean_fn_decl_from_did_and_sig(cx, None, sig);
2074+
let generic_params = clean_bound_vars(sig.bound_vars());
2075+
21122076
BareFunction(Box::new(BareFunctionDecl {
21132077
unsafety: sig.unsafety(),
2114-
generic_params: Vec::new(),
2078+
generic_params,
21152079
decl,
21162080
abi: sig.abi(),
21172081
}))
@@ -2187,8 +2151,8 @@ pub(crate) fn clean_middle_ty<'tcx>(
21872151

21882152
let late_bound_regions: FxIndexSet<_> = obj
21892153
.iter()
2190-
.flat_map(|pb| pb.bound_vars())
2191-
.filter_map(|br| match br {
2154+
.flat_map(|pred| pred.bound_vars())
2155+
.filter_map(|var| match var {
21922156
ty::BoundVariableKind::Region(ty::BrNamed(_, name))
21932157
if name != kw::UnderscoreLifetime =>
21942158
{
@@ -3121,3 +3085,19 @@ fn clean_type_binding<'tcx>(
31213085
},
31223086
}
31233087
}
3088+
3089+
fn clean_bound_vars<'tcx>(
3090+
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
3091+
) -> Vec<GenericParamDef> {
3092+
bound_vars
3093+
.into_iter()
3094+
.filter_map(|var| match var {
3095+
ty::BoundVariableKind::Region(ty::BrNamed(_, name))
3096+
if name != kw::UnderscoreLifetime =>
3097+
{
3098+
Some(GenericParamDef::lifetime(name))
3099+
}
3100+
_ => None,
3101+
})
3102+
.collect()
3103+
}

src/librustdoc/clean/simplify.rs

+4-15
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,18 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> ThinVec<WP
4040
WP::RegionPredicate { lifetime, bounds } => {
4141
lifetimes.push((lifetime, bounds));
4242
}
43-
WP::EqPredicate { lhs, rhs, bound_params } => equalities.push((lhs, rhs, bound_params)),
43+
WP::EqPredicate { lhs, rhs } => equalities.push((lhs, rhs)),
4444
}
4545
}
4646

4747
// Look for equality predicates on associated types that can be merged into
4848
// general bound predicates.
49-
equalities.retain(|(lhs, rhs, bound_params)| {
49+
equalities.retain(|(lhs, rhs)| {
5050
let Some((ty, trait_did, name)) = lhs.projection() else {
5151
return true;
5252
};
5353
let Some((bounds, _)) = tybounds.get_mut(ty) else { return true };
54-
merge_bounds(cx, bounds, bound_params.clone(), trait_did, name, rhs)
54+
merge_bounds(cx, bounds, trait_did, name, rhs)
5555
});
5656

5757
// And finally, let's reassemble everything
@@ -64,18 +64,13 @@ pub(crate) fn where_clauses(cx: &DocContext<'_>, clauses: Vec<WP>) -> ThinVec<WP
6464
bounds,
6565
bound_params,
6666
}));
67-
clauses.extend(equalities.into_iter().map(|(lhs, rhs, bound_params)| WP::EqPredicate {
68-
lhs,
69-
rhs,
70-
bound_params,
71-
}));
67+
clauses.extend(equalities.into_iter().map(|(lhs, rhs)| WP::EqPredicate { lhs, rhs }));
7268
clauses
7369
}
7470

7571
pub(crate) fn merge_bounds(
7672
cx: &clean::DocContext<'_>,
7773
bounds: &mut Vec<clean::GenericBound>,
78-
mut bound_params: Vec<clean::GenericParamDef>,
7974
trait_did: DefId,
8075
assoc: clean::PathSegment,
8176
rhs: &clean::Term,
@@ -93,12 +88,6 @@ pub(crate) fn merge_bounds(
9388
}
9489
let last = trait_ref.trait_.segments.last_mut().expect("segments were empty");
9590

96-
trait_ref.generic_params.append(&mut bound_params);
97-
// Sort parameters (likely) originating from a hashset alphabetically to
98-
// produce predictable output (and to allow for full deduplication).
99-
trait_ref.generic_params.sort_unstable_by(|p, q| p.name.as_str().cmp(q.name.as_str()));
100-
trait_ref.generic_params.dedup_by_key(|p| p.name);
101-
10291
match last.args {
10392
PP::AngleBracketed { ref mut bindings, .. } => {
10493
bindings.push(clean::TypeBinding {

src/librustdoc/clean/types.rs

+1-10
Original file line numberDiff line numberDiff line change
@@ -1289,7 +1289,7 @@ impl Lifetime {
12891289
pub(crate) enum WherePredicate {
12901290
BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
12911291
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
1292-
EqPredicate { lhs: Box<Type>, rhs: Box<Term>, bound_params: Vec<GenericParamDef> },
1292+
EqPredicate { lhs: Type, rhs: Term },
12931293
}
12941294

12951295
impl WherePredicate {
@@ -1300,15 +1300,6 @@ impl WherePredicate {
13001300
_ => None,
13011301
}
13021302
}
1303-
1304-
pub(crate) fn get_bound_params(&self) -> Option<&[GenericParamDef]> {
1305-
match self {
1306-
Self::BoundPredicate { bound_params, .. } | Self::EqPredicate { bound_params, .. } => {
1307-
Some(bound_params)
1308-
}
1309-
_ => None,
1310-
}
1311-
}
13121303
}
13131304

13141305
#[derive(Clone, PartialEq, Eq, Debug, Hash)]

src/librustdoc/html/format.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -326,8 +326,7 @@ pub(crate) fn print_where_clause<'a, 'tcx: 'a>(
326326
bounds_display.truncate(bounds_display.len() - " + ".len());
327327
write!(f, "{}: {bounds_display}", lifetime.print())
328328
}
329-
// FIXME(fmease): Render bound params.
330-
clean::WherePredicate::EqPredicate { lhs, rhs, bound_params: _ } => {
329+
clean::WherePredicate::EqPredicate { lhs, rhs } => {
331330
if f.alternate() {
332331
write!(f, "{:#} == {:#}", lhs.print(cx), rhs.print(cx))
333332
} else {

src/librustdoc/json/conversions.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -506,9 +506,8 @@ impl FromWithTcx<clean::WherePredicate> for WherePredicate {
506506
lifetime: convert_lifetime(lifetime),
507507
bounds: bounds.into_tcx(tcx),
508508
},
509-
// FIXME(fmease): Convert bound parameters as well.
510-
EqPredicate { lhs, rhs, bound_params: _ } => {
511-
WherePredicate::EqPredicate { lhs: (*lhs).into_tcx(tcx), rhs: (*rhs).into_tcx(tcx) }
509+
EqPredicate { lhs, rhs } => {
510+
WherePredicate::EqPredicate { lhs: lhs.into_tcx(tcx), rhs: rhs.into_tcx(tcx) }
512511
}
513512
}
514513
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
pub type F = for<'z, 'a, '_unused> fn(&'z for<'b> fn(&'b str), &'a ()) -> &'a ();

tests/rustdoc/inline_cross/auxiliary/impl_trait_aux.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub fn func4<T: Iterator<Item = impl Clone>>(_x: T) {}
1515

1616
pub fn func5(
1717
_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,
18-
_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>,
18+
_a: impl for<'beta, 'alpha, '_gamma> Auxiliary<'alpha, Item<'beta> = fn(&'beta ())>,
1919
) {}
2020

2121
pub trait Other {

tests/rustdoc/inline_cross/fn-type.rs

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Make sure that we print the higher-ranked parameters of cross-crate function pointer types.
2+
// They should be rendered exactly as the user wrote it, i.e., in source order and with unused
3+
// parameters present, not stripped.
4+
5+
// aux-crate:fn_type=fn-type.rs
6+
// edition: 2021
7+
#![crate_name = "user"]
8+
9+
// @has user/type.F.html
10+
// @has - '//*[@class="rust item-decl"]//code' \
11+
// "for<'z, 'a, '_unused> fn(_: &'z for<'b> fn(_: &'b str), _: &'a ()) -> &'a ();"
12+
pub use fn_type::F;

tests/rustdoc/inline_cross/impl_trait.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub use impl_trait_aux::func4;
2929
// @has impl_trait/fn.func5.html
3030
// @has - '//pre[@class="rust item-decl"]' "func5("
3131
// @has - '//pre[@class="rust item-decl"]' "_f: impl for<'any> Fn(&'any str, &'any str) -> bool + for<'r> Other<T<'r> = ()>,"
32-
// @has - '//pre[@class="rust item-decl"]' "_a: impl for<'alpha, 'beta> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
32+
// @has - '//pre[@class="rust item-decl"]' "_a: impl for<'beta, 'alpha, '_gamma> Auxiliary<'alpha, Item<'beta> = fn(_: &'beta ())>"
3333
// @!has - '//pre[@class="rust item-decl"]' 'where'
3434
pub use impl_trait_aux::func5;
3535

0 commit comments

Comments
 (0)