Skip to content

Commit eee6d3d

Browse files
committed
Render generic consts in rustdoc
1 parent f893f3c commit eee6d3d

File tree

7 files changed

+116
-68
lines changed

7 files changed

+116
-68
lines changed

src/librustdoc/clean/inline.rs

+5
Original file line numberDiff line numberDiff line change
@@ -632,13 +632,18 @@ pub(crate) fn print_inlined_const(tcx: TyCtxt<'_>, did: DefId) -> String {
632632
}
633633

634634
fn build_const(cx: &mut DocContext<'_>, def_id: DefId) -> clean::Constant {
635+
let mut generics =
636+
clean_ty_generics(cx, cx.tcx.generics_of(def_id), cx.tcx.explicit_predicates_of(def_id));
637+
clean::simplify::move_bounds_to_generic_parameters(&mut generics);
638+
635639
clean::Constant {
636640
type_: clean_middle_ty(
637641
ty::Binder::dummy(cx.tcx.type_of(def_id).subst_identity()),
638642
cx,
639643
Some(def_id),
640644
None,
641645
),
646+
generics: Box::new(generics),
642647
kind: clean::ConstantKind::Extern { def_id },
643648
}
644649
}

src/librustdoc/clean/mod.rs

+30-38
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,7 @@ pub(crate) fn clean_const<'tcx>(constant: &hir::ConstArg, cx: &mut DocContext<'t
256256
Some(def_id),
257257
None,
258258
),
259+
generics: Box::new(Generics::default()),
259260
kind: ConstantKind::Anonymous { body: constant.value.body },
260261
}
261262
}
@@ -267,6 +268,7 @@ pub(crate) fn clean_middle_const<'tcx>(
267268
// FIXME: instead of storing the stringified expression, store `self` directly instead.
268269
Constant {
269270
type_: clean_middle_ty(constant.map_bound(|c| c.ty()), cx, None, None),
271+
generics: Box::new(Generics::default()),
270272
kind: ConstantKind::TyConst { expr: constant.skip_binder().to_string().into() },
271273
}
272274
}
@@ -1159,11 +1161,20 @@ fn clean_trait_item<'tcx>(trait_item: &hir::TraitItem<'tcx>, cx: &mut DocContext
11591161
let local_did = trait_item.owner_id.to_def_id();
11601162
cx.with_param_env(local_did, |cx| {
11611163
let inner = match trait_item.kind {
1162-
hir::TraitItemKind::Const(ty, Some(default)) => AssocConstItem(
1163-
clean_ty(ty, cx),
1164-
ConstantKind::Local { def_id: local_did, body: default },
1165-
),
1166-
hir::TraitItemKind::Const(ty, None) => TyAssocConstItem(clean_ty(ty, cx)),
1164+
hir::TraitItemKind::Const(ty, Some(default)) => {
1165+
// FIXME(generic_consts): I don't think we need to / should `enter_impl_trait`
1166+
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
1167+
AssocConstItem(
1168+
Box::new(generics),
1169+
clean_ty(ty, cx),
1170+
ConstantKind::Local { def_id: local_did, body: default },
1171+
)
1172+
}
1173+
hir::TraitItemKind::Const(ty, None) => {
1174+
// FIXME(generic_consts): I don't think we need to / should `enter_impl_trait`
1175+
let generics = enter_impl_trait(cx, |cx| clean_generics(trait_item.generics, cx));
1176+
TyAssocConstItem(Box::new(generics), clean_ty(ty, cx))
1177+
}
11671178
hir::TraitItemKind::Fn(ref sig, hir::TraitFn::Provided(body)) => {
11681179
let m = clean_function(cx, sig, trait_item.generics, FunctionArgs::Body(body));
11691180
MethodItem(m, None)
@@ -1208,8 +1219,9 @@ pub(crate) fn clean_impl_item<'tcx>(
12081219
cx.with_param_env(local_did, |cx| {
12091220
let inner = match impl_.kind {
12101221
hir::ImplItemKind::Const(ty, expr) => {
1222+
let generics = clean_generics(impl_.generics, cx);
12111223
let default = ConstantKind::Local { def_id: local_did, body: expr };
1212-
AssocConstItem(clean_ty(ty, cx), default)
1224+
AssocConstItem(Box::new(generics), clean_ty(ty, cx), default)
12131225
}
12141226
hir::ImplItemKind::Fn(ref sig, body) => {
12151227
let m = clean_function(cx, sig, impl_.generics, FunctionArgs::Body(body));
@@ -1250,14 +1262,21 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
12501262
None,
12511263
);
12521264

1265+
let mut generics = Box::new(clean_ty_generics(
1266+
cx,
1267+
tcx.generics_of(assoc_item.def_id),
1268+
tcx.explicit_predicates_of(assoc_item.def_id),
1269+
));
1270+
simplify::move_bounds_to_generic_parameters(&mut generics);
1271+
12531272
let provided = match assoc_item.container {
12541273
ty::ImplContainer => true,
12551274
ty::TraitContainer => tcx.defaultness(assoc_item.def_id).has_value(),
12561275
};
12571276
if provided {
1258-
AssocConstItem(ty, ConstantKind::Extern { def_id: assoc_item.def_id })
1277+
AssocConstItem(generics, ty, ConstantKind::Extern { def_id: assoc_item.def_id })
12591278
} else {
1260-
TyAssocConstItem(ty)
1279+
TyAssocConstItem(generics, ty)
12611280
}
12621281
}
12631282
ty::AssocKind::Fn => {
@@ -1348,34 +1367,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
13481367
tcx.generics_of(assoc_item.def_id),
13491368
ty::GenericPredicates { parent: None, predicates },
13501369
);
1351-
// Move bounds that are (likely) directly attached to the parameters of the
1352-
// (generic) associated type from the where clause to the respective parameter.
1353-
// There is no guarantee that this is what the user actually wrote but we have
1354-
// no way of knowing.
1355-
let mut where_predicates = ThinVec::new();
1356-
for mut pred in generics.where_predicates {
1357-
if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred
1358-
&& let Some(GenericParamDef {
1359-
kind: GenericParamDefKind::Type { bounds: param_bounds, .. },
1360-
..
1361-
}) = generics.params.iter_mut().find(|param| &param.name == arg)
1362-
{
1363-
param_bounds.append(bounds);
1364-
} else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred
1365-
&& let Some(GenericParamDef {
1366-
kind: GenericParamDefKind::Lifetime { outlives: param_bounds },
1367-
..
1368-
}) = generics.params.iter_mut().find(|param| &param.name == arg)
1369-
{
1370-
param_bounds.extend(bounds.drain(..).map(|bound| match bound {
1371-
GenericBound::Outlives(lifetime) => lifetime,
1372-
_ => unreachable!(),
1373-
}));
1374-
} else {
1375-
where_predicates.push(pred);
1376-
}
1377-
}
1378-
generics.where_predicates = where_predicates;
1370+
simplify::move_bounds_to_generic_parameters(&mut generics);
13791371

13801372
if let ty::TraitContainer = assoc_item.container {
13811373
// Move bounds that are (likely) directly attached to the associated type
@@ -2446,9 +2438,9 @@ fn clean_maybe_renamed_item<'tcx>(
24462438
ItemKind::Static(ty, mutability, body_id) => {
24472439
StaticItem(Static { type_: clean_ty(ty, cx), mutability, expr: Some(body_id) })
24482440
}
2449-
// FIXME(fmease): rustdoc integration
2450-
ItemKind::Const(ty, _generics, body_id) => ConstantItem(Constant {
2441+
ItemKind::Const(ty, generics, body_id) => ConstantItem(Constant {
24512442
type_: clean_ty(ty, cx),
2443+
generics: Box::new(clean_generics(generics, cx)),
24522444
kind: ConstantKind::Local { body: body_id, def_id },
24532445
}),
24542446
ItemKind::OpaqueTy(ref ty) => OpaqueTyItem(OpaqueTy {

src/librustdoc/clean/simplify.rs

+35
Original file line numberDiff line numberDiff line change
@@ -136,3 +136,38 @@ fn trait_is_same_or_supertrait(cx: &DocContext<'_>, child: DefId, trait_: DefId)
136136
})
137137
.any(|did| trait_is_same_or_supertrait(cx, did, trait_))
138138
}
139+
140+
/// Move bounds that are (likely) directly attached to generic parameters from the where-clause to
141+
/// the respective parameter.
142+
///
143+
/// There is no guarantee that this is what the user actually wrote but we have no way of knowing.
144+
// FIXME(fmease): It'd make a lot of sense to just incorporate this logic into `clean_ty_generics`
145+
// making every of its users benefit from it.
146+
pub(crate) fn move_bounds_to_generic_parameters(generics: &mut clean::Generics) {
147+
use clean::types::*;
148+
149+
let mut where_predicates = ThinVec::new();
150+
for mut pred in generics.where_predicates.drain(..) {
151+
if let WherePredicate::BoundPredicate { ty: Generic(arg), bounds, .. } = &mut pred
152+
&& let Some(GenericParamDef {
153+
kind: GenericParamDefKind::Type { bounds: param_bounds, .. },
154+
..
155+
}) = generics.params.iter_mut().find(|param| &param.name == arg)
156+
{
157+
param_bounds.append(bounds);
158+
} else if let WherePredicate::RegionPredicate { lifetime: Lifetime(arg), bounds } = &mut pred
159+
&& let Some(GenericParamDef {
160+
kind: GenericParamDefKind::Lifetime { outlives: param_bounds },
161+
..
162+
}) = generics.params.iter_mut().find(|param| &param.name == arg)
163+
{
164+
param_bounds.extend(bounds.drain(..).map(|bound| match bound {
165+
GenericBound::Outlives(lifetime) => lifetime,
166+
_ => unreachable!(),
167+
}));
168+
} else {
169+
where_predicates.push(pred);
170+
}
171+
}
172+
generics.where_predicates = where_predicates;
173+
}

src/librustdoc/clean/types.rs

+9-7
Original file line numberDiff line numberDiff line change
@@ -830,9 +830,9 @@ pub(crate) enum ItemKind {
830830
ProcMacroItem(ProcMacro),
831831
PrimitiveItem(PrimitiveType),
832832
/// A required associated constant in a trait declaration.
833-
TyAssocConstItem(Type),
833+
TyAssocConstItem(Box<Generics>, Type),
834834
/// An associated constant in a trait impl or a provided one in a trait declaration.
835-
AssocConstItem(Type, ConstantKind),
835+
AssocConstItem(Box<Generics>, Type, ConstantKind),
836836
/// A required associated type in a trait declaration.
837837
///
838838
/// The bounds may be non-empty if there is a `where` clause.
@@ -877,8 +877,8 @@ impl ItemKind {
877877
| MacroItem(_)
878878
| ProcMacroItem(_)
879879
| PrimitiveItem(_)
880-
| TyAssocConstItem(_)
881-
| AssocConstItem(_, _)
880+
| TyAssocConstItem(..)
881+
| AssocConstItem(..)
882882
| TyAssocTypeItem(..)
883883
| AssocTypeItem(..)
884884
| StrippedItem(_)
@@ -1275,7 +1275,7 @@ impl Lifetime {
12751275
}
12761276
}
12771277

1278-
#[derive(Clone, Debug)]
1278+
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
12791279
pub(crate) enum WherePredicate {
12801280
BoundPredicate { ty: Type, bounds: Vec<GenericBound>, bound_params: Vec<GenericParamDef> },
12811281
RegionPredicate { lifetime: Lifetime, bounds: Vec<GenericBound> },
@@ -1345,7 +1345,7 @@ impl GenericParamDef {
13451345
}
13461346

13471347
// maybe use a Generic enum and use Vec<Generic>?
1348-
#[derive(Clone, Debug, Default)]
1348+
#[derive(Clone, PartialEq, Eq, Hash, Debug, Default)]
13491349
pub(crate) struct Generics {
13501350
pub(crate) params: ThinVec<GenericParamDef>,
13511351
pub(crate) where_predicates: ThinVec<WherePredicate>,
@@ -2253,6 +2253,7 @@ pub(crate) struct Static {
22532253
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
22542254
pub(crate) struct Constant {
22552255
pub(crate) type_: Type,
2256+
pub(crate) generics: Box<Generics>,
22562257
pub(crate) kind: ConstantKind,
22572258
}
22582259

@@ -2502,7 +2503,8 @@ mod size_asserts {
25022503
static_assert_size!(GenericParamDef, 56);
25032504
static_assert_size!(Generics, 16);
25042505
static_assert_size!(Item, 56);
2505-
static_assert_size!(ItemKind, 64);
2506+
// FIXME(generic_consts): Further reduce the size.
2507+
static_assert_size!(ItemKind, 72);
25062508
static_assert_size!(PathSegment, 40);
25072509
static_assert_size!(Type, 32);
25082510
// tidy-alphabetical-end

src/librustdoc/html/render/mod.rs

+28-20
Original file line numberDiff line numberDiff line change
@@ -748,20 +748,22 @@ fn assoc_href_attr(it: &clean::Item, link: AssocItemLink<'_>, cx: &Context<'_>)
748748
fn assoc_const(
749749
w: &mut Buffer,
750750
it: &clean::Item,
751+
generics: &clean::Generics,
751752
ty: &clean::Type,
752753
default: Option<&clean::ConstantKind>,
753754
link: AssocItemLink<'_>,
754-
extra: &str,
755+
indent: usize,
755756
cx: &Context<'_>,
756757
) {
757758
let tcx = cx.tcx();
758759
write!(
759760
w,
760-
"{extra}{vis}const <a{href} class=\"constant\">{name}</a>: {ty}",
761-
extra = extra,
761+
"{indent}{vis}const <a{href} class=\"constant\">{name}</a>{generics}: {ty}",
762+
indent = " ".repeat(indent),
762763
vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
763764
href = assoc_href_attr(it, link, cx),
764765
name = it.name.as_ref().unwrap(),
766+
generics = generics.print(cx),
765767
ty = ty.print(cx),
766768
);
767769
if let Some(default) = default {
@@ -774,6 +776,7 @@ fn assoc_const(
774776
// Find a way to print constants here without all that jazz.
775777
write!(w, "{}", Escape(&default.value(tcx).unwrap_or_else(|| default.expr(tcx))));
776778
}
779+
write!(w, "{}", print_where_clause(generics, cx, indent, Ending::NoNewline));
777780
}
778781

779782
fn assoc_type(
@@ -986,19 +989,22 @@ fn render_assoc_item(
986989
clean::MethodItem(m, _) => {
987990
assoc_method(w, item, &m.generics, &m.decl, link, parent, cx, render_mode)
988991
}
989-
kind @ (clean::TyAssocConstItem(ty) | clean::AssocConstItem(ty, _)) => assoc_const(
990-
w,
991-
item,
992-
ty,
993-
match kind {
994-
clean::TyAssocConstItem(_) => None,
995-
clean::AssocConstItem(_, default) => Some(default),
996-
_ => unreachable!(),
997-
},
998-
link,
999-
if parent == ItemType::Trait { " " } else { "" },
1000-
cx,
1001-
),
992+
kind @ (clean::TyAssocConstItem(generics, ty) | clean::AssocConstItem(generics, ty, _)) => {
993+
assoc_const(
994+
w,
995+
item,
996+
generics,
997+
ty,
998+
match kind {
999+
clean::TyAssocConstItem(..) => None,
1000+
clean::AssocConstItem(.., default) => Some(default),
1001+
_ => unreachable!(),
1002+
},
1003+
link,
1004+
if parent == ItemType::Trait { 4 } else { 0 },
1005+
cx,
1006+
)
1007+
}
10021008
clean::TyAssocTypeItem(ref generics, ref bounds) => assoc_type(
10031009
w,
10041010
item,
@@ -1565,7 +1571,8 @@ fn render_impl(
15651571
w.write_str("</section>");
15661572
}
15671573
}
1568-
kind @ (clean::TyAssocConstItem(ty) | clean::AssocConstItem(ty, _)) => {
1574+
kind @ (clean::TyAssocConstItem(generics, ty)
1575+
| clean::AssocConstItem(generics, ty, _)) => {
15691576
let source_id = format!("{}.{}", item_type, name);
15701577
let id = cx.derive_id(source_id.clone());
15711578
write!(w, "<section id=\"{}\" class=\"{}{}\">", id, item_type, in_trait_class);
@@ -1578,14 +1585,15 @@ fn render_impl(
15781585
assoc_const(
15791586
w,
15801587
item,
1588+
generics,
15811589
ty,
15821590
match kind {
1583-
clean::TyAssocConstItem(_) => None,
1584-
clean::AssocConstItem(_, default) => Some(default),
1591+
clean::TyAssocConstItem(..) => None,
1592+
clean::AssocConstItem(.., default) => Some(default),
15851593
_ => unreachable!(),
15861594
},
15871595
link.anchor(if trait_.is_some() { &source_id } else { &id }),
1588-
"",
1596+
0,
15891597
cx,
15901598
);
15911599
w.write_str("</h4>");

src/librustdoc/html/render/print_item.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -1543,10 +1543,12 @@ fn item_constant(w: &mut Buffer, cx: &mut Context<'_>, it: &clean::Item, c: &cle
15431543

15441544
write!(
15451545
w,
1546-
"{vis}const {name}: {typ}",
1546+
"{vis}const {name}{generics}: {typ}{where_clause}",
15471547
vis = visibility_print_with_space(it.visibility(tcx), it.item_id, cx),
15481548
name = it.name.unwrap(),
1549+
generics = c.generics.print(cx),
15491550
typ = c.type_.print(cx),
1551+
where_clause = print_where_clause(&c.generics, cx, 0, Ending::NoNewline),
15501552
);
15511553

15521554
// FIXME: The code below now prints

src/librustdoc/json/conversions.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -321,8 +321,12 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
321321
impls: Vec::new(), // Added in JsonRenderer::item
322322
})
323323
}
324-
TyAssocConstItem(ty) => ItemEnum::AssocConst { type_: ty.into_tcx(tcx), default: None },
325-
AssocConstItem(ty, default) => {
324+
// FIXME(generic_consts): Add support.
325+
TyAssocConstItem(_generics, ty) => {
326+
ItemEnum::AssocConst { type_: ty.into_tcx(tcx), default: None }
327+
}
328+
// FIXME(generic_consts): Add support.
329+
AssocConstItem(_generics, ty, default) => {
326330
ItemEnum::AssocConst { type_: ty.into_tcx(tcx), default: Some(default.expr(tcx)) }
327331
}
328332
TyAssocTypeItem(g, b) => ItemEnum::AssocType {

0 commit comments

Comments
 (0)