From 61f33bfd2940ea55559b253a66c42937a17d3c87 Mon Sep 17 00:00:00 2001 From: Julian Knodt Date: Thu, 31 Dec 2020 01:58:27 +0100 Subject: [PATCH 1/7] 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 --- compiler/rustc_ast/src/ast.rs | 2 ++ compiler/rustc_ast/src/mut_visit.rs | 3 +- compiler/rustc_ast/src/visit.rs | 7 ++++- compiler/rustc_ast_lowering/src/lib.rs | 5 ++-- .../rustc_ast_passes/src/ast_validation.rs | 18 ++++++++++-- compiler/rustc_ast_pretty/src/pprust/state.rs | 8 +++-- .../rustc_builtin_macros/src/deriving/mod.rs | 3 +- compiler/rustc_feature/src/active.rs | 3 ++ compiler/rustc_hir/src/hir.rs | 2 ++ compiler/rustc_hir/src/intravisit.rs | 7 ++++- compiler/rustc_hir_pretty/src/lib.rs | 8 +++-- compiler/rustc_parse/src/parser/generics.rs | 5 +++- compiler/rustc_parse/src/parser/path.rs | 29 ++++++++++++------- compiler/rustc_resolve/src/late.rs | 3 +- .../rustc_save_analysis/src/dump_visitor.rs | 5 +++- compiler/rustc_save_analysis/src/sig.rs | 6 +++- compiler/rustc_span/src/symbol.rs | 1 + compiler/rustc_typeck/src/check/wfcheck.rs | 6 ++-- src/librustdoc/clean/mod.rs | 3 +- .../clippy_lints/src/utils/ast_utils.rs | 7 ++++- 20 files changed, 99 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index cf31e566c384e..8167bde0322f2 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -368,6 +368,8 @@ pub enum GenericParamKind { ty: P, /// Span of the `const` keyword. kw_span: Span, + /// Optional default value for the const generic param + default: Option, }, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 3889ede7f4c21..97966cc326055 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -790,8 +790,9 @@ pub fn noop_flat_map_generic_param( GenericParamKind::Type { default } => { visit_opt(default, |default| vis.visit_ty(default)); } - GenericParamKind::Const { ty, kw_span: _ } => { + GenericParamKind::Const { ty, kw_span: _, default } => { vis.visit_ty(ty); + visit_opt(default, |default| vis.visit_anon_const(default)); } } smallvec![param] diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index a420bb56350c6..a696626f8c419 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -578,7 +578,12 @@ pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a Generi match param.kind { GenericParamKind::Lifetime => (), GenericParamKind::Type { ref default } => walk_list!(visitor, visit_ty, default), - GenericParamKind::Const { ref ty, .. } => visitor.visit_ty(ty), + GenericParamKind::Const { ref ty, ref default, .. } => { + visitor.visit_ty(ty); + if let Some(default) = default { + visitor.visit_anon_const(default); + } + } } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d17b29089d694..f81dc39842cb9 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2242,13 +2242,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { (hir::ParamName::Plain(param.ident), kind) } - GenericParamKind::Const { ref ty, kw_span: _ } => { + GenericParamKind::Const { ref ty, kw_span: _, ref default } => { let ty = self .with_anonymous_lifetime_mode(AnonymousLifetimeMode::ReportError, |this| { this.lower_ty(&ty, ImplTraitContext::disallowed()) }); + let default = default.as_ref().map(|def| self.lower_anon_const(def)); - (hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty }) + (hir::ParamName::Plain(param.ident), hir::GenericParamKind::Const { ty, default }) } }; diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index c40f00bc9e99b..fd080fa59921c 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -733,7 +733,7 @@ fn validate_generic_param_order( let (ord_kind, ident) = match ¶m.kind { GenericParamKind::Lifetime => (ParamKindOrd::Lifetime, ident), GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident), - GenericParamKind::Const { ref ty, kw_span: _ } => { + GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { let ty = pprust::ty_to_string(ty); let unordered = sess.features_untracked().const_generics; (ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty))) @@ -775,7 +775,7 @@ fn validate_generic_param_order( GenericParamKind::Type { default: None } => (), GenericParamKind::Lifetime => (), // FIXME(const_generics:defaults) - GenericParamKind::Const { ty: _, kw_span: _ } => (), + GenericParamKind::Const { ty: _, kw_span: _, default: _ } => (), } first = false; } @@ -1166,6 +1166,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } } + if !self.session.features_untracked().const_generics_defaults { + if let GenericParamKind::Const { default: Some(ref default), .. } = param.kind { + let mut err = self.err_handler().struct_span_err( + default.value.span, + "default values for const generic parameters are unstable", + ); + err.help( + "add `#![feature(const_generics_defaults)]` \ + to the crate attributes to enable", + ); + err.emit(); + break; + } + } } validate_generic_param_order( diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 333a396a0b4fc..bdd378b34e144 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -2668,13 +2668,17 @@ impl<'a> State<'a> { s.print_type(default) } } - ast::GenericParamKind::Const { ref ty, kw_span: _ } => { + ast::GenericParamKind::Const { ref ty, kw_span: _, ref default } => { s.word_space("const"); s.print_ident(param.ident); s.s.space(); s.word_space(":"); s.print_type(ty); - s.print_type_bounds(":", ¶m.bounds) + s.print_type_bounds(":", ¶m.bounds); + if let Some(ref _default) = default { + // FIXME(const_generics_defaults): print the `default` value here + todo!(); + } } } }); diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 1651180817b9d..3c8bf12b3d415 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -145,7 +145,8 @@ fn inject_impl_of_structural_trait( *default = None; ast::GenericArg::Type(cx.ty_ident(span, param.ident)) } - ast::GenericParamKind::Const { ty: _, kw_span: _ } => { + ast::GenericParamKind::Const { ty: _, kw_span: _, default } => { + *default = None; ast::GenericArg::Const(cx.const_ident(span, param.ident)) } }) diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index c61857a1cd0ae..70213f346f68c 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -623,6 +623,9 @@ declare_features! ( /// `:pat2018` and `:pat2021` macro matchers. (active, edition_macro_pats, "1.51.0", Some(54883), None), + /// Allows const generics to have default values (e.g. `struct Foo(...);`). + (active, const_generics_defaults, "1.51.0", Some(44580), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 47a7651e1d414..ebeb1bae2a314 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -418,6 +418,8 @@ pub enum GenericParamKind<'hir> { }, Const { ty: &'hir Ty<'hir>, + /// Optional default value for the const generic param + default: Option, }, } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 03c8b1738853d..87a2434152fcf 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -877,7 +877,12 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi match param.kind { GenericParamKind::Lifetime { .. } => {} GenericParamKind::Type { ref default, .. } => walk_list!(visitor, visit_ty, default), - GenericParamKind::Const { ref ty } => visitor.visit_ty(ty), + GenericParamKind::Const { ref ty, ref default } => { + visitor.visit_ty(ty); + if let Some(ref default) = default { + visitor.visit_anon_const(default); + } + } } walk_list!(visitor, visit_param_bound, param.bounds); } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 0b5eb1d82667d..85bc38daa3d28 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2205,9 +2205,13 @@ impl<'a> State<'a> { self.print_type(&default) } } - GenericParamKind::Const { ref ty } => { + GenericParamKind::Const { ref ty, ref default } => { self.word_space(":"); - self.print_type(ty) + self.print_type(ty); + if let Some(ref _default) = default { + // FIXME(const_generics_defaults): print the `default` value here + todo!(); + } } } } diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 860e63020bb06..ff84dba417728 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -56,12 +56,15 @@ impl<'a> Parser<'a> { self.expect(&token::Colon)?; let ty = self.parse_ty()?; + // Parse optional const generics default value. + let default = if self.eat(&token::Eq) { Some(self.parse_const_arg()?) } else { None }; + Ok(GenericParam { ident, id: ast::DUMMY_NODE_ID, attrs: preceding_attrs.into(), bounds: Vec::new(), - kind: GenericParamKind::Const { ty, kw_span: const_span }, + kind: GenericParamKind::Const { ty, kw_span: const_span, default }, is_placeholder: false, }) } diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 60a47ca12b868..43dee391c171a 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -515,6 +515,23 @@ impl<'a> Parser<'a> { } } + /// Parse a const argument, e.g. `<3>`. It is assumed the angle brackets will be parsed by + /// the caller. + pub(super) fn parse_const_arg(&mut self) -> PResult<'a, AnonConst> { + // Parse const argument. + let value = if let token::OpenDelim(token::Brace) = self.token.kind { + self.parse_block_expr( + None, + self.token.span, + BlockCheckMode::Default, + ast::AttrVec::new(), + )? + } else { + self.handle_unambiguous_unbraced_const_arg()? + }; + Ok(AnonConst { id: ast::DUMMY_NODE_ID, value }) + } + /// Parse a generic argument in a path segment. /// This does not include constraints, e.g., `Item = u8`, which is handled in `parse_angle_arg`. fn parse_generic_arg(&mut self) -> PResult<'a, Option> { @@ -524,17 +541,7 @@ impl<'a> Parser<'a> { GenericArg::Lifetime(self.expect_lifetime()) } else if self.check_const_arg() { // Parse const argument. - let value = if let token::OpenDelim(token::Brace) = self.token.kind { - self.parse_block_expr( - None, - self.token.span, - BlockCheckMode::Default, - ast::AttrVec::new(), - )? - } else { - self.handle_unambiguous_unbraced_const_arg()? - }; - GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }) + GenericArg::Const(self.parse_const_arg()?) } else if self.check_type() { // Parse type argument. match self.parse_ty() { diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index dd1874debbd96..fbe99a3115054 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -586,7 +586,8 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // Allow all following defaults to refer to this type parameter. default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name)); } - GenericParamKind::Const { ref ty, kw_span: _ } => { + GenericParamKind::Const { ref ty, kw_span: _, default: _ } => { + // FIXME(const_generics_defaults): handle `default` value here for bound in ¶m.bounds { self.visit_param_bound(bound); } diff --git a/compiler/rustc_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 40d60a8394be3..987badcedde4c 100644 --- a/compiler/rustc_save_analysis/src/dump_visitor.rs +++ b/compiler/rustc_save_analysis/src/dump_visitor.rs @@ -1343,9 +1343,12 @@ impl<'tcx> Visitor<'tcx> for DumpVisitor<'tcx> { self.visit_ty(ty); } } - hir::GenericParamKind::Const { ref ty } => { + hir::GenericParamKind::Const { ref ty, ref default } => { self.process_bounds(param.bounds); self.visit_ty(ty); + if let Some(default) = default { + self.visit_anon_const(default); + } } } } diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index ff445d727fa34..e7d1c9d3bbe58 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -614,9 +614,13 @@ impl<'hir> Sig for hir::Generics<'hir> { start: offset + text.len(), end: offset + text.len() + param_text.as_str().len(), }); - if let hir::GenericParamKind::Const { ref ty } = param.kind { + if let hir::GenericParamKind::Const { ref ty, ref default } = param.kind { param_text.push_str(": "); param_text.push_str(&ty_to_string(&ty)); + if let Some(ref _default) = default { + // FIXME(const_generics_defaults): push the `default` value here + todo!(); + } } if !param.bounds.is_empty() { param_text.push_str(": "); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b040a70437d9e..64b50a9b70a70 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -368,6 +368,7 @@ symbols! { const_fn_transmute, const_fn_union, const_generics, + const_generics_defaults, const_if_match, const_impl_trait, const_in_array_repeat_expressions, diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 2ae9ded3fa0cf..18c63cb433da1 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -286,9 +286,9 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &hir::GenericParam<'_>) { // We currently only check wf of const params here. hir::GenericParamKind::Lifetime { .. } | hir::GenericParamKind::Type { .. } => (), - // Const parameters are well formed if their - // type is structural match. - hir::GenericParamKind::Const { ty: hir_ty } => { + // Const parameters are well formed if their type is structural match. + // FIXME(const_generics_defaults): we also need to check that the `default` is wf. + hir::GenericParamKind::Const { ty: hir_ty, default: _ } => { let ty = tcx.type_of(tcx.hir().local_def_id(param.hir_id)); let err_ty_str; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index f4eb1924e6f7e..022161164d1e5 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -607,11 +607,12 @@ impl Clean for hir::GenericParam<'_> { synthetic, }, ), - hir::GenericParamKind::Const { ref ty } => ( + hir::GenericParamKind::Const { ref ty, default: _ } => ( self.name.ident().name, GenericParamDefKind::Const { did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(), ty: ty.clean(cx), + // FIXME(const_generics_defaults): add `default` field here to the docs }, ), }; diff --git a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs index f0267e4c79289..940573e4caa69 100644 --- a/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs +++ b/src/tools/clippy/clippy_lints/src/utils/ast_utils.rs @@ -407,6 +407,10 @@ pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool { } } +pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool { + eq_expr(&l.value, &r.value) +} + pub fn eq_defaultness(l: Defaultness, r: Defaultness) -> bool { matches!( (l, r), @@ -497,7 +501,8 @@ pub fn eq_generic_param(l: &GenericParam, r: &GenericParam) -> bool { && match (&l.kind, &r.kind) { (Lifetime, Lifetime) => true, (Type { default: l }, Type { default: r }) => both(l, r, |l, r| eq_ty(l, r)), - (Const { ty: l, kw_span: _ }, Const { ty: r, kw_span: _ }) => eq_ty(l, r), + (Const { ty: lt, kw_span: _ , default: ld}, Const { ty: rt, kw_span: _, default: rd }) => + eq_ty(lt, rt) && both(ld, rd, |ld, rd| eq_anon_const(ld, rd)), _ => false, } && over(&l.attrs, &r.attrs, |l, r| eq_attr(l, r)) From 5f4bb468c1750ade685d168e25cc876bb6d73f8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 31 Dec 2020 02:01:57 +0100 Subject: [PATCH 2/7] fix typo in feature gates file --- compiler/rustc_feature/src/active.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 70213f346f68c..6d8443a75e70f 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -581,7 +581,7 @@ declare_features! ( /// Allows `if let` guard in match arms. (active, if_let_guard, "1.47.0", Some(51114), None), - /// Allows non-trivial generic constants which have to be manually propageted upwards. + /// Allows non-trivial generic constants which have to be manually propagated upwards. (active, const_evaluatable_checked, "1.48.0", Some(76560), None), /// Allows basic arithmetic on floating point types in a `const fn`. From ea8fa36bb47f77bf0e339cc4f8b00f183d913f3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 31 Dec 2020 02:02:49 +0100 Subject: [PATCH 3/7] mark `const_generics_defaults` as an incomplete feature --- compiler/rustc_feature/src/active.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs index 6d8443a75e70f..252e96b47c664 100644 --- a/compiler/rustc_feature/src/active.rs +++ b/compiler/rustc_feature/src/active.rs @@ -650,6 +650,7 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[ sym::repr128, sym::unsized_locals, sym::capture_disjoint_fields, + sym::const_generics_defaults, ]; /// Some features are not allowed to be used together at the same time, if From 64244b22014995cffb41c231953b7c9e0b0bdb66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 31 Dec 2020 02:03:15 +0100 Subject: [PATCH 4/7] add test for the `const_generics_defaults` feature gate --- .../feature-gate-const_generics_defaults.rs | 7 +++++++ ...feature-gate-const_generics_defaults.stderr | 18 ++++++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 src/test/ui/feature-gates/feature-gate-const_generics_defaults.rs create mode 100644 src/test/ui/feature-gates/feature-gate-const_generics_defaults.stderr diff --git a/src/test/ui/feature-gates/feature-gate-const_generics_defaults.rs b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.rs new file mode 100644 index 0000000000000..90959e7a3656e --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.rs @@ -0,0 +1,7 @@ +struct A; +//~^ ERROR default values for const generic parameters are unstable + +fn foo() {} +//~^ ERROR default values for const generic parameters are unstable + +fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_generics_defaults.stderr b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.stderr new file mode 100644 index 0000000000000..00d564772d2bc --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.stderr @@ -0,0 +1,18 @@ +error: default values for const generic parameters are unstable + --> $DIR/feature-gate-const_generics_defaults.rs:1:27 + | +LL | struct A; + | ^ + | + = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable + +error: default values for const generic parameters are unstable + --> $DIR/feature-gate-const_generics_defaults.rs:4:22 + | +LL | fn foo() {} + | ^ + | + = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable + +error: aborting due to 2 previous errors + From 907ba75eb0b063c1da72703642e5710b91868dc8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 31 Dec 2020 02:04:52 +0100 Subject: [PATCH 5/7] update `min_const_generics` tests using default values for const params The `const_generics_defaults` now handles them, and they correctly parse, so we can update these tests expecting a parser error . --- .../min_const_generics/default_function_param.rs | 2 +- .../min_const_generics/default_function_param.stderr | 8 +++++--- .../min_const_generics/default_trait_param.rs | 2 +- .../min_const_generics/default_trait_param.stderr | 8 +++++--- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/src/test/ui/const-generics/min_const_generics/default_function_param.rs b/src/test/ui/const-generics/min_const_generics/default_function_param.rs index d7918a73ab8b3..425c5eb9e7c5f 100644 --- a/src/test/ui/const-generics/min_const_generics/default_function_param.rs +++ b/src/test/ui/const-generics/min_const_generics/default_function_param.rs @@ -1,4 +1,4 @@ fn foo() {} - //~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` +//~^ ERROR default values for const generic parameters are unstable fn main() {} diff --git a/src/test/ui/const-generics/min_const_generics/default_function_param.stderr b/src/test/ui/const-generics/min_const_generics/default_function_param.stderr index 8eb796d9bb7a8..3d2fac78d7c2c 100644 --- a/src/test/ui/const-generics/min_const_generics/default_function_param.stderr +++ b/src/test/ui/const-generics/min_const_generics/default_function_param.stderr @@ -1,8 +1,10 @@ -error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` - --> $DIR/default_function_param.rs:1:26 +error: default values for const generic parameters are unstable + --> $DIR/default_function_param.rs:1:28 | LL | fn foo() {} - | ^ expected one of 7 possible tokens + | ^ + | + = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable error: aborting due to previous error diff --git a/src/test/ui/const-generics/min_const_generics/default_trait_param.rs b/src/test/ui/const-generics/min_const_generics/default_trait_param.rs index c8003ad5d44d8..c6d91ef97a020 100644 --- a/src/test/ui/const-generics/min_const_generics/default_trait_param.rs +++ b/src/test/ui/const-generics/min_const_generics/default_trait_param.rs @@ -1,4 +1,4 @@ trait Foo {} - //~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` +//~^ ERROR default values for const generic parameters are unstable fn main() {} diff --git a/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr b/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr index 6d112ef1de033..b727fdd807b66 100644 --- a/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr +++ b/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr @@ -1,8 +1,10 @@ -error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` - --> $DIR/default_trait_param.rs:1:28 +error: default values for const generic parameters are unstable + --> $DIR/default_trait_param.rs:1:30 | LL | trait Foo {} - | ^ expected one of 7 possible tokens + | ^^^^ + | + = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable error: aborting due to previous error From 1fc3c4c16dde2a6cb4f565435d131b8c57bc1295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 31 Dec 2020 02:50:23 +0100 Subject: [PATCH 6/7] adjust const generics defaults FIXMEs to the new feature gate --- compiler/rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_infer/src/infer/error_reporting/mod.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 2 +- compiler/rustc_middle/src/ty/print/mod.rs | 2 +- compiler/rustc_passes/src/stability.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_typeck/src/astconv/generics.rs | 2 +- compiler/rustc_typeck/src/astconv/mod.rs | 2 +- compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 2 +- compiler/rustc_typeck/src/check/wfcheck.rs | 2 +- compiler/rustc_typeck/src/collect.rs | 2 +- src/librustdoc/clean/mod.rs | 4 ++-- .../ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs | 2 +- 13 files changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index fd080fa59921c..6ac212af68e80 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -774,7 +774,7 @@ fn validate_generic_param_order( } GenericParamKind::Type { default: None } => (), GenericParamKind::Lifetime => (), - // FIXME(const_generics:defaults) + // FIXME(const_generics_defaults) GenericParamKind::Const { ty: _, kw_span: _, default: _ } => (), } first = false; diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 777107ed86310..14a56119f21e3 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -958,7 +958,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ty::GenericParamDefKind::Type { has_default, .. } => { Some((param.def_id, has_default)) } - ty::GenericParamDefKind::Const => None, // FIXME(const_generics:defaults) + ty::GenericParamDefKind::Const => None, // FIXME(const_generics_defaults) }) .peekable(); let has_default = { diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 4dfe3e8487762..ac6ceafaba8c7 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1834,7 +1834,7 @@ impl EncodeContext<'a, 'tcx> { EntryKind::ConstParam, true, ); - // FIXME(const_generics:defaults) + // FIXME(const_generics_defaults) } } } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index c79e06b7fdd32..77f1668893782 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -203,7 +203,7 @@ pub trait Printer<'tcx>: Sized { self.tcx().type_of(param.def_id).subst(self.tcx(), substs), ) } - ty::GenericParamDefKind::Const => false, // FIXME(const_generics:defaults) + ty::GenericParamDefKind::Const => false, // FIXME(const_generics_defaults) } }) .count(); diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 3c2462aab26b7..def2a501cf475 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -443,7 +443,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Annotator<'a, 'tcx> { fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { let kind = match &p.kind { - // FIXME(const_generics:defaults) + // FIXME(const_generics_defaults) hir::GenericParamKind::Type { default, .. } if default.is_some() => { AnnotationKind::Container } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ca30d90e6ad1d..0de732b2cf97e 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -214,7 +214,7 @@ enum ResolutionError<'a> { /// Error E0530: `X` bindings cannot shadow `Y`s. BindingShadowsSomethingUnacceptable(&'static str, Symbol, &'a NameBinding<'a>), /// Error E0128: type parameters with a default cannot use forward-declared identifiers. - ForwardDeclaredTyParam, // FIXME(const_generics:defaults) + ForwardDeclaredTyParam, // FIXME(const_generics_defaults) /// ERROR E0770: the type of const parameters must not depend on other generic parameters. ParamInTyOfConstParam(Symbol), /// constant values inside of type parameter defaults must not depend on generic parameters. diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 0feac036f0026..a3a2b8967c606 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -387,7 +387,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { defaults.types += has_default as usize } GenericParamDefKind::Const => { - // FIXME(const_generics:defaults) + // FIXME(const_generics_defaults) } }; } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 38d33e5586644..9a2210e4f0e80 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -486,7 +486,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } GenericParamDefKind::Const => { let ty = tcx.at(self.span).type_of(param.def_id); - // FIXME(const_generics:defaults) + // FIXME(const_generics_defaults) if infer_args { // No const parameters were provided, we can infer all. self.astconv.ct_infer(ty, Some(param), self.span).into() diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 2a8b77da44fc4..7126b62405968 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1376,7 +1376,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } GenericParamDefKind::Const => { - // FIXME(const_generics:defaults) + // FIXME(const_generics_defaults) // No const parameters were provided, we have to infer them. self.fcx.var_for_def(self.span, param) } diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 18c63cb433da1..ab41ff372e23f 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -785,7 +785,7 @@ fn check_where_clauses<'tcx, 'fcx>( } GenericParamDefKind::Const => { - // FIXME(const_generics:defaults) + // FIXME(const_generics_defaults) fcx.tcx.mk_param_from_def(param) } } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 3e40f5ba28a7e..2ebb1a3be4e44 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -228,7 +228,7 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { hir::GenericParamKind::Const { .. } => { let def_id = self.tcx.hir().local_def_id(param.hir_id); self.tcx.ensure().type_of(def_id); - // FIXME(const_generics:defaults) + // FIXME(const_generics_defaults) } } } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 022161164d1e5..2f430842f9d8e 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -612,7 +612,7 @@ impl Clean for hir::GenericParam<'_> { GenericParamDefKind::Const { did: cx.tcx.hir().local_def_id(self.hir_id).to_def_id(), ty: ty.clean(cx), - // FIXME(const_generics_defaults): add `default` field here to the docs + // FIXME(const_generics_defaults): add `default` field here for docs }, ), }; @@ -1386,7 +1386,7 @@ fn clean_qpath(hir_ty: &hir::Ty<'_>, cx: &DocContext<'_>) -> Type { if let Some(ct) = const_ { ct_substs.insert(const_param_def_id.to_def_id(), ct.clean(cx)); } - // FIXME(const_generics:defaults) + // FIXME(const_generics_defaults) indices.consts += 1; } } diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs index 845c6111b5968..a85e2a2f2c4f1 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs @@ -7,7 +7,7 @@ struct Foo()]>(T, U); //[full]~^ ERROR constant values inside of type parameter defaults //[min]~^^ ERROR generic parameters may not be used in const operations -// FIXME(const_generics:defaults): We still don't know how to we deal with type defaults. +// FIXME(const_generics_defaults): We still don't know how to deal with type defaults. struct Bar(T); //~^ ERROR constant values inside of type parameter defaults //~| ERROR type parameters with a default From 942b7ce2c14b1c4fde5b9f27aa5bef39e0b990d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 31 Dec 2020 18:32:06 +0100 Subject: [PATCH 7/7] make `const_generics_defaults` use the unstable syntax mechanism This is important to not accidentally stabilize the parsing of the syntax while it still is experimental and not formally accepted --- compiler/rustc_ast_passes/src/ast_validation.rs | 14 -------------- compiler/rustc_ast_passes/src/feature_gate.rs | 4 ++++ compiler/rustc_parse/src/parser/generics.rs | 17 ++++++++++++++--- .../default_function_param.rs | 2 +- .../default_function_param.stderr | 8 +++++--- .../min_const_generics/default_trait_param.rs | 2 +- .../default_trait_param.stderr | 8 +++++--- .../feature-gate-const_generics_defaults.rs | 8 +++++--- .../feature-gate-const_generics_defaults.stderr | 17 ++++++++++------- 9 files changed, 45 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 6ac212af68e80..e172f9d71ffbc 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1166,20 +1166,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } } - if !self.session.features_untracked().const_generics_defaults { - if let GenericParamKind::Const { default: Some(ref default), .. } = param.kind { - let mut err = self.err_handler().struct_span_err( - default.value.span, - "default values for const generic parameters are unstable", - ); - err.help( - "add `#![feature(const_generics_defaults)]` \ - to the crate attributes to enable", - ); - err.emit(); - break; - } - } } validate_generic_param_order( diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 6a9d6d2ed121e..435f32535b6d4 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -619,6 +619,10 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) { extended_key_value_attributes, "arbitrary expressions in key-value attributes are unstable" ); + gate_all!( + const_generics_defaults, + "default values for const generic parameters are experimental" + ); if sess.parse_sess.span_diagnostic.err_count() == 0 { // Errors for `destructuring_assignment` can get quite noisy, especially where `_` is // involved, so we only emit errors where there are no other parsing errors. diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index ff84dba417728..42a1337686321 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -5,7 +5,7 @@ use rustc_ast::{ self as ast, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause, }; use rustc_errors::PResult; -use rustc_span::symbol::kw; +use rustc_span::symbol::{kw, sym}; impl<'a> Parser<'a> { /// Parses bounds of a lifetime parameter `BOUND + BOUND + BOUND`, possibly with trailing `+`. @@ -56,8 +56,19 @@ impl<'a> Parser<'a> { self.expect(&token::Colon)?; let ty = self.parse_ty()?; - // Parse optional const generics default value. - let default = if self.eat(&token::Eq) { Some(self.parse_const_arg()?) } else { None }; + // Parse optional const generics default value, taking care of feature gating the spans + // with the unstable syntax mechanism. + let default = if self.eat(&token::Eq) { + // The gated span goes from the `=` to the end of the const argument that follows (and + // which could be a block expression). + let start = self.prev_token.span; + let const_arg = self.parse_const_arg()?; + let span = start.to(const_arg.value.span); + self.sess.gated_spans.gate(sym::const_generics_defaults, span); + Some(const_arg) + } else { + None + }; Ok(GenericParam { ident, diff --git a/src/test/ui/const-generics/min_const_generics/default_function_param.rs b/src/test/ui/const-generics/min_const_generics/default_function_param.rs index 425c5eb9e7c5f..5b0a42a45565c 100644 --- a/src/test/ui/const-generics/min_const_generics/default_function_param.rs +++ b/src/test/ui/const-generics/min_const_generics/default_function_param.rs @@ -1,4 +1,4 @@ fn foo() {} -//~^ ERROR default values for const generic parameters are unstable +//~^ ERROR default values for const generic parameters are experimental fn main() {} diff --git a/src/test/ui/const-generics/min_const_generics/default_function_param.stderr b/src/test/ui/const-generics/min_const_generics/default_function_param.stderr index 3d2fac78d7c2c..31b5ad5123ed2 100644 --- a/src/test/ui/const-generics/min_const_generics/default_function_param.stderr +++ b/src/test/ui/const-generics/min_const_generics/default_function_param.stderr @@ -1,10 +1,12 @@ -error: default values for const generic parameters are unstable - --> $DIR/default_function_param.rs:1:28 +error[E0658]: default values for const generic parameters are experimental + --> $DIR/default_function_param.rs:1:26 | LL | fn foo() {} - | ^ + | ^^^ | + = note: see issue #44580 for more information = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable error: aborting due to previous error +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/const-generics/min_const_generics/default_trait_param.rs b/src/test/ui/const-generics/min_const_generics/default_trait_param.rs index c6d91ef97a020..14bac473ed9a0 100644 --- a/src/test/ui/const-generics/min_const_generics/default_trait_param.rs +++ b/src/test/ui/const-generics/min_const_generics/default_trait_param.rs @@ -1,4 +1,4 @@ trait Foo {} -//~^ ERROR default values for const generic parameters are unstable +//~^ ERROR default values for const generic parameters are experimental fn main() {} diff --git a/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr b/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr index b727fdd807b66..5617b35ad013a 100644 --- a/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr +++ b/src/test/ui/const-generics/min_const_generics/default_trait_param.stderr @@ -1,10 +1,12 @@ -error: default values for const generic parameters are unstable - --> $DIR/default_trait_param.rs:1:30 +error[E0658]: default values for const generic parameters are experimental + --> $DIR/default_trait_param.rs:1:28 | LL | trait Foo {} - | ^^^^ + | ^^^^^^ | + = note: see issue #44580 for more information = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable error: aborting due to previous error +For more information about this error, try `rustc --explain E0658`. diff --git a/src/test/ui/feature-gates/feature-gate-const_generics_defaults.rs b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.rs index 90959e7a3656e..5b5ccc8887322 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics_defaults.rs +++ b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.rs @@ -1,7 +1,9 @@ +#[cfg(FALSE)] struct A; -//~^ ERROR default values for const generic parameters are unstable +//~^ ERROR default values for const generic parameters are experimental -fn foo() {} -//~^ ERROR default values for const generic parameters are unstable +#[cfg(FALSE)] +fn foo() {} +//~^ ERROR default values for const generic parameters are experimental fn main() {} diff --git a/src/test/ui/feature-gates/feature-gate-const_generics_defaults.stderr b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.stderr index 00d564772d2bc..e2b48d793fdff 100644 --- a/src/test/ui/feature-gates/feature-gate-const_generics_defaults.stderr +++ b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.stderr @@ -1,18 +1,21 @@ -error: default values for const generic parameters are unstable - --> $DIR/feature-gate-const_generics_defaults.rs:1:27 +error[E0658]: default values for const generic parameters are experimental + --> $DIR/feature-gate-const_generics_defaults.rs:2:25 | LL | struct A; - | ^ + | ^^^ | + = note: see issue #44580 for more information = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable -error: default values for const generic parameters are unstable - --> $DIR/feature-gate-const_generics_defaults.rs:4:22 +error[E0658]: default values for const generic parameters are experimental + --> $DIR/feature-gate-const_generics_defaults.rs:6:22 | -LL | fn foo() {} - | ^ +LL | fn foo() {} + | ^^^^^^^ | + = note: see issue #44580 for more information = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0658`.