Skip to content

Commit 04abc37

Browse files
committed
Auto merge of #113522 - fmease:generic-consts, r=cjgillot
Implement generic const items This implements generic parameters and where-clauses on free and associated const items under the experimental feature gate `generic_const_items`. See rust-lang/lang-team#214. Tracking issue: #113521. Fixes #104400. This PR doesn't include rustfmt support as per [nightly style procedure](https://github.com/rust-lang/style-team/blob/master/nightly-style-procedure.md) and it doesn't add rustdoc JSON support (see [related Zulip topic](https://rust-lang.zulipchat.com/#narrow/stream/266220-rustdoc/topic/Rustdoc.20JSON.3A.20Experimental.20rustc.20features)). CC `@scottmcm` `@compiler-errors` `@WalterSmuts` r? `@oli-obk` <details><summary>Resolved Questions</summary> * Q: Should `const ADD<const N: usize, const M: usize>: usize = N + M; ADD::<0, 1>` trigger the error *generic parameters may not be used in const operations* (which can be unlocked with `#![feature(generic_const_exprs)]`). Currently it doesn't. Or does this fall under [this paragraph](https://github.com/rust-lang/rust/blob/71f71a5397c42fec01f5c1045c638d961fa9f7ca/compiler/rustc_resolve/src/late.rs#L191)? * A: No, #113522 (comment) * Q: Should `const UNUSED: () = () where String: Copy;` (with `#![feature(trivial_bounds)]` and with `UNUSED` unused) succeed compilation? Currently it doesn't: *evaluation of constant value failed // entering unreachable code* * A: Yes, but postponed until stabilization (latest), #113522 (comment) </details>
2 parents b6dd153 + 203d400 commit 04abc37

File tree

91 files changed

+1645
-360
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

91 files changed

+1645
-360
lines changed

compiler/rustc_ast/src/ast.rs

+2
Original file line numberDiff line numberDiff line change
@@ -2947,6 +2947,7 @@ pub struct StaticItem {
29472947
#[derive(Clone, Encodable, Decodable, Debug)]
29482948
pub struct ConstItem {
29492949
pub defaultness: Defaultness,
2950+
pub generics: Generics,
29502951
pub ty: P<Ty>,
29512952
pub expr: Option<P<Expr>>,
29522953
}
@@ -3058,6 +3059,7 @@ impl ItemKind {
30583059
match self {
30593060
Self::Fn(box Fn { generics, .. })
30603061
| Self::TyAlias(box TyAlias { generics, .. })
3062+
| Self::Const(box ConstItem { generics, .. })
30613063
| Self::Enum(_, generics)
30623064
| Self::Struct(_, generics)
30633065
| Self::Union(_, generics)

compiler/rustc_ast/src/mut_visit.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1149,10 +1149,11 @@ pub fn noop_flat_map_assoc_item<T: MutVisitor>(
11491149
}
11501150

11511151
fn visit_const_item<T: MutVisitor>(
1152-
ConstItem { defaultness, ty, expr }: &mut ConstItem,
1152+
ConstItem { defaultness, generics, ty, expr }: &mut ConstItem,
11531153
visitor: &mut T,
11541154
) {
11551155
visit_defaultness(defaultness, visitor);
1156+
visitor.visit_generics(generics);
11561157
visitor.visit_ty(ty);
11571158
visit_opt(expr, |expr| visitor.visit_expr(expr));
11581159
}

compiler/rustc_ast/src/visit.rs

+8-3
Original file line numberDiff line numberDiff line change
@@ -308,8 +308,12 @@ pub fn walk_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a Item) {
308308
match &item.kind {
309309
ItemKind::ExternCrate(_) => {}
310310
ItemKind::Use(use_tree) => visitor.visit_use_tree(use_tree, item.id, false),
311-
ItemKind::Static(box StaticItem { ty, mutability: _, expr })
312-
| ItemKind::Const(box ConstItem { ty, expr, .. }) => {
311+
ItemKind::Static(box StaticItem { ty, mutability: _, expr }) => {
312+
visitor.visit_ty(ty);
313+
walk_list!(visitor, visit_expr, expr);
314+
}
315+
ItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
316+
visitor.visit_generics(generics);
313317
visitor.visit_ty(ty);
314318
walk_list!(visitor, visit_expr, expr);
315319
}
@@ -677,7 +681,8 @@ pub fn walk_assoc_item<'a, V: Visitor<'a>>(visitor: &mut V, item: &'a AssocItem,
677681
visitor.visit_ident(ident);
678682
walk_list!(visitor, visit_attribute, attrs);
679683
match kind {
680-
AssocItemKind::Const(box ConstItem { ty, expr, .. }) => {
684+
AssocItemKind::Const(box ConstItem { defaultness: _, generics, ty, expr }) => {
685+
visitor.visit_generics(generics);
681686
visitor.visit_ty(ty);
682687
walk_list!(visitor, visit_expr, expr);
683688
}

compiler/rustc_ast_lowering/src/item.rs

+39-16
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
231231
let (ty, body_id) = self.lower_const_item(t, span, e.as_deref());
232232
hir::ItemKind::Static(ty, *m, body_id)
233233
}
234-
ItemKind::Const(box ast::ConstItem { ty, expr, .. }) => {
235-
let (ty, body_id) = self.lower_const_item(ty, span, expr.as_deref());
236-
hir::ItemKind::Const(ty, body_id)
234+
ItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
235+
let (generics, (ty, body_id)) = self.lower_generics(
236+
generics,
237+
Const::No,
238+
id,
239+
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
240+
|this| this.lower_const_item(ty, span, expr.as_deref()),
241+
);
242+
hir::ItemKind::Const(ty, generics, body_id)
237243
}
238244
ItemKind::Fn(box Fn {
239245
sig: FnSig { decl, header, span: fn_sig_span },
@@ -715,11 +721,23 @@ impl<'hir> LoweringContext<'_, 'hir> {
715721
let trait_item_def_id = hir_id.expect_owner();
716722

717723
let (generics, kind, has_default) = match &i.kind {
718-
AssocItemKind::Const(box ConstItem { ty, expr, .. }) => {
719-
let ty =
720-
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
721-
let body = expr.as_ref().map(|x| self.lower_const_body(i.span, Some(x)));
722-
(hir::Generics::empty(), hir::TraitItemKind::Const(ty, body), body.is_some())
724+
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => {
725+
let (generics, kind) = self.lower_generics(
726+
&generics,
727+
Const::No,
728+
i.id,
729+
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
730+
|this| {
731+
let ty = this.lower_ty(
732+
ty,
733+
&ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy),
734+
);
735+
let body = expr.as_ref().map(|x| this.lower_const_body(i.span, Some(x)));
736+
737+
hir::TraitItemKind::Const(ty, body)
738+
},
739+
);
740+
(generics, kind, expr.is_some())
723741
}
724742
AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => {
725743
let asyncness = sig.header.asyncness;
@@ -817,14 +835,19 @@ impl<'hir> LoweringContext<'_, 'hir> {
817835
self.lower_attrs(hir_id, &i.attrs);
818836

819837
let (generics, kind) = match &i.kind {
820-
AssocItemKind::Const(box ConstItem { ty, expr, .. }) => {
821-
let ty =
822-
self.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
823-
(
824-
hir::Generics::empty(),
825-
hir::ImplItemKind::Const(ty, self.lower_const_body(i.span, expr.as_deref())),
826-
)
827-
}
838+
AssocItemKind::Const(box ConstItem { generics, ty, expr, .. }) => self.lower_generics(
839+
&generics,
840+
Const::No,
841+
i.id,
842+
&ImplTraitContext::Disallowed(ImplTraitPosition::Generic),
843+
|this| {
844+
let ty = this
845+
.lower_ty(ty, &ImplTraitContext::Disallowed(ImplTraitPosition::ConstTy));
846+
let body = this.lower_const_body(i.span, expr.as_deref());
847+
848+
hir::ImplItemKind::Const(ty, body)
849+
},
850+
),
828851
AssocItemKind::Fn(box Fn { sig, generics, body, .. }) => {
829852
self.current_item = Some(i.span);
830853
let asyncness = sig.header.asyncness;

compiler/rustc_ast_passes/src/feature_gate.rs

+1
Original file line numberDiff line numberDiff line change
@@ -569,6 +569,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
569569
gate_all!(const_closures, "const closures are experimental");
570570
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
571571
gate_all!(explicit_tail_calls, "`become` expression is experimental");
572+
gate_all!(generic_const_items, "generic const items are experimental");
572573

573574
if !visitor.features.negative_bounds {
574575
for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {

compiler/rustc_ast_pretty/src/pprust/state/item.rs

+26-9
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,15 @@ impl<'a> State<'a> {
3030
ast::ForeignItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
3131
self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
3232
}
33-
ast::ForeignItemKind::Static(ty, mutbl, body) => {
34-
let def = ast::Defaultness::Final;
35-
self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def);
36-
}
33+
ast::ForeignItemKind::Static(ty, mutbl, body) => self.print_item_const(
34+
ident,
35+
Some(*mutbl),
36+
&ast::Generics::default(),
37+
ty,
38+
body.as_deref(),
39+
vis,
40+
ast::Defaultness::Final,
41+
),
3742
ast::ForeignItemKind::TyAlias(box ast::TyAlias {
3843
defaultness,
3944
generics,
@@ -67,6 +72,7 @@ impl<'a> State<'a> {
6772
&mut self,
6873
ident: Ident,
6974
mutbl: Option<ast::Mutability>,
75+
generics: &ast::Generics,
7076
ty: &ast::Ty,
7177
body: Option<&ast::Expr>,
7278
vis: &ast::Visibility,
@@ -82,6 +88,7 @@ impl<'a> State<'a> {
8288
};
8389
self.word_space(leading);
8490
self.print_ident(ident);
91+
self.print_generic_params(&generics.params);
8592
self.word_space(":");
8693
self.print_type(ty);
8794
if body.is_some() {
@@ -92,6 +99,7 @@ impl<'a> State<'a> {
9299
self.word_space("=");
93100
self.print_expr(body);
94101
}
102+
self.print_where_clause(&generics.where_clause);
95103
self.word(";");
96104
self.end(); // end the outer cbox
97105
}
@@ -158,20 +166,21 @@ impl<'a> State<'a> {
158166
self.word(";");
159167
}
160168
ast::ItemKind::Static(box StaticItem { ty, mutability: mutbl, expr: body }) => {
161-
let def = ast::Defaultness::Final;
162169
self.print_item_const(
163170
item.ident,
164171
Some(*mutbl),
172+
&ast::Generics::default(),
165173
ty,
166174
body.as_deref(),
167175
&item.vis,
168-
def,
176+
ast::Defaultness::Final,
169177
);
170178
}
171-
ast::ItemKind::Const(box ast::ConstItem { defaultness, ty, expr }) => {
179+
ast::ItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => {
172180
self.print_item_const(
173181
item.ident,
174182
None,
183+
generics,
175184
ty,
176185
expr.as_deref(),
177186
&item.vis,
@@ -515,8 +524,16 @@ impl<'a> State<'a> {
515524
ast::AssocItemKind::Fn(box ast::Fn { defaultness, sig, generics, body }) => {
516525
self.print_fn_full(sig, ident, generics, vis, *defaultness, body.as_deref(), attrs);
517526
}
518-
ast::AssocItemKind::Const(box ast::ConstItem { defaultness, ty, expr }) => {
519-
self.print_item_const(ident, None, ty, expr.as_deref(), vis, *defaultness);
527+
ast::AssocItemKind::Const(box ast::ConstItem { defaultness, generics, ty, expr }) => {
528+
self.print_item_const(
529+
ident,
530+
None,
531+
generics,
532+
ty,
533+
expr.as_deref(),
534+
vis,
535+
*defaultness,
536+
);
520537
}
521538
ast::AssocItemKind::Type(box ast::TyAlias {
522539
defaultness,

compiler/rustc_builtin_macros/src/test.rs

+1
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,7 @@ pub fn expand_test_or_bench(
255255
ast::ItemKind::Const(
256256
ast::ConstItem {
257257
defaultness: ast::Defaultness::Final,
258+
generics: ast::Generics::default(),
258259
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
259260
// test::TestDescAndFn {
260261
expr: Some(

compiler/rustc_expand/src/build.rs

+10-1
Original file line numberDiff line numberDiff line change
@@ -643,7 +643,16 @@ impl<'a> ExtCtxt<'a> {
643643
span,
644644
name,
645645
AttrVec::new(),
646-
ast::ItemKind::Const(ast::ConstItem { defaultness, ty, expr: Some(expr) }.into()),
646+
ast::ItemKind::Const(
647+
ast::ConstItem {
648+
defaultness,
649+
// FIXME(generic_const_items): Pass the generics as a parameter.
650+
generics: ast::Generics::default(),
651+
ty,
652+
expr: Some(expr),
653+
}
654+
.into(),
655+
),
647656
)
648657
}
649658

compiler/rustc_feature/src/active.rs

+2
Original file line numberDiff line numberDiff line change
@@ -424,6 +424,8 @@ declare_features! (
424424
(incomplete, generic_associated_types_extended, "1.61.0", Some(95451), None),
425425
/// Allows non-trivial generic constants which have to have wfness manually propagated to callers
426426
(incomplete, generic_const_exprs, "1.56.0", Some(76560), None),
427+
/// Allows generic parameters and where-clauses on free & associated const items.
428+
(incomplete, generic_const_items, "CURRENT_RUSTC_VERSION", Some(113521), None),
427429
/// Allows using `..=X` as a patterns in slices.
428430
(active, half_open_range_patterns_in_slices, "1.66.0", Some(67264), None),
429431
/// Allows `if let` guard in match arms.

compiler/rustc_hir/src/hir.rs

+14-9
Original file line numberDiff line numberDiff line change
@@ -3130,9 +3130,9 @@ impl<'hir> Item<'hir> {
31303130
}
31313131
/// Expect an [`ItemKind::Const`] or panic.
31323132
#[track_caller]
3133-
pub fn expect_const(&self) -> (&'hir Ty<'hir>, BodyId) {
3134-
let ItemKind::Const(ty, body) = self.kind else { self.expect_failed("a constant") };
3135-
(ty, body)
3133+
pub fn expect_const(&self) -> (&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId) {
3134+
let ItemKind::Const(ty, gen, body) = self.kind else { self.expect_failed("a constant") };
3135+
(ty, gen, body)
31363136
}
31373137
/// Expect an [`ItemKind::Fn`] or panic.
31383138
#[track_caller]
@@ -3319,7 +3319,7 @@ pub enum ItemKind<'hir> {
33193319
/// A `static` item.
33203320
Static(&'hir Ty<'hir>, Mutability, BodyId),
33213321
/// A `const` item.
3322-
Const(&'hir Ty<'hir>, BodyId),
3322+
Const(&'hir Ty<'hir>, &'hir Generics<'hir>, BodyId),
33233323
/// A function declaration.
33243324
Fn(FnSig<'hir>, &'hir Generics<'hir>, BodyId),
33253325
/// A MBE macro definition (`macro_rules!` or `macro`).
@@ -3372,6 +3372,7 @@ impl ItemKind<'_> {
33723372
Some(match *self {
33733373
ItemKind::Fn(_, ref generics, _)
33743374
| ItemKind::TyAlias(_, ref generics)
3375+
| ItemKind::Const(_, ref generics, _)
33753376
| ItemKind::OpaqueTy(OpaqueTy { ref generics, .. })
33763377
| ItemKind::Enum(_, ref generics)
33773378
| ItemKind::Struct(_, ref generics)
@@ -3567,7 +3568,9 @@ impl<'hir> OwnerNode<'hir> {
35673568
match self {
35683569
OwnerNode::Item(Item {
35693570
kind:
3570-
ItemKind::Static(_, _, body) | ItemKind::Const(_, body) | ItemKind::Fn(_, _, body),
3571+
ItemKind::Static(_, _, body)
3572+
| ItemKind::Const(_, _, body)
3573+
| ItemKind::Fn(_, _, body),
35713574
..
35723575
})
35733576
| OwnerNode::TraitItem(TraitItem {
@@ -3770,9 +3773,9 @@ impl<'hir> Node<'hir> {
37703773
pub fn ty(self) -> Option<&'hir Ty<'hir>> {
37713774
match self {
37723775
Node::Item(it) => match it.kind {
3773-
ItemKind::TyAlias(ty, _) | ItemKind::Static(ty, _, _) | ItemKind::Const(ty, _) => {
3774-
Some(ty)
3775-
}
3776+
ItemKind::TyAlias(ty, _)
3777+
| ItemKind::Static(ty, _, _)
3778+
| ItemKind::Const(ty, _, _) => Some(ty),
37763779
_ => None,
37773780
},
37783781
Node::TraitItem(it) => match it.kind {
@@ -3800,7 +3803,9 @@ impl<'hir> Node<'hir> {
38003803
match self {
38013804
Node::Item(Item {
38023805
kind:
3803-
ItemKind::Static(_, _, body) | ItemKind::Const(_, body) | ItemKind::Fn(_, _, body),
3806+
ItemKind::Static(_, _, body)
3807+
| ItemKind::Const(_, _, body)
3808+
| ItemKind::Fn(_, _, body),
38043809
..
38053810
})
38063811
| Node::TraitItem(TraitItem {

compiler/rustc_hir/src/intravisit.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -467,11 +467,17 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) {
467467
ItemKind::Use(ref path, _) => {
468468
visitor.visit_use(path, item.hir_id());
469469
}
470-
ItemKind::Static(ref typ, _, body) | ItemKind::Const(ref typ, body) => {
470+
ItemKind::Static(ref typ, _, body) => {
471471
visitor.visit_id(item.hir_id());
472472
visitor.visit_ty(typ);
473473
visitor.visit_nested_body(body);
474474
}
475+
ItemKind::Const(ref typ, ref generics, body) => {
476+
visitor.visit_id(item.hir_id());
477+
visitor.visit_ty(typ);
478+
visitor.visit_generics(generics);
479+
visitor.visit_nested_body(body);
480+
}
475481
ItemKind::Fn(ref sig, ref generics, body_id) => {
476482
visitor.visit_id(item.hir_id());
477483
visitor.visit_fn(

0 commit comments

Comments
 (0)