Skip to content

Commit a609fb4

Browse files
committedJan 1, 2021
Auto merge of #80547 - lqd:const_generics_defaults, r=varkor
In which we start to parse const generics defaults As discussed in this [zulip topic](https://rust-lang.zulipchat.com/#narrow/stream/260443-project-const-generics/topic/const.20generic.20defaults), this PR extracts the parsing parts from `@JulianKnodt's` PR #75384 for a better user-experience using the newly stabilized `min_const_generics` (albeit temporary) as shown in #80507: trying to use default values on const generics currently results in parse errors, as if the user didn't use the correct syntax (which is somewhat true but also misleading). This PR extracts (and slightly modifies in a couple places) `@JulianKnodt's` parsing code (with attribution if I've done everything correctly), AST and HIR changes, and feature gate setup. This feature is now marked as "incomplete" and thus will also print out the expected "const generics default values are unstable" error instead of a syntax error. Note that, as I've only extracted the parsing part, the actual feature will not work at all if enabled. There will be ICEs, and inference errors on the const generics default values themselves. Fixes #80507. Once this merges, I'll: - modify the const generics tracking issue to refer to the `const_generics_defaults` gate rather than the older temporary name it uses there. - create the GH `F-const_generics_defaults` label r? `@varkor`
2 parents 18d27b2 + 942b7ce commit a609fb4

File tree

37 files changed

+160
-53
lines changed

37 files changed

+160
-53
lines changed
 

‎compiler/rustc_ast/src/ast.rs

+2
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

+2-1
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

+6-1
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

+3-2
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

+3-3
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)))
@@ -774,8 +774,8 @@ fn validate_generic_param_order(
774774
}
775775
GenericParamKind::Type { default: None } => (),
776776
GenericParamKind::Lifetime => (),
777-
// FIXME(const_generics:defaults)
778-
GenericParamKind::Const { ty: _, kw_span: _ } => (),
777+
// FIXME(const_generics_defaults)
778+
GenericParamKind::Const { ty: _, kw_span: _, default: _ } => (),
779779
}
780780
first = false;
781781
}

‎compiler/rustc_ast_passes/src/feature_gate.rs

+4
Original file line numberDiff line numberDiff line change
@@ -619,6 +619,10 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
619619
extended_key_value_attributes,
620620
"arbitrary expressions in key-value attributes are unstable"
621621
);
622+
gate_all!(
623+
const_generics_defaults,
624+
"default values for const generic parameters are experimental"
625+
);
622626
if sess.parse_sess.span_diagnostic.err_count() == 0 {
623627
// Errors for `destructuring_assignment` can get quite noisy, especially where `_` is
624628
// involved, so we only emit errors where there are no other parsing errors.

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

+6-2
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

+2-1
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

+5-1
Original file line numberDiff line numberDiff line change
@@ -581,7 +581,7 @@ declare_features! (
581581
/// Allows `if let` guard in match arms.
582582
(active, if_let_guard, "1.47.0", Some(51114), None),
583583

584-
/// Allows non-trivial generic constants which have to be manually propageted upwards.
584+
/// Allows non-trivial generic constants which have to be manually propagated upwards.
585585
(active, const_evaluatable_checked, "1.48.0", Some(76560), None),
586586

587587
/// Allows basic arithmetic on floating point types in a `const fn`.
@@ -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
// -------------------------------------------------------------------------
@@ -647,6 +650,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
647650
sym::repr128,
648651
sym::unsized_locals,
649652
sym::capture_disjoint_fields,
653+
sym::const_generics_defaults,
650654
];
651655

652656
/// Some features are not allowed to be used together at the same time, if

‎compiler/rustc_hir/src/hir.rs

+2
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

+6-1
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
}

‎compiler/rustc_hir_pretty/src/lib.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -2205,9 +2205,13 @@ impl<'a> State<'a> {
22052205
self.print_type(&default)
22062206
}
22072207
}
2208-
GenericParamKind::Const { ref ty } => {
2208+
GenericParamKind::Const { ref ty, ref default } => {
22092209
self.word_space(":");
2210-
self.print_type(ty)
2210+
self.print_type(ty);
2211+
if let Some(ref _default) = default {
2212+
// FIXME(const_generics_defaults): print the `default` value here
2213+
todo!();
2214+
}
22112215
}
22122216
}
22132217
}

‎compiler/rustc_infer/src/infer/error_reporting/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -958,7 +958,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
958958
ty::GenericParamDefKind::Type { has_default, .. } => {
959959
Some((param.def_id, has_default))
960960
}
961-
ty::GenericParamDefKind::Const => None, // FIXME(const_generics:defaults)
961+
ty::GenericParamDefKind::Const => None, // FIXME(const_generics_defaults)
962962
})
963963
.peekable();
964964
let has_default = {

‎compiler/rustc_metadata/src/rmeta/encoder.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1834,7 +1834,7 @@ impl EncodeContext<'a, 'tcx> {
18341834
EntryKind::ConstParam,
18351835
true,
18361836
);
1837-
// FIXME(const_generics:defaults)
1837+
// FIXME(const_generics_defaults)
18381838
}
18391839
}
18401840
}

‎compiler/rustc_middle/src/ty/print/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ pub trait Printer<'tcx>: Sized {
203203
self.tcx().type_of(param.def_id).subst(self.tcx(), substs),
204204
)
205205
}
206-
ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults)
206+
ty::GenericParamDefKind::Const => false, // FIXME(const_generics_defaults)
207207
}
208208
})
209209
.count();

‎compiler/rustc_parse/src/parser/generics.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use rustc_ast::{
55
self as ast, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause,
66
};
77
use rustc_errors::PResult;
8-
use rustc_span::symbol::kw;
8+
use rustc_span::symbol::{kw, sym};
99

1010
impl<'a> Parser<'a> {
1111
/// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`.
@@ -56,12 +56,26 @@ impl<'a> Parser<'a> {
5656
self.expect(&token::Colon)?;
5757
let ty = self.parse_ty()?;
5858

59+
// Parse optional const generics default value, taking care of feature gating the spans
60+
// with the unstable syntax mechanism.
61+
let default = if self.eat(&token::Eq) {
62+
// The gated span goes from the `=` to the end of the const argument that follows (and
63+
// which could be a block expression).
64+
let start = self.prev_token.span;
65+
let const_arg = self.parse_const_arg()?;
66+
let span = start.to(const_arg.value.span);
67+
self.sess.gated_spans.gate(sym::const_generics_defaults, span);
68+
Some(const_arg)
69+
} else {
70+
None
71+
};
72+
5973
Ok(GenericParam {
6074
ident,
6175
id: ast::DUMMY_NODE_ID,
6276
attrs: preceding_attrs.into(),
6377
bounds: Vec::new(),
64-
kind: GenericParamKind::Const { ty, kw_span: const_span },
78+
kind: GenericParamKind::Const { ty, kw_span: const_span, default },
6579
is_placeholder: false,
6680
})
6781
}

‎compiler/rustc_parse/src/parser/path.rs

+18-11
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,23 @@ impl<'a> Parser<'a> {
515515
}
516516
}
517517

518+
/// Parse a const argument, e.g. `<3>`. It is assumed the angle brackets will be parsed by
519+
/// the caller.
520+
pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> {
521+
// Parse const argument.
522+
let value = if let token::OpenDelim(token::Brace) = self.token.kind {
523+
self.parse_block_expr(
524+
None,
525+
self.token.span,
526+
BlockCheckMode::Default,
527+
ast::AttrVec::new(),
528+
)?
529+
} else {
530+
self.handle_unambiguous_unbraced_const_arg()?
531+
};
532+
Ok(AnonConst { id: ast::DUMMY_NODE_ID, value })
533+
}
534+
518535
/// Parse a generic argument in a path segment.
519536
/// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`.
520537
fn parse_generic_arg(&mut self) -> PResult<'a, Option<GenericArg>> {
@@ -524,17 +541,7 @@ impl<'a> Parser<'a> {
524541
GenericArg::Lifetime(self.expect_lifetime())
525542
} else if self.check_const_arg() {
526543
// Parse const argument.
527-
let value = if let token::OpenDelim(token::Brace) = self.token.kind {
528-
self.parse_block_expr(
529-
None,
530-
self.token.span,
531-
BlockCheckMode::Default,
532-
ast::AttrVec::new(),
533-
)?
534-
} else {
535-
self.handle_unambiguous_unbraced_const_arg()?
536-
};
537-
GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })
544+
GenericArg::Const(self.parse_const_arg()?)
538545
} else if self.check_type() {
539546
// Parse type argument.
540547
match self.parse_ty() {

‎compiler/rustc_passes/src/stability.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> {
443443

444444
fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) {
445445
let kind = match &p.kind {
446-
// FIXME(const_generics:defaults)
446+
// FIXME(const_generics_defaults)
447447
hir::GenericParamKind::Type { default, .. } if default.is_some() => {
448448
AnnotationKind::Container
449449
}

‎compiler/rustc_resolve/src/late.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -586,7 +586,8 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
586586
// Allow all following defaults to refer to this type parameter.
587587
default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
588588
}
589-
GenericParamKind::Const { ref ty, kw_span: _ } => {
589+
GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
590+
// FIXME(const_generics_defaults): handle `default` value here
590591
for bound in &param.bounds {
591592
self.visit_param_bound(bound);
592593
}

‎compiler/rustc_resolve/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ enum ResolutionError<'a> {
214214
/// Error E0530: `X` bindings cannot shadow `Y`s.
215215
BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>),
216216
/// Error E0128: type parameters with a default cannot use forward-declared identifiers.
217-
ForwardDeclaredTyParam, // FIXME(const_generics:defaults)
217+
ForwardDeclaredTyParam, // FIXME(const_generics_defaults)
218218
/// ERROR E0770: the type of const parameters must not depend on other generic parameters.
219219
ParamInTyOfConstParam(Symbol),
220220
/// constant values inside of type parameter defaults must not depend on generic parameters.

‎compiler/rustc_save_analysis/src/dump_visitor.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1343,9 +1343,12 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> {
13431343
self.visit_ty(ty);
13441344
}
13451345
}
1346-
hir::GenericParamKind::Const { ref ty } => {
1346+
hir::GenericParamKind::Const { ref ty, ref default } => {
13471347
self.process_bounds(param.bounds);
13481348
self.visit_ty(ty);
1349+
if let Some(default) = default {
1350+
self.visit_anon_const(default);
1351+
}
13491352
}
13501353
}
13511354
}

‎compiler/rustc_save_analysis/src/sig.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -614,9 +614,13 @@ impl<'hir> Sig for hir::Generics<'hir> {
614614
start: offset + text.len(),
615615
end: offset + text.len() + param_text.as_str().len(),
616616
});
617-
if let hir::GenericParamKind::Const { ref ty } = param.kind {
617+
if let hir::GenericParamKind::Const { ref ty, ref default } = param.kind {
618618
param_text.push_str(": ");
619619
param_text.push_str(&ty_to_string(&ty));
620+
if let Some(ref _default) = default {
621+
// FIXME(const_generics_defaults): push the `default` value here
622+
todo!();
623+
}
620624
}
621625
if !param.bounds.is_empty() {
622626
param_text.push_str(": ");

‎compiler/rustc_span/src/symbol.rs

+1
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ symbols! {
368368
const_fn_transmute,
369369
const_fn_union,
370370
const_generics,
371+
const_generics_defaults,
371372
const_if_match,
372373
const_impl_trait,
373374
const_in_array_repeat_expressions,

‎compiler/rustc_typeck/src/astconv/generics.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -387,7 +387,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
387387
defaults.types += has_default as usize
388388
}
389389
GenericParamDefKind::Const => {
390-
// FIXME(const_generics:defaults)
390+
// FIXME(const_generics_defaults)
391391
}
392392
};
393393
}

‎compiler/rustc_typeck/src/astconv/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -486,7 +486,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
486486
}
487487
GenericParamDefKind::Const => {
488488
let ty = tcx.at(self.span).type_of(param.def_id);
489-
// FIXME(const_generics:defaults)
489+
// FIXME(const_generics_defaults)
490490
if infer_args {
491491
// No const parameters were provided, we can infer all.
492492
self.astconv.ct_infer(ty, Some(param), self.span).into()

‎compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -1376,7 +1376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
13761376
}
13771377
}
13781378
GenericParamDefKind::Const => {
1379-
// FIXME(const_generics:defaults)
1379+
// FIXME(const_generics_defaults)
13801380
// No const parameters were provided, we have to infer them.
13811381
self.fcx.var_for_def(self.span, param)
13821382
}

‎compiler/rustc_typeck/src/check/wfcheck.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,9 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) {
286286
// We currently only check wf of const params here.
287287
hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => (),
288288

289-
// Const parameters are well formed if their
290-
// type is structural match.
291-
hir::GenericParamKind::Const { ty: hir_ty } => {
289+
// Const parameters are well formed if their type is structural match.
290+
// FIXME(const_generics_defaults): we also need to check that the `default` is wf.
291+
hir::GenericParamKind::Const { ty: hir_ty, default: _ } => {
292292
let ty = tcx.type_of(tcx.hir().local_def_id(param.hir_id));
293293

294294
let err_ty_str;
@@ -785,7 +785,7 @@ fn check_where_clauses<'tcx, 'fcx>(
785785
}
786786

787787
GenericParamDefKind::Const => {
788-
// FIXME(const_generics:defaults)
788+
// FIXME(const_generics_defaults)
789789
fcx.tcx.mk_param_from_def(param)
790790
}
791791
}

0 commit comments

Comments
 (0)
Please sign in to comment.