Skip to content

Commit afd009a

Browse files
committed
Parse generic const items
1 parent b6dd153 commit afd009a

File tree

12 files changed

+220
-34
lines changed

12 files changed

+220
-34
lines changed

Diff for: 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)

Diff for: 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
}

Diff for: 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
}

Diff for: 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() {

Diff for: 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,

Diff for: 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(

Diff for: 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

Diff for: 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.

Diff for: compiler/rustc_parse/messages.ftl

+8
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,8 @@ parse_single_colon_import_path = expected `::`, found `:`
690690
parse_single_colon_struct_type = found single colon in a struct field type path
691691
.suggestion = write a path separator here
692692
693+
parse_static_with_generics = static items may not have generic parameters
694+
693695
parse_struct_literal_body_without_path =
694696
struct literal body without path
695697
.suggestion = you might have forgotten to add the struct literal inside the block
@@ -847,6 +849,12 @@ parse_visibility_not_followed_by_item = visibility `{$vis}` is not followed by a
847849
.label = the visibility
848850
.help = you likely meant to define an item, e.g., `{$vis} fn foo() {"{}"}`
849851
852+
parse_where_clause_before_const_body = where clauses are not allowed before const item bodies
853+
.label = unexpected where clause
854+
.name_label = while parsing this const item
855+
.body_label = the item body
856+
.suggestion = move the body before the where clause
857+
850858
parse_where_clause_before_tuple_struct_body = where clauses are not allowed before tuple struct bodies
851859
.label = unexpected where clause
852860
.name_label = while parsing this tuple struct

Diff for: compiler/rustc_parse/src/errors.rs

+31
Original file line numberDiff line numberDiff line change
@@ -2692,3 +2692,34 @@ pub(crate) struct ExpectedBuiltinIdent {
26922692
#[primary_span]
26932693
pub span: Span,
26942694
}
2695+
2696+
#[derive(Diagnostic)]
2697+
#[diag(parse_static_with_generics)]
2698+
pub(crate) struct StaticWithGenerics {
2699+
#[primary_span]
2700+
pub span: Span,
2701+
}
2702+
2703+
#[derive(Diagnostic)]
2704+
#[diag(parse_where_clause_before_const_body)]
2705+
pub(crate) struct WhereClauseBeforeConstBody {
2706+
#[primary_span]
2707+
#[label]
2708+
pub span: Span,
2709+
#[label(parse_name_label)]
2710+
pub name: Span,
2711+
#[label(parse_body_label)]
2712+
pub body: Span,
2713+
#[subdiagnostic]
2714+
pub sugg: Option<WhereClauseBeforeConstBodySugg>,
2715+
}
2716+
2717+
#[derive(Subdiagnostic)]
2718+
#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
2719+
pub(crate) struct WhereClauseBeforeConstBodySugg {
2720+
#[suggestion_part(code = "= {snippet} ")]
2721+
pub left: Span,
2722+
pub snippet: String,
2723+
#[suggestion_part(code = "")]
2724+
pub right: Span,
2725+
}

0 commit comments

Comments
 (0)