Skip to content

Commit 61f33bf

Browse files
JulianKnodtlqd
authored andcommitted
first pass at default values for const generics
- Adds optional default values to const generic parameters in the AST and HIR - Parses these optional default values - Adds a `const_generics_defaults` feature gate
1 parent f8ab56b commit 61f33bf

File tree

20 files changed

+99
-32
lines changed

20 files changed

+99
-32
lines changed

compiler/rustc_ast/src/ast.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,8 @@ pub enum GenericParamKind {
368368
ty: P<Ty>,
369369
/// Span of the `const` keyword.
370370
kw_span: Span,
371+
/// Optional default value for the const generic param
372+
default: Option<AnonConst>,
371373
},
372374
}
373375

compiler/rustc_ast/src/mut_visit.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -790,8 +790,9 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
790790
GenericParamKind::Type { default } => {
791791
visit_opt(default, |default| vis.visit_ty(default));
792792
}
793-
GenericParamKind::Const { ty, kw_span: _ } => {
793+
GenericParamKind::Const { ty, kw_span: _, default } => {
794794
vis.visit_ty(ty);
795+
visit_opt(default, |default| vis.visit_anon_const(default));
795796
}
796797
}
797798
smallvec![param]

compiler/rustc_ast/src/visit.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -578,7 +578,12 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Generi
578578
match param.kind {
579579
GenericParamKind::Lifetime => (),
580580
GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default),
581-
GenericParamKind::Const { ref ty, .. } => visitor.visit_ty(ty),
581+
GenericParamKind::Const { ref ty, ref default, .. } => {
582+
visitor.visit_ty(ty);
583+
if let Some(default) = default {
584+
visitor.visit_anon_const(default);
585+
}
586+
}
582587
}
583588
}
584589

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2242,13 +2242,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
22422242

22432243
(hir::ParamName::Plain(param.ident), kind)
22442244
}
2245-
GenericParamKind::Const { ref ty, kw_span: _ } => {
2245+
GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
22462246
let ty = self
22472247
.with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| {
22482248
this.lower_ty(&ty, ImplTraitContext::disallowed())
22492249
});
2250+
let default = default.as_ref().map(|def| self.lower_anon_const(def));
22502251

2251-
(hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty })
2252+
(hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty, default })
22522253
}
22532254
};
22542255

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -733,7 +733,7 @@ fn validate_generic_param_order(
733733
let (ord_kind, ident) = match &param.kind {
734734
GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident),
735735
GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
736-
GenericParamKind::Const { ref ty, kw_span: _ } => {
736+
GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
737737
let ty = pprust::ty_to_string(ty);
738738
let unordered = sess.features_untracked().const_generics;
739739
(ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty)))
@@ -775,7 +775,7 @@ fn validate_generic_param_order(
775775
GenericParamKind::Type { default: None } => (),
776776
GenericParamKind::Lifetime => (),
777777
// FIXME(const_generics:defaults)
778-
GenericParamKind::Const { ty: _, kw_span: _ } => (),
778+
GenericParamKind::Const { ty: _, kw_span: _, default: _ } => (),
779779
}
780780
first = false;
781781
}
@@ -1166,6 +1166,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11661166
}
11671167
}
11681168
}
1169+
if !self.session.features_untracked().const_generics_defaults {
1170+
if let GenericParamKind::Const { default: Some(ref default), .. } = param.kind {
1171+
let mut err = self.err_handler().struct_span_err(
1172+
default.value.span,
1173+
"default values for const generic parameters are unstable",
1174+
);
1175+
err.help(
1176+
"add `#![feature(const_generics_defaults)]` \
1177+
to the crate attributes to enable",
1178+
);
1179+
err.emit();
1180+
break;
1181+
}
1182+
}
11691183
}
11701184

11711185
validate_generic_param_order(

compiler/rustc_ast_pretty/src/pprust/state.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2668,13 +2668,17 @@ impl<'a> State<'a> {
26682668
s.print_type(default)
26692669
}
26702670
}
2671-
ast::GenericParamKind::Const { ref ty, kw_span: _ } => {
2671+
ast::GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
26722672
s.word_space("const");
26732673
s.print_ident(param.ident);
26742674
s.s.space();
26752675
s.word_space(":");
26762676
s.print_type(ty);
2677-
s.print_type_bounds(":", &param.bounds)
2677+
s.print_type_bounds(":", &param.bounds);
2678+
if let Some(ref _default) = default {
2679+
// FIXME(const_generics_defaults): print the `default` value here
2680+
todo!();
2681+
}
26782682
}
26792683
}
26802684
});

compiler/rustc_builtin_macros/src/deriving/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ fn inject_impl_of_structural_trait(
145145
*default = None;
146146
ast::GenericArg::Type(cx.ty_ident(span, param.ident))
147147
}
148-
ast::GenericParamKind::Const { ty: _, kw_span: _ } => {
148+
ast::GenericParamKind::Const { ty: _, kw_span: _, default } => {
149+
*default = None;
149150
ast::GenericArg::Const(cx.const_ident(span, param.ident))
150151
}
151152
})

compiler/rustc_feature/src/active.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,9 @@ declare_features! (
623623
/// `:pat2018` and `:pat2021` macro matchers.
624624
(active, edition_macro_pats, "1.51.0", Some(54883), None),
625625

626+
/// Allows const generics to have default values (e.g. `struct Foo<const N: usize = 3>(...);`).
627+
(active, const_generics_defaults, "1.51.0", Some(44580), None),
628+
626629
// -------------------------------------------------------------------------
627630
// feature-group-end: actual feature gates
628631
// -------------------------------------------------------------------------

compiler/rustc_hir/src/hir.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,8 @@ pub enum GenericParamKind<'hir> {
418418
},
419419
Const {
420420
ty: &'hir Ty<'hir>,
421+
/// Optional default value for the const generic param
422+
default: Option<AnonConst>,
421423
},
422424
}
423425

compiler/rustc_hir/src/intravisit.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -877,7 +877,12 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi
877877
match param.kind {
878878
GenericParamKind::Lifetime { .. } => {}
879879
GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default),
880-
GenericParamKind::Const { ref ty } => visitor.visit_ty(ty),
880+
GenericParamKind::Const { ref ty, ref default } => {
881+
visitor.visit_ty(ty);
882+
if let Some(ref default) = default {
883+
visitor.visit_anon_const(default);
884+
}
885+
}
881886
}
882887
walk_list!(visitor, visit_param_bound, param.bounds);
883888
}

0 commit comments

Comments
 (0)