Skip to content

Commit bcdda5e

Browse files
committed
Parse generic consts
1 parent 02d1ee4 commit bcdda5e

File tree

13 files changed

+193
-21
lines changed

13 files changed

+193
-21
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2942,6 +2942,7 @@ pub struct StaticItem {
29422942
#[derive(Clone, Encodable, Decodable, Debug)]
29432943
pub struct ConstItem {
29442944
pub defaultness: Defaultness,
2945+
pub generics: Generics,
29452946
pub ty: P<Ty>,
29462947
pub expr: Option<P<Expr>>,
29472948
}
@@ -3053,6 +3054,7 @@ impl ItemKind {
30533054
match self {
30543055
Self::Fn(box Fn { generics, .. })
30553056
| Self::TyAlias(box TyAlias { generics, .. })
3057+
| Self::Const(box ConstItem { generics, .. })
30563058
| Self::Enum(_, generics)
30573059
| Self::Struct(_, generics)
30583060
| Self::Union(_, generics)

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 2 additions & 1 deletion
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

Lines changed: 8 additions & 3 deletions
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 { 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 { generics, ty, expr, .. }) => {
685+
visitor.visit_generics(generics);
681686
visitor.visit_ty(ty);
682687
walk_list!(visitor, visit_expr, expr);
683688
}

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1338,6 +1338,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13381338
self.check_item_named(item.ident, "const");
13391339
}
13401340

1341+
// FIXME(generic_consts): Pretty sure we need to visit the generics of consts here, too.
13411342
match &item.kind {
13421343
AssocItemKind::Type(box TyAlias { generics, bounds, ty, .. })
13431344
if ctxt == AssocCtxt::Trait =>

compiler/rustc_ast_passes/src/feature_gate.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -556,6 +556,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
556556
gate_all!(const_closures, "const closures are experimental");
557557
gate_all!(builtin_syntax, "`builtin #` syntax is unstable");
558558
gate_all!(explicit_tail_calls, "`become` expression is experimental");
559+
gate_all!(generic_consts, "generic consts are experimental");
559560

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

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

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl<'a> State<'a> {
3232
}
3333
ast::ForeignItemKind::Static(ty, mutbl, body) => {
3434
let def = ast::Defaultness::Final;
35-
self.print_item_const(ident, Some(*mutbl), ty, body.as_deref(), vis, def);
35+
self.print_item_const(ident, Some(*mutbl), None, ty, body.as_deref(), vis, def);
3636
}
3737
ast::ForeignItemKind::TyAlias(box ast::TyAlias {
3838
defaultness,
@@ -67,6 +67,7 @@ impl<'a> State<'a> {
6767
&mut self,
6868
ident: Ident,
6969
mutbl: Option<ast::Mutability>,
70+
generics: Option<&ast::Generics>,
7071
ty: &ast::Ty,
7172
body: Option<&ast::Expr>,
7273
vis: &ast::Visibility,
@@ -82,6 +83,9 @@ impl<'a> State<'a> {
8283
};
8384
self.word_space(leading);
8485
self.print_ident(ident);
86+
if let Some(generics) = generics {
87+
self.print_generic_params(&generics.params);
88+
}
8589
self.word_space(":");
8690
self.print_type(ty);
8791
if body.is_some() {
@@ -92,6 +96,9 @@ impl<'a> State<'a> {
9296
self.word_space("=");
9397
self.print_expr(body);
9498
}
99+
if let Some(generics) = generics {
100+
self.print_where_clause(&generics.where_clause);
101+
}
95102
self.word(";");
96103
self.end(); // end the outer cbox
97104
}
@@ -162,16 +169,18 @@ impl<'a> State<'a> {
162169
self.print_item_const(
163170
item.ident,
164171
Some(*mutbl),
172+
None,
165173
ty,
166174
body.as_deref(),
167175
&item.vis,
168176
def,
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+
Some(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+
Some(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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 10 additions & 1 deletion
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_consts): 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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -422,6 +422,8 @@ declare_features! (
422422
(incomplete, generic_associated_types_extended, "1.61.0", Some(95451), None),
423423
/// Allows non-trivial generic constants which have to have wfness manually propagated to callers
424424
(incomplete, generic_const_exprs, "1.56.0", Some(76560), None),
425+
/// Allows generic parameters and where-clauses on free & associated const items.
426+
(incomplete, generic_consts, "CURRENT_RUSTC_VERSION", Some(113521), None),
425427
/// Allows using `..=X` as a patterns in slices.
426428
(active, half_open_range_patterns_in_slices, "1.66.0", Some(67264), None),
427429
/// Allows `if let` guard in match arms.

compiler/rustc_parse/messages.ftl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -690,6 +690,10 @@ 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+
695+
parse_static_with_where_clause = static items may not have a where clause
696+
693697
parse_struct_literal_body_without_path =
694698
struct literal body without path
695699
.suggestion = you might have forgotten to add the struct literal inside the block
@@ -847,6 +851,12 @@ parse_visibility_not_followed_by_item = visibility `{$vis}` is not followed by a
847851
.label = the visibility
848852
.help = you likely meant to define an item, e.g., `{$vis} fn foo() {"{}"}`
849853
854+
parse_where_clause_before_const_body = where clauses are not allowed before const item bodies
855+
.label = unexpected where clause
856+
.name_label = while parsing this const item
857+
.body_label = the item body
858+
.suggestion = move the body before the where clause
859+
850860
parse_where_clause_before_tuple_struct_body = where clauses are not allowed before tuple struct bodies
851861
.label = unexpected where clause
852862
.name_label = while parsing this tuple struct

compiler/rustc_parse/src/errors.rs

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2692,3 +2692,41 @@ 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_static_with_where_clause)]
2705+
pub(crate) struct StaticWithWhereClause {
2706+
#[primary_span]
2707+
pub span: Span,
2708+
}
2709+
2710+
#[derive(Diagnostic)]
2711+
#[diag(parse_where_clause_before_const_body)]
2712+
pub(crate) struct WhereClauseBeforeConstBody {
2713+
#[primary_span]
2714+
#[label]
2715+
pub span: Span,
2716+
#[label(parse_name_label)]
2717+
pub name: Span,
2718+
#[label(parse_body_label)]
2719+
pub body: Span,
2720+
#[subdiagnostic]
2721+
pub sugg: Option<WhereClauseBeforeConstBodySugg>,
2722+
}
2723+
2724+
#[derive(Subdiagnostic)]
2725+
#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
2726+
pub(crate) struct WhereClauseBeforeConstBodySugg {
2727+
#[suggestion_part(code = "= {snippet} ")]
2728+
pub left: Span,
2729+
pub snippet: String,
2730+
#[suggestion_part(code = "")]
2731+
pub right: Span,
2732+
}

0 commit comments

Comments
 (0)