diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index d4d7713f705..96bb9cfb1a6 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1150,20 +1150,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } 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 @@ 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_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 6f8dfe3a73b..2ea8ae68ef8 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 701e4a63293..9b908b141af 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -366,6 +366,9 @@ pub trait Visitor<'v>: Sized { 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 a3d891fd1ba..4602ed695fe 100644 --- a/compiler/rustc_middle/src/hir/map/collector.rs +++ b/compiler/rustc_middle/src/hir/map/collector.rs @@ -395,6 +395,10 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, '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 779d6c90f97..9cd4c09082c 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -44,7 +44,11 @@ impl<'tcx> Const<'tcx> { 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 4eda1220599..14e3d8498b0 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 604611406af..9625211109d 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -499,7 +499,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { 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 4328d0acb0a..1a765772e3c 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -505,34 +505,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } } 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 2c13405b72c..49b6e506eb1 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 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } 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 5e61a168270..7fd49ccc8e4 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 44e905c0b0a..933618e3a7b 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 95905b53585..a05cc36fd4c 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 00410224de5..150c70770ae 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 96deb4a8b5a..accc73134d8 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 b19da76f415..c8f1d471b24 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 4f1c05011b0..5c2d9b8ad47 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 52803c5b726..ebdb5a65bc3 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 c7148e8ec07..243ac0db5f5 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 debb272da36..c2b7b206653 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 171efca1938..4a462c328bf 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 a85e2a2f2c4..c7be8bdaf9c 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 @@ struct Foo()]>(T, U); // 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 8d9883dc7a9..bd076b1f725 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 33dd4429722..6d768617503 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 ac0cab20d78..000c47095d2 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 b2494a91a3f..3391ea4b350 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() {}