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..e172f9d71ffbc 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 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_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..252e96b47c664 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(...);`). + (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 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_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_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index 860e63020bb06..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,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 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_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/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_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_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/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 2ae9ded3fa0cf..ab41ff372e23f 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 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 f4eb1924e6f7e..2f430842f9d8e 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 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 d7918a73ab8b3..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 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 8eb796d9bb7a8..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,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() {} - | ^ expected one of 7 possible tokens + | ^^^ + | + = 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 c8003ad5d44d8..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 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 6d112ef1de033..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,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 {} - | ^ expected one of 7 possible tokens + | ^^^^^^ + | + = 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/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 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..5b5ccc8887322 --- /dev/null +++ b/src/test/ui/feature-gates/feature-gate-const_generics_defaults.rs @@ -0,0 +1,9 @@ +#[cfg(FALSE)] +struct A; +//~^ ERROR default values for const generic parameters are experimental + +#[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 new file mode 100644 index 0000000000000..e2b48d793fdff --- /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; + | ^^^ + | + = note: see issue #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() {} + | ^^^^^^^ + | + = 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`. 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))