Skip to content

Commit 70c520e

Browse files
committed
Print all generic parameter bounds as where predicates in rustdoc.
1 parent 21e9336 commit 70c520e

File tree

7 files changed

+70
-224
lines changed

7 files changed

+70
-224
lines changed

src/librustdoc/clean/auto_trait.rs

+10-10
Original file line numberDiff line numberDiff line change
@@ -332,10 +332,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
332332
match br {
333333
// We only care about named late bound regions, as we need to add them
334334
// to the 'for<>' section
335-
ty::BrNamed(_, name) => Some(GenericParamDef {
336-
name,
337-
kind: GenericParamDefKind::Lifetime { outlives: vec![] },
338-
}),
335+
ty::BrNamed(_, name) => {
336+
Some(GenericParamDef { name, kind: GenericParamDefKind::Lifetime })
337+
}
339338
_ => None,
340339
}
341340
})
@@ -610,18 +609,15 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
610609
};
611610
}
612611

613-
let final_bounds = self.make_final_bounds(ty_to_bounds, ty_to_fn, lifetime_to_bounds);
614-
615-
existing_predicates.extend(final_bounds);
616-
617612
for param in generic_params.iter_mut() {
618613
match param.kind {
619-
GenericParamDefKind::Type { ref mut default, ref mut bounds, .. } => {
614+
GenericParamDefKind::Type { ref mut default, .. } => {
620615
// We never want something like `impl<T=Foo>`.
621616
default.take();
622617
let generic_ty = Type::Generic(param.name);
623618
if !has_sized.contains(&generic_ty) {
624-
bounds.insert(0, GenericBound::maybe_sized(self.cx));
619+
let b = GenericBound::maybe_sized(self.cx);
620+
ty_to_bounds.entry(generic_ty).or_default().insert(b);
625621
}
626622
}
627623
GenericParamDefKind::Lifetime { .. } => {}
@@ -632,6 +628,10 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> {
632628
}
633629
}
634630

631+
let final_bounds = self.make_final_bounds(ty_to_bounds, ty_to_fn, lifetime_to_bounds);
632+
633+
existing_predicates.extend(final_bounds);
634+
635635
self.sort_where_predicates(&mut existing_predicates);
636636

637637
Generics { params: generic_params, where_predicates: existing_predicates }

src/librustdoc/clean/mod.rs

+48-138
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
1616
use rustc_hir as hir;
1717
use rustc_hir::def::{CtorKind, DefKind, Res};
1818
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
19-
use rustc_hir::PredicateOrigin;
2019
use rustc_infer::infer::region_constraints::{Constraint, RegionConstraintData};
2120
use rustc_middle::middle::resolve_lifetime as rl;
2221
use rustc_middle::ty::fold::TypeFolder;
@@ -33,7 +32,7 @@ use std::collections::hash_map::Entry;
3332
use std::collections::BTreeMap;
3433
use std::default::Default;
3534
use std::hash::Hash;
36-
use std::{mem, vec};
35+
use std::vec;
3736

3837
use crate::core::{self, DocContext, ImplTraitParam};
3938
use crate::formats::item_type::ItemType;
@@ -167,10 +166,9 @@ fn clean_poly_trait_ref_with_bindings<'tcx>(
167166
.collect_referenced_late_bound_regions(&poly_trait_ref)
168167
.into_iter()
169168
.filter_map(|br| match br {
170-
ty::BrNamed(_, name) => Some(GenericParamDef {
171-
name,
172-
kind: GenericParamDefKind::Lifetime { outlives: vec![] },
173-
}),
169+
ty::BrNamed(_, name) => {
170+
Some(GenericParamDef { name, kind: GenericParamDefKind::Lifetime })
171+
}
174172
_ => None,
175173
})
176174
.collect();
@@ -239,12 +237,9 @@ impl<'tcx> Clean<'tcx, Option<Lifetime>> for ty::Region<'tcx> {
239237
}
240238
}
241239

242-
impl<'tcx> Clean<'tcx, Option<WherePredicate>> for hir::WherePredicate<'tcx> {
243-
fn clean(&self, cx: &mut DocContext<'tcx>) -> Option<WherePredicate> {
244-
if !self.in_where_clause() {
245-
return None;
246-
}
247-
Some(match *self {
240+
impl<'tcx> Clean<'tcx, WherePredicate> for hir::WherePredicate<'tcx> {
241+
fn clean(&self, cx: &mut DocContext<'tcx>) -> WherePredicate {
242+
match *self {
248243
hir::WherePredicate::BoundPredicate(ref wbp) => {
249244
let bound_params = wbp
250245
.bound_generic_params
@@ -275,7 +270,7 @@ impl<'tcx> Clean<'tcx, Option<WherePredicate>> for hir::WherePredicate<'tcx> {
275270
lhs: wrp.lhs_ty.clean(cx),
276271
rhs: wrp.rhs_ty.clean(cx).into(),
277272
},
278-
})
273+
}
279274
}
280275
}
281276

@@ -434,9 +429,7 @@ fn projection_to_path_segment<'tcx>(
434429
impl<'tcx> Clean<'tcx, GenericParamDef> for ty::GenericParamDef {
435430
fn clean(&self, cx: &mut DocContext<'tcx>) -> GenericParamDef {
436431
let (name, kind) = match self.kind {
437-
ty::GenericParamDefKind::Lifetime => {
438-
(self.name, GenericParamDefKind::Lifetime { outlives: vec![] })
439-
}
432+
ty::GenericParamDefKind::Lifetime => (self.name, GenericParamDefKind::Lifetime),
440433
ty::GenericParamDefKind::Type { has_default, synthetic, .. } => {
441434
let default = if has_default {
442435
Some(clean_ty(cx.tcx.type_of(self.def_id), cx, Some(self.def_id)))
@@ -447,7 +440,6 @@ impl<'tcx> Clean<'tcx, GenericParamDef> for ty::GenericParamDef {
447440
self.name,
448441
GenericParamDefKind::Type {
449442
did: self.def_id,
450-
bounds: vec![], // These are filled in from the where-clauses.
451443
default: default.map(Box::new),
452444
synthetic,
453445
},
@@ -472,143 +464,61 @@ impl<'tcx> Clean<'tcx, GenericParamDef> for ty::GenericParamDef {
472464

473465
fn clean_generic_param<'tcx>(
474466
cx: &mut DocContext<'tcx>,
475-
generics: Option<&hir::Generics<'tcx>>,
476467
param: &hir::GenericParam<'tcx>,
477468
) -> GenericParamDef {
478469
let did = cx.tcx.hir().local_def_id(param.hir_id);
479-
let (name, kind) = match param.kind {
480-
hir::GenericParamKind::Lifetime { .. } => {
481-
let outlives = if let Some(generics) = generics {
482-
generics
483-
.outlives_for_param(did)
484-
.filter(|bp| !bp.in_where_clause)
485-
.flat_map(|bp| bp.bounds)
486-
.map(|bound| match bound {
487-
hir::GenericBound::Outlives(lt) => lt.clean(cx),
488-
_ => panic!(),
489-
})
490-
.collect()
491-
} else {
492-
Vec::new()
493-
};
494-
(param.name.ident().name, GenericParamDefKind::Lifetime { outlives })
495-
}
496-
hir::GenericParamKind::Type { ref default, synthetic } => {
497-
let bounds = if let Some(generics) = generics {
498-
generics
499-
.bounds_for_param(did)
500-
.filter(|bp| bp.origin != PredicateOrigin::WhereClause)
501-
.flat_map(|bp| bp.bounds)
502-
.filter_map(|x| x.clean(cx))
503-
.collect()
504-
} else {
505-
Vec::new()
506-
};
507-
(
508-
param.name.ident().name,
509-
GenericParamDefKind::Type {
510-
did: did.to_def_id(),
511-
bounds,
512-
default: default.map(|t| t.clean(cx)).map(Box::new),
513-
synthetic,
514-
},
515-
)
516-
}
517-
hir::GenericParamKind::Const { ty, default } => (
518-
param.name.ident().name,
519-
GenericParamDefKind::Const {
520-
did: did.to_def_id(),
521-
ty: Box::new(ty.clean(cx)),
522-
default: default.map(|ct| {
523-
let def_id = cx.tcx.hir().local_def_id(ct.hir_id);
524-
Box::new(ty::Const::from_anon_const(cx.tcx, def_id).to_string())
525-
}),
526-
},
527-
),
470+
let name = param.name.ident().name;
471+
let kind = match param.kind {
472+
hir::GenericParamKind::Lifetime { .. } => GenericParamDefKind::Lifetime,
473+
hir::GenericParamKind::Type { ref default, synthetic } => GenericParamDefKind::Type {
474+
did: cx.tcx.hir().local_def_id(param.hir_id).to_def_id(),
475+
default: default.map(|t| t.clean(cx)).map(Box::new),
476+
synthetic,
477+
},
478+
hir::GenericParamKind::Const { ty, default } => GenericParamDefKind::Const {
479+
did: did.to_def_id(),
480+
ty: Box::new(ty.clean(cx)),
481+
default: default.map(|ct| {
482+
let def_id = cx.tcx.hir().local_def_id(ct.hir_id);
483+
Box::new(ty::Const::from_anon_const(cx.tcx, def_id).to_string())
484+
}),
485+
},
528486
};
529487

530488
GenericParamDef { name, kind }
531489
}
532490

533491
impl<'tcx> Clean<'tcx, Generics> for hir::Generics<'tcx> {
534492
fn clean(&self, cx: &mut DocContext<'tcx>) -> Generics {
535-
// Synthetic type-parameters are inserted after normal ones.
536-
// In order for normal parameters to be able to refer to synthetic ones,
537-
// scans them first.
538-
fn is_impl_trait(param: &hir::GenericParam<'_>) -> bool {
539-
match param.kind {
540-
hir::GenericParamKind::Type { synthetic, .. } => synthetic,
541-
_ => false,
542-
}
543-
}
544-
/// This can happen for `async fn`, e.g. `async fn f<'_>(&'_ self)`.
545-
///
546-
/// See [`lifetime_to_generic_param`] in [`rustc_ast_lowering`] for more information.
547-
///
548-
/// [`lifetime_to_generic_param`]: rustc_ast_lowering::LoweringContext::lifetime_to_generic_param
549-
fn is_elided_lifetime(param: &hir::GenericParam<'_>) -> bool {
550-
matches!(
551-
param.kind,
552-
hir::GenericParamKind::Lifetime { kind: hir::LifetimeParamKind::Elided }
553-
)
554-
}
555-
556-
let impl_trait_params = self
557-
.params
558-
.iter()
559-
.filter(|param| is_impl_trait(param))
560-
.map(|param| {
561-
let param = clean_generic_param(cx, Some(self), param);
562-
match param.kind {
563-
GenericParamDefKind::Lifetime { .. } => unreachable!(),
564-
GenericParamDefKind::Type { did, ref bounds, .. } => {
565-
cx.impl_trait_bounds.insert(did.into(), bounds.clone());
493+
let mut impl_trait = FxHashSet::default();
494+
for (i, p) in self.predicates.iter().enumerate() {
495+
if let hir::WherePredicate::BoundPredicate(bp) = p {
496+
if let Some((def_id, ident)) = bp.bounded_ty.as_generic_param() {
497+
// Do not include predicates on `impl Trait` desugaring.
498+
if ident.as_str().starts_with("impl ") {
499+
let bounds = bp.bounds.iter().filter_map(|b| b.clean(cx)).collect();
500+
cx.impl_trait_bounds.insert(def_id.into(), bounds);
501+
impl_trait.insert(i);
566502
}
567-
GenericParamDefKind::Const { .. } => unreachable!(),
568503
}
569-
param
570-
})
571-
.collect::<Vec<_>>();
504+
}
505+
}
572506

573507
let mut params = Vec::with_capacity(self.params.len());
574-
for p in self.params.iter().filter(|p| !is_impl_trait(p) && !is_elided_lifetime(p)) {
575-
let p = clean_generic_param(cx, Some(self), p);
576-
params.push(p);
508+
for p in self.params {
509+
if !p.is_elided_lifetime() {
510+
params.push(clean_generic_param(cx, p));
511+
}
577512
}
578-
params.extend(impl_trait_params);
579-
580-
let mut generics = Generics {
581-
params,
582-
where_predicates: self.predicates.iter().filter_map(|x| x.clean(cx)).collect(),
583-
};
584513

585-
// Some duplicates are generated for ?Sized bounds between type params and where
586-
// predicates. The point in here is to move the bounds definitions from type params
587-
// to where predicates when such cases occur.
588-
for where_pred in &mut generics.where_predicates {
589-
match *where_pred {
590-
WherePredicate::BoundPredicate {
591-
ty: Generic(ref name), ref mut bounds, ..
592-
} => {
593-
if bounds.is_empty() {
594-
for param in &mut generics.params {
595-
match param.kind {
596-
GenericParamDefKind::Lifetime { .. } => {}
597-
GenericParamDefKind::Type { bounds: ref mut ty_bounds, .. } => {
598-
if &param.name == name {
599-
mem::swap(bounds, ty_bounds);
600-
break;
601-
}
602-
}
603-
GenericParamDefKind::Const { .. } => {}
604-
}
605-
}
606-
}
607-
}
608-
_ => continue,
514+
let mut where_predicates = Vec::with_capacity(self.predicates.len());
515+
for (i, p) in self.predicates.iter().enumerate() {
516+
if impl_trait.contains(&i) {
517+
continue;
609518
}
519+
where_predicates.push(p.clean(cx));
610520
}
611-
generics
521+
Generics { params, where_predicates }
612522
}
613523
}
614524

@@ -991,7 +901,7 @@ impl<'tcx> Clean<'tcx, PolyTrait> for hir::PolyTraitRef<'tcx> {
991901
generic_params: self
992902
.bound_generic_params
993903
.iter()
994-
.map(|x| clean_generic_param(cx, None, x))
904+
.map(|x| clean_generic_param(cx, x))
995905
.collect(),
996906
}
997907
}
@@ -1866,7 +1776,7 @@ impl<'tcx> Clean<'tcx, BareFunctionDecl> for hir::BareFnTy<'tcx> {
18661776
let (generic_params, decl) = enter_impl_trait(cx, |cx| {
18671777
// NOTE: generics must be cleaned before args
18681778
let generic_params =
1869-
self.generic_params.iter().map(|x| clean_generic_param(cx, None, x)).collect();
1779+
self.generic_params.iter().map(|x| clean_generic_param(cx, x)).collect();
18701780
let args = clean_args_from_types_and_names(cx, self.decl.inputs, self.param_names);
18711781
let decl = clean_fn_decl_with_args(cx, self.decl, args);
18721782
(generic_params, decl)

src/librustdoc/clean/types.rs

+4-21
Original file line numberDiff line numberDiff line change
@@ -1362,17 +1362,11 @@ impl WherePredicate {
13621362

13631363
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
13641364
pub(crate) enum GenericParamDefKind {
1365-
Lifetime { outlives: Vec<Lifetime> },
1366-
Type { did: DefId, bounds: Vec<GenericBound>, default: Option<Box<Type>>, synthetic: bool },
1365+
Lifetime,
1366+
Type { did: DefId, default: Option<Box<Type>>, synthetic: bool },
13671367
Const { did: DefId, ty: Box<Type>, default: Option<Box<String>> },
13681368
}
13691369

1370-
impl GenericParamDefKind {
1371-
pub(crate) fn is_type(&self) -> bool {
1372-
matches!(self, GenericParamDefKind::Type { .. })
1373-
}
1374-
}
1375-
13761370
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
13771371
pub(crate) struct GenericParamDef {
13781372
pub(crate) name: Symbol,
@@ -1381,26 +1375,15 @@ pub(crate) struct GenericParamDef {
13811375

13821376
// `GenericParamDef` is used in many places. Make sure it doesn't unintentionally get bigger.
13831377
#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
1384-
rustc_data_structures::static_assert_size!(GenericParamDef, 56);
1378+
rustc_data_structures::static_assert_size!(GenericParamDef, 40);
13851379

13861380
impl GenericParamDef {
13871381
pub(crate) fn is_synthetic_type_param(&self) -> bool {
13881382
match self.kind {
1389-
GenericParamDefKind::Lifetime { .. } | GenericParamDefKind::Const { .. } => false,
1383+
GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => false,
13901384
GenericParamDefKind::Type { synthetic, .. } => synthetic,
13911385
}
13921386
}
1393-
1394-
pub(crate) fn is_type(&self) -> bool {
1395-
self.kind.is_type()
1396-
}
1397-
1398-
pub(crate) fn get_bounds(&self) -> Option<&[GenericBound]> {
1399-
match self.kind {
1400-
GenericParamDefKind::Type { ref bounds, .. } => Some(bounds),
1401-
_ => None,
1402-
}
1403-
}
14041387
}
14051388

14061389
// maybe use a Generic enum and use Vec<Generic>?

0 commit comments

Comments
 (0)