diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index d4d7713f705658eaad1a9d52dcd953b15301a7ea..96bb9cfb1a6bb1593d3563621b0424db651fc29b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1150,20 +1150,23 @@ fn visit_generic_args(&mut self, _: Span, generic_args: &'a GenericArgs) { } fn visit_generics(&mut self, generics: &'a Generics) { - let mut prev_ty_default = None; + let cg_defaults = self.session.features_untracked().const_generics_defaults; + + let mut prev_param_default = None; for param in &generics.params { match param.kind { GenericParamKind::Lifetime => (), - GenericParamKind::Type { default: Some(_), .. } => { - prev_ty_default = Some(param.ident.span); + GenericParamKind::Type { default: Some(_), .. } + | GenericParamKind::Const { default: Some(_), .. } => { + prev_param_default = Some(param.ident.span); } GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => { - if let Some(span) = prev_ty_default { + if let Some(span) = prev_param_default { let mut err = self.err_handler().struct_span_err( span, - "type parameters with a default must be trailing", + "generic parameters with a default must be trailing", ); - if matches!(param.kind, GenericParamKind::Const { .. }) { + if matches!(param.kind, GenericParamKind::Const { .. }) && !cg_defaults { err.note( "using type defaults and const parameters \ in the same parameter list is currently not permitted", @@ -1174,17 +1177,6 @@ fn visit_generics(&mut self, generics: &'a Generics) { } } } - 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_generic_defaults)]` to the crate attributes to enable"); - err.emit(); - break; - } - } } validate_generic_param_order( diff --git a/compiler/rustc_error_codes/src/error_codes/E0128.md b/compiler/rustc_error_codes/src/error_codes/E0128.md index 6f8dfe3a73b9e3f01afe7a8dbe5c4c7387351471..2ea8ae68ef87702265e4d2b1a3d366321155d39f 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0128.md +++ b/compiler/rustc_error_codes/src/error_codes/E0128.md @@ -7,7 +7,7 @@ struct Foo { field1: T, field2: U, } -// error: type parameters with a default cannot use forward declared +// error: generic parameters with a default cannot use forward declared // identifiers ``` diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 701e4a632939473180b28cab0009da66dcf8d049..9b908b141af147659048d542d86b68c493f53876 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -366,6 +366,9 @@ fn visit_ty(&mut self, t: &'v Ty<'v>) { fn visit_generic_param(&mut self, p: &'v GenericParam<'v>) { walk_generic_param(self, p) } + fn visit_const_param_default(&mut self, _param: HirId, ct: &'v AnonConst) { + walk_const_param_default(self, ct) + } fn visit_generics(&mut self, g: &'v Generics<'v>) { walk_generics(self, g) } @@ -869,13 +872,17 @@ pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v Generi GenericParamKind::Const { ref ty, ref default } => { visitor.visit_ty(ty); if let Some(ref default) = default { - visitor.visit_anon_const(default); + visitor.visit_const_param_default(param.hir_id, default); } } } walk_list!(visitor, visit_param_bound, param.bounds); } +pub fn walk_const_param_default<'v, V: Visitor<'v>>(visitor: &mut V, ct: &'v AnonConst) { + visitor.visit_anon_const(ct) +} + pub fn walk_generics<'v, V: Visitor<'v>>(visitor: &mut V, generics: &'v Generics<'v>) { walk_list!(visitor, visit_generic_param, generics.params); walk_list!(visitor, visit_where_predicate, generics.where_clause.predicates); diff --git a/compiler/rustc_middle/src/hir/map/collector.rs b/compiler/rustc_middle/src/hir/map/collector.rs index a3d891fd1ba5ebda069602fe16cd6acfdf68cf7d..4602ed695fe68ccdc8202a1e6cd105f9c013c9ef 100644 --- a/compiler/rustc_middle/src/hir/map/collector.rs +++ b/compiler/rustc_middle/src/hir/map/collector.rs @@ -395,6 +395,10 @@ fn visit_generic_param(&mut self, param: &'hir GenericParam<'hir>) { } } + fn visit_const_param_default(&mut self, param: HirId, ct: &'hir AnonConst) { + self.with_parent(param, |this| intravisit::walk_const_param_default(this, ct)) + } + fn visit_trait_item(&mut self, ti: &'hir TraitItem<'hir>) { self.with_dep_node_owner(ti.def_id, ti, |this, hash| { this.insert_with_hash(ti.span, ti.hir_id(), Node::TraitItem(ti), hash); diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 779d6c90f973f022842b9bdd1b756525f9497676..9cd4c09082cef2472ad8588294d463bbf274c25b 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -44,7 +44,11 @@ pub fn from_opt_const_arg_anon_const( let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); let body_id = match tcx.hir().get(hir_id) { - hir::Node::AnonConst(ac) => ac.body, + hir::Node::AnonConst(ac) + | hir::Node::GenericParam(hir::GenericParam { + kind: hir::GenericParamKind::Const { ty: _, default: Some(ac) }, + .. + }) => ac.body, _ => span_bug!( tcx.def_span(def.did.to_def_id()), "from_anon_const can only process anonymous constants" diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 4eda1220599c794a1ac55be7f459c2b6d6d9f149..14e3d8498b0d8d4a278bac71de474a3492414dc4 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -228,7 +228,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. + /// Error E0128: generic parameters with a default cannot use forward-declared identifiers. ForwardDeclaredTyParam, // FIXME(const_generics_defaults) /// ERROR E0770: the type of const parameters must not depend on other generic parameters. ParamInTyOfConstParam(Symbol), @@ -238,7 +238,7 @@ enum ResolutionError<'a> { /// /// This error is only emitted when using `min_const_generics`. ParamInNonTrivialAnonConst { name: Symbol, is_type: bool }, - /// Error E0735: type parameters with a default cannot use `Self` + /// Error E0735: generic parameters with a default cannot use `Self` SelfInTyParamDefault, /// Error E0767: use of unreachable label UnreachableLabel { name: Symbol, definition_span: Span, suggestion: Option }, diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 604611406afe630dd5195bd20470266d6ecfa7c2..9625211109d1067c04d2572ab2de4473c33a4268 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -499,7 +499,9 @@ pub(crate) fn check_generic_arg_count( let expected_min = if infer_args { 0 } else { - param_counts.consts + named_type_param_count - default_counts.types + param_counts.consts + named_type_param_count + - default_counts.types + - default_counts.consts }; check_generics( diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 4328d0acb0a2af2168987bae4ff4f07c1449bbfe..1a765772e3ca99e3140201f70bfc43bd8d8e6f56 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -505,34 +505,17 @@ fn inferred_kind( } } GenericParamDefKind::Const { has_default } => { - let ty = tcx.at(self.span).type_of(param.def_id); if !infer_args && has_default { - let c = substs.unwrap()[param.index as usize].expect_const(); - ty::subst::GenericArg::from(c) - } else if infer_args { - self.astconv.ct_infer(ty, Some(param), self.span).into() + ty::Const::from_anon_const(tcx, param.def_id.expect_local()).into() } else { - // We've already errored above about the mismatch. - tcx.const_error(ty).into() - } - // FIXME(const_generic_defaults) - /* - if !infer_args && has_default { - /* - if default_needs_object_self(param) { - missing_type_params.push(param.name.to_string()); - tcx.const_error(ty).into() + let ty = tcx.at(self.span).type_of(param.def_id); + if infer_args { + self.astconv.ct_infer(ty, Some(param), self.span).into() } else { + // We've already errored above about the mismatch. + tcx.const_error(ty).into() } - */ - } else if infer_args { - // No const parameters were provided, we can infer all. - self.astconv.ct_infer(ty, Some(param), self.span).into() - } else { - // We've already errored above about the mismatch. - tcx.const_error(ty).into() } - */ } } } diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 2c13405b72c999996d6ba0c40be0e09f1c767a21..49b6e506eb1aae906a9abc77c7ab505d6c66cff0 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1444,12 +1444,11 @@ fn inferred_kind( } } GenericParamDefKind::Const { has_default, .. } => { - if infer_args || !has_default { - return self.fcx.var_for_def(self.span, param); + if !infer_args && has_default { + ty::Const::from_anon_const(tcx, param.def_id.expect_local()).into() + } else { + self.fcx.var_for_def(self.span, param) } - // FIXME(const_generic_defaults) - // No const parameters were provided, we have to infer them. - todo!() } } } diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 5e61a168270f5aec9442c7e88936ab5c75baa2b7..7fd49ccc8e46a57cf8a55997c889c8e0fee84778 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -759,7 +759,7 @@ fn check_where_clauses<'tcx, 'fcx>( fcx.tcx.mk_param_from_def(param) } - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { + GenericParamDefKind::Type { .. } => { // If the param has a default, ... if is_our_default(param) { let default_ty = fcx.tcx.type_of(param.def_id); @@ -772,6 +772,16 @@ fn check_where_clauses<'tcx, 'fcx>( fcx.tcx.mk_param_from_def(param) } + GenericParamDefKind::Const { .. } => { + if is_our_default(param) { + let default_ct = ty::Const::from_anon_const(tcx, param.def_id.expect_local()); + // Const params have to currently be concrete. + assert!(!default_ct.needs_subst()); + default_ct.into() + } else { + fcx.tcx.mk_param_from_def(param) + } + } } }); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 44e905c0b0a2687316ade27cee0422d5eb0ee080..933618e3a7b9f0b749c7597c0c111bb139665149 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1527,7 +1527,7 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { |lint| { lint.build( "defaults for type parameters are only allowed in \ - `struct`, `enum`, `type`, or `trait` definitions.", + `struct`, `enum`, `type`, or `trait` definitions", ) .emit(); }, @@ -1554,6 +1554,14 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { Some(param_def) } GenericParamKind::Const { default, .. } => { + if !allow_defaults && default.is_some() { + tcx.sess.span_err( + param.span, + "defaults for const parameters are only allowed in \ + `struct`, `enum`, `type`, or `trait` definitions", + ); + } + let param_def = ty::GenericParamDef { index: type_start + i as u32, name: param.name.ident().name, diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 95905b53585a9fecde17d228575d2d5add0220c7..a05cc36fd4c1c8731181d35ef5fcbd0b7a8736de 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -436,6 +436,12 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> { .discr_type() .to_ty(tcx), + Node::GenericParam(&GenericParam { + hir_id: param_hir_id, + kind: GenericParamKind::Const { default: Some(ct), .. }, + .. + }) if ct.hir_id == hir_id => tcx.type_of(tcx.hir().local_def_id(param_hir_id)), + x => tcx.ty_error_with_message( DUMMY_SP, &format!("unexpected const parent in type_of_def_id(): {:?}", x), diff --git a/src/test/ui/const-generics/defaults/const-default.rs b/src/test/ui/const-generics/defaults/const-default.rs index 00410224de5bb6a73689dc001eb32bee533f17df..150c70770ae51e69d1627326c5e898707aa7c911 100644 --- a/src/test/ui/const-generics/defaults/const-default.rs +++ b/src/test/ui/const-generics/defaults/const-default.rs @@ -1,12 +1,30 @@ -// check-pass +// run-pass #![feature(const_generics)] -#![feature(const_generic_defaults)] +#![feature(const_generics_defaults)] #![allow(incomplete_features)] -pub struct ConstDefault {} +pub struct ConstDefault; + +impl ConstDefault { + fn foo(self) -> usize { + N + } +} + +impl ConstDefault { + fn new() -> Self { + ConstDefault + } + + fn bar(self) {} +} pub fn main() { - let s = ConstDefault::default(); + let s = ConstDefault::new(); + assert_eq!(s.foo(), 3); + + let w = ConstDefault::<3>; + w.bar(); } diff --git a/src/test/ui/const-generics/defaults/wrong-order.full.stderr b/src/test/ui/const-generics/defaults/wrong-order.full.stderr index 96deb4a8b5abb968bfdd951aa2037ea55f6ec271..accc73134d8997f984832b730d4b62ce98871923 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.full.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.full.stderr @@ -1,4 +1,4 @@ -error: type parameters with a default must be trailing +error: generic parameters with a default must be trailing --> $DIR/wrong-order.rs:4:10 | LL | struct A { diff --git a/src/test/ui/const-generics/defaults/wrong-order.min.stderr b/src/test/ui/const-generics/defaults/wrong-order.min.stderr index b19da76f415d72be5502c1c69ea42a2387114fa2..c8f1d471b244b3497ae28a6f3704e1745d2b8df9 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.min.stderr +++ b/src/test/ui/const-generics/defaults/wrong-order.min.stderr @@ -1,4 +1,4 @@ -error: type parameters with a default must be trailing +error: generic parameters with a default must be trailing --> $DIR/wrong-order.rs:4:10 | LL | struct A { diff --git a/src/test/ui/const-generics/defaults/wrong-order.rs b/src/test/ui/const-generics/defaults/wrong-order.rs index 4f1c05011b0bfc2d02f08fbc969a51254d651616..5c2d9b8ad475104d5e488a331f4f05b1b8ecc49b 100644 --- a/src/test/ui/const-generics/defaults/wrong-order.rs +++ b/src/test/ui/const-generics/defaults/wrong-order.rs @@ -2,7 +2,7 @@ #![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete struct A { - //~^ ERROR type parameters with a default must be trailing + //~^ ERROR generic parameters with a default must be trailing arg: T, } 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 52803c5b7266a02363f70c36abbe20e528ec7583..ebdb5a65bc351840ef94784a7cf5dc1f027a7e7b 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,6 +1,6 @@ #![crate_type = "lib"] #![feature(const_generics_defaults)] -#![feature(min_const_generics)] #![allow(incomplete_features)] fn foo() {} +//~^ ERROR defaults for const parameters are 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 c7148e8ec071a2d2cea6e381e066a48dfbf82b2d..243ac0db5f55f194defecdf313977cefc6c287dc 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,9 +1,8 @@ -error[E0282]: type annotations needed - --> $DIR/default_function_param.rs:6:28 +error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions + --> $DIR/default_function_param.rs:5:14 | -LL | fn foo() {} - | ^ cannot infer type for type `{integer}` +LL | fn foo() {} + | ^^^^ error: aborting due to previous error -For more information about this error, try `rustc --explain E0282`. diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr index debb272da360848f2076c0fc8ab1782a31bc58bc..c2b7b206653a60d97a73f92aa5e4ba549608f2ea 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr @@ -1,4 +1,4 @@ -error: type parameters with a default must be trailing +error: generic parameters with a default must be trailing --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12 | LL | struct Bar(T); diff --git a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index 171efca19383135c679690482355b3864bd8b390..4a462c328bf6457e434d3c613f9b2d40db74e041 100644 --- a/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -1,4 +1,4 @@ -error: type parameters with a default must be trailing +error: generic parameters with a default must be trailing --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12 | LL | struct Bar(T); 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 a85e2a2f2c4f18b46383dc28672a8e998079dc32..c7be8bdaf9c3dc68fe5be5b322c56c353ba0f06b 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 @@ -10,6 +10,6 @@ // 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 +//~| ERROR generic parameters with a default fn main() {} diff --git a/src/test/ui/generics/generic-non-trailing-defaults.rs b/src/test/ui/generics/generic-non-trailing-defaults.rs index 8d9883dc7a9393daa1d01b5fc56fcfb34980f803..bd076b1f72579956a6b33dd8589a7ce3794de9ee 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.rs +++ b/src/test/ui/generics/generic-non-trailing-defaults.rs @@ -1,10 +1,10 @@ struct Heap; struct Vec(A, T); -//~^ ERROR type parameters with a default must be trailing +//~^ ERROR generic parameters with a default must be trailing struct Foo, C>(A, B, C); -//~^ ERROR type parameters with a default must be trailing -//~| ERROR type parameters with a default cannot use forward declared identifiers +//~^ ERROR generic parameters with a default must be trailing +//~| ERROR generic parameters with a default cannot use forward declared identifiers fn main() {} diff --git a/src/test/ui/generics/generic-non-trailing-defaults.stderr b/src/test/ui/generics/generic-non-trailing-defaults.stderr index 33dd44297220846a058e421487e13ea67a67ede5..6d7686175033545215869f2b111652728784d654 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.stderr +++ b/src/test/ui/generics/generic-non-trailing-defaults.stderr @@ -1,10 +1,10 @@ -error: type parameters with a default must be trailing +error: generic parameters with a default must be trailing --> $DIR/generic-non-trailing-defaults.rs:3:12 | LL | struct Vec(A, T); | ^ -error: type parameters with a default must be trailing +error: generic parameters with a default must be trailing --> $DIR/generic-non-trailing-defaults.rs:6:15 | LL | struct Foo, C>(A, B, C); diff --git a/src/test/ui/generics/generic-type-params-forward-mention.rs b/src/test/ui/generics/generic-type-params-forward-mention.rs index ac0cab20d78a2cfc33a560754ba65edd5f571114..000c47095d27ca988f3b3fa944051adea7066b7b 100644 --- a/src/test/ui/generics/generic-type-params-forward-mention.rs +++ b/src/test/ui/generics/generic-type-params-forward-mention.rs @@ -1,6 +1,6 @@ // Ensure that we get an error and not an ICE for this problematic case. struct Foo, U = bool>(T, U); -//~^ ERROR type parameters with a default cannot use forward declared identifiers +//~^ ERROR generic parameters with a default cannot use forward declared identifiers fn main() { let x: Foo; } diff --git a/src/test/ui/issues/issue-26812.rs b/src/test/ui/issues/issue-26812.rs index b2494a91a3f8a738b0d01cf7c864c47fcab207f2..3391ea4b350af466de5ae328d942c0b56b443ced 100644 --- a/src/test/ui/issues/issue-26812.rs +++ b/src/test/ui/issues/issue-26812.rs @@ -1,6 +1,6 @@ #![feature(default_type_parameter_fallback)] fn avg(_: T) {} -//~^ ERROR type parameters with a default cannot use forward declared identifiers +//~^ ERROR generic parameters with a default cannot use forward declared identifiers fn main() {}