diff options
| author | bors <bors@rust-lang.org> | 2021-01-01 13:17:42 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2021-01-01 13:17:42 +0000 |
| commit | a609fb45efad59dfd459c76e50899be9f0583b5a (patch) | |
| tree | c1fdab60473e830ac13b75ffaa0175c46bb27f57 | |
| parent | 18d27b2c94cff9a5f6d8e4d2ea45f6f2e434e5f6 (diff) | |
| parent | 942b7ce2c14b1c4fde5b9f27aa5bef39e0b990d5 (diff) | |
| download | rust-a609fb45efad59dfd459c76e50899be9f0583b5a.tar.gz rust-a609fb45efad59dfd459c76e50899be9f0583b5a.zip | |
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`
37 files changed, 160 insertions, 53 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index cf31e566c38..8167bde0322 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -368,6 +368,8 @@ pub enum GenericParamKind { ty: P<Ty>, /// Span of the `const` keyword. kw_span: Span, + /// Optional default value for the const generic param + default: Option<AnonConst>, }, } diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index 3889ede7f4c..97966cc3260 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<T: MutVisitor>( 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 a420bb56350..a696626f8c4 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 d17b29089d6..f81dc39842c 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 c40f00bc9e9..e172f9d71ff 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))) @@ -774,8 +774,8 @@ fn validate_generic_param_order( } GenericParamKind::Type { default: None } => (), GenericParamKind::Lifetime => (), - // FIXME(const_generics:defaults) - GenericParamKind::Const { ty: _, kw_span: _ } => (), + // FIXME(const_generics_defaults) + GenericParamKind::Const { ty: _, kw_span: _, default: _ } => (), } first = false; } diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 6a9d6d2ed12..435f32535b6 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_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 333a396a0b4..bdd378b34e1 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 1651180817b..3c8bf12b3d4 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 c61857a1cd0..252e96b47c6 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`. @@ -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<const N: usize = 3>(...);`). + (active, const_generics_defaults, "1.51.0", Some(44580), None), + // ------------------------------------------------------------------------- // feature-group-end: actual feature gates // ------------------------------------------------------------------------- @@ -647,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 diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 47a7651e1d4..ebeb1bae2a3 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<AnonConst>, }, } diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 03c8b173885..87a2434152f 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 0b5eb1d8266..85bc38daa3d 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_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 777107ed863..14a56119f21 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 4dfe3e84877..ac6ceafaba8 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 c79e06b7fdd..77f16688937 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_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 860e63020bb..42a13376863 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,12 +56,26 @@ impl<'a> Parser<'a> { self.expect(&token::Colon)?; let ty = self.parse_ty()?; + // 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, 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 60a47ca12b8..43dee391c17 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<GenericArg>> { @@ -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_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 3c2462aab26..def2a501cf4 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/late.rs b/compiler/rustc_resolve/src/late.rs index dd1874debbd..fbe99a31150 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_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ca30d90e6ad..0de732b2cf9 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_save_analysis/src/dump_visitor.rs b/compiler/rustc_save_analysis/src/dump_visitor.rs index 40d60a8394b..987badcedde 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 ff445d727fa..e7d1c9d3bbe 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 b040a70437d..64b50a9b70a 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/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 0feac036f00..a3a2b8967c6 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 38d33e55866..9a2210e4f0e 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 2a8b77da44f..7126b624059 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 2ae9ded3fa0..ab41ff372e2 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; @@ -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 3e40f5ba28a..2ebb1a3be4e 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 f4eb1924e6f..2f430842f9d 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -607,11 +607,12 @@ impl Clean<GenericParamDef> 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 for docs }, ), }; @@ -1385,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/min_const_generics/default_function_param.rs b/src/test/ui/const-generics/min_const_generics/default_function_param.rs index d7918a73ab8..5b0a42a4556 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<const SIZE: usize = 5>() {} - //~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` +//~^ 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 8eb796d9bb7..31b5ad5123e 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,12 @@ -error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` +error[E0658]: default values for const generic parameters are experimental --> $DIR/default_function_param.rs:1:26 | LL | fn foo<const SIZE: usize = 5>() {} - | ^ expected one of 7 possible tokens + | ^^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/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 c8003ad5d44..14bac473ed9 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<const KIND: bool = true> {} - //~^ ERROR expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` +//~^ 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 6d112ef1de0..5617b35ad01 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,12 @@ -error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `=` +error[E0658]: default values for const generic parameters are experimental --> $DIR/default_trait_param.rs:1:28 | LL | trait Foo<const KIND: bool = true> {} - | ^ expected one of 7 possible tokens + | ^^^^^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/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/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 845c6111b59..a85e2a2f2c4 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 = [u8; std::mem::size_of::<T>()]>(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 = [u8; N], const N: usize>(T); //~^ ERROR constant values inside of type parameter defaults //~| ERROR type parameters with a default 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 00000000000..5b5ccc88873 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.rs @@ -0,0 +1,9 @@ +#[cfg(FALSE)] +struct A<const N: usize = 3>; +//~^ ERROR default values for const generic parameters are experimental + +#[cfg(FALSE)] +fn foo<const B: bool = false>() {} +//~^ 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 new file mode 100644 index 00000000000..e2b48d793fd --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.stderr @@ -0,0 +1,21 @@ +error[E0658]: default values for const generic parameters are experimental + --> $DIR/feature-gate-const_generics_defaults.rs:2:25 + | +LL | struct A<const N: usize = 3>; + | ^^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information + = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable + +error[E0658]: default values for const generic parameters are experimental + --> $DIR/feature-gate-const_generics_defaults.rs:6:22 + | +LL | fn foo<const B: bool = false>() {} + | ^^^^^^^ + | + = note: see issue #44580 <https://github.com/rust-lang/rust/issues/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`. 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 f0267e4c792..940573e4caa 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)) |
