From e4e5db4e4207e21c38c07640d44005dab022f1b8 Mon Sep 17 00:00:00 2001 From: kadmin Date: Tue, 11 Aug 2020 00:02:45 +0000 Subject: [PATCH 1/8] Add has_default to GenericParamDefKind::Const This currently creates a field which is always false on GenericParamDefKind for future use when consts are permitted to have defaults Update const_generics:default locations Previously just ignored them, now actually do something about them. Fix using type check instead of value Add parsing This adds all the necessary changes to lower const-generics defaults from parsing. Change P to AnonConst This matches the arguments passed to instantiations of const generics, and makes it specific to just anonymous constants. Attempt to fix lowering bugs --- compiler/rustc_ast/src/ast.rs | 1 + compiler/rustc_ast/src/mut_visit.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 1 - .../rustc_ast_passes/src/ast_validation.rs | 11 ++++++++ compiler/rustc_ast_pretty/src/pprust/state.rs | 3 +++ compiler/rustc_hir_pretty/src/lib.rs | 6 +++-- .../src/infer/error_reporting/mod.rs | 5 ++-- compiler/rustc_middle/src/ty/context.rs | 4 +-- compiler/rustc_middle/src/ty/generics.rs | 20 +++++++------- compiler/rustc_middle/src/ty/instance.rs | 2 +- compiler/rustc_middle/src/ty/print/mod.rs | 27 +++++++++++-------- .../rustc_mir/src/monomorphize/collector.rs | 3 ++- compiler/rustc_privacy/src/lib.rs | 9 +++++-- compiler/rustc_resolve/src/late.rs | 1 + compiler/rustc_resolve/src/late/lifetimes.rs | 4 ++- compiler/rustc_save_analysis/src/sig.rs | 7 ++--- compiler/rustc_span/src/symbol.rs | 1 + .../error_reporting/on_unimplemented.rs | 2 +- .../rustc_trait_selection/src/traits/mod.rs | 2 +- .../src/traits/on_unimplemented.rs | 2 +- compiler/rustc_traits/src/chalk/db.rs | 2 +- compiler/rustc_typeck/src/astconv/generics.rs | 8 +++--- compiler/rustc_typeck/src/astconv/mod.rs | 26 +++++++++++++++--- .../rustc_typeck/src/check/compare_method.rs | 4 +-- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 11 +++++--- .../rustc_typeck/src/check/method/confirm.rs | 2 +- compiler/rustc_typeck/src/check/method/mod.rs | 2 +- .../rustc_typeck/src/check/method/probe.rs | 2 +- compiler/rustc_typeck/src/check/wfcheck.rs | 7 +---- compiler/rustc_typeck/src/collect.rs | 4 +-- compiler/rustc_typeck/src/collect/type_of.rs | 7 ++--- compiler/rustc_typeck/src/impl_wf_check.rs | 2 +- compiler/rustc_typeck/src/variance/solve.rs | 2 +- .../const-generics/defaults/const-default.rs | 15 +++++++++++ .../default_function_param.rs | 3 +++ .../min_const_generics/default_trait_param.rs | 2 -- .../feature-gate-const_generic_defaults.rs | 5 ++++ ...feature-gate-const_generic_defaults.stderr | 10 +++++++ .../clippy/clippy_utils/src/ast_utils.rs | 8 +++--- 39 files changed, 158 insertions(+), 77 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/const-default.rs create mode 100644 src/test/ui/feature-gate/feature-gate-const_generic_defaults.rs create mode 100644 src/test/ui/feature-gate/feature-gate-const_generic_defaults.stderr diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 7e82d7ff77d96..4b9bf273c70f7 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -385,6 +385,7 @@ 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 f426f2c7fece5..c5378fb47bc2a 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -785,8 +785,8 @@ pub fn noop_flat_map_generic_param( visit_opt(default, |default| vis.visit_ty(default)); } GenericParamKind::Const { ty, kw_span: _, default } => { - vis.visit_ty(ty); visit_opt(default, |default| vis.visit_anon_const(default)); + vis.visit_ty(ty); } } smallvec![param] diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8a051066c7d21..5385c4d72e4ba 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -2290,7 +2290,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { 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, default }) } }; diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 563bcda519065..235528d6b02bf 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1174,6 +1174,17 @@ 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.note("to enable them use #![feature(const_generic_defaults)]"); + err.emit(); + break; + } + } } validate_generic_param_order( diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index cb6f567c55140..3a7ec3a8df1dd 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -2661,6 +2661,9 @@ impl<'a> State<'a> { s.print_type_bounds(":", ¶m.bounds); if let Some(ref _default) = default { // FIXME(const_generics_defaults): print the `default` value here + s.s.space(); + s.word_space("="); + // s.print_anon_const(&default); } } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 76e5d30dc5ee2..7eeda6013ed75 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -2266,8 +2266,10 @@ impl<'a> State<'a> { GenericParamKind::Const { ref ty, ref default } => { self.word_space(":"); self.print_type(ty); - if let Some(ref _default) = default { - // FIXME(const_generics_defaults): print the `default` value here + if let Some(ref default) = default { + self.s.space(); + self.word_space("="); + self.print_anon_const(&default) } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index eeff48a63950e..d614f18610683 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -963,10 +963,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .rev() .filter_map(|param| match param.kind { ty::GenericParamDefKind::Lifetime => None, - ty::GenericParamDefKind::Type { has_default, .. } => { + + ty::GenericParamDefKind::Type { has_default, .. } + | ty::GenericParamDefKind::Const { has_default } => { Some((param.def_id, has_default)) } - ty::GenericParamDefKind::Const => None, // FIXME(const_generics_defaults) }) .peekable(); let has_default = { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 41a8bc10c8de2..56c38baa2df81 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2221,7 +2221,7 @@ impl<'tcx> TyCtxt<'tcx> { let adt_def = self.adt_def(wrapper_def_id); let substs = InternalSubsts::for_item(self, wrapper_def_id, |param, substs| match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => bug!(), + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => bug!(), GenericParamDefKind::Type { has_default, .. } => { if param.index == 0 { ty_param.into() @@ -2416,7 +2416,7 @@ impl<'tcx> TyCtxt<'tcx> { self.mk_region(ty::ReEarlyBound(param.to_early_bound_region_data())).into() } GenericParamDefKind::Type { .. } => self.mk_ty_param(param.index, param.name).into(), - GenericParamDefKind::Const => { + GenericParamDefKind::Const { .. } => { self.mk_const_param(param.index, param.name, self.type_of(param.def_id)).into() } } diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 79cd26f5668a1..ef46a41996488 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -18,7 +18,9 @@ pub enum GenericParamDefKind { object_lifetime_default: ObjectLifetimeDefault, synthetic: Option, }, - Const, + Const { + has_default: bool, + }, } impl GenericParamDefKind { @@ -26,14 +28,14 @@ impl GenericParamDefKind { match self { GenericParamDefKind::Lifetime => "lifetime", GenericParamDefKind::Type { .. } => "type", - GenericParamDefKind::Const => "constant", + GenericParamDefKind::Const { .. } => "constant", } } pub fn to_ord(&self, tcx: TyCtxt<'_>) -> ast::ParamKindOrd { match self { GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime, GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type, - GenericParamDefKind::Const => { + GenericParamDefKind::Const { .. } => { ast::ParamKindOrd::Const { unordered: tcx.features().const_generics } } } @@ -105,7 +107,7 @@ impl<'tcx> Generics { match param.kind { GenericParamDefKind::Lifetime => own_counts.lifetimes += 1, GenericParamDefKind::Type { .. } => own_counts.types += 1, - GenericParamDefKind::Const => own_counts.consts += 1, + GenericParamDefKind::Const { .. } => own_counts.consts += 1, } } @@ -118,12 +120,10 @@ impl<'tcx> Generics { for param in &self.params { match param.kind { GenericParamDefKind::Lifetime => (), - GenericParamDefKind::Type { has_default, .. } => { + GenericParamDefKind::Type { has_default, .. } | + GenericParamDefKind::Const { has_default } => { own_defaults.types += has_default as usize; } - GenericParamDefKind::Const => { - // FIXME(const_generics:defaults) - } } } @@ -146,7 +146,7 @@ impl<'tcx> Generics { pub fn own_requires_monomorphization(&self) -> bool { for param in &self.params { match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => return true, + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => return true, GenericParamDefKind::Lifetime => {} } } @@ -189,7 +189,7 @@ impl<'tcx> Generics { pub fn const_param(&'tcx self, param: &ParamConst, tcx: TyCtxt<'tcx>) -> &GenericParamDef { let param = self.param_at(param.index as usize, tcx); match param.kind { - GenericParamDefKind::Const => param, + GenericParamDefKind::Const { .. } => param, _ => bug!("expected const parameter, but found another generic parameter"), } } diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 23cedfd499eaa..f61b6946985e5 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -593,7 +593,7 @@ fn polymorphize<'tcx>( }, // Simple case: If parameter is a const or type parameter.. - ty::GenericParamDefKind::Const | ty::GenericParamDefKind::Type { .. } if + ty::GenericParamDefKind::Const { .. } | ty::GenericParamDefKind::Type { .. } if // ..and is within range and unused.. unused.contains(param.index).unwrap_or(false) => // ..then use the identity for this parameter. diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index 77f1668893782..ad323df8a69c1 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -193,17 +193,22 @@ pub trait Printer<'tcx>: Sized { .params .iter() .rev() - .take_while(|param| { - match param.kind { - ty::GenericParamDefKind::Lifetime => false, - ty::GenericParamDefKind::Type { has_default, .. } => { - has_default - && substs[param.index as usize] - == GenericArg::from( - self.tcx().type_of(param.def_id).subst(self.tcx(), substs), - ) - } - ty::GenericParamDefKind::Const => false, // FIXME(const_generics_defaults) + .take_while(|param| match param.kind { + ty::GenericParamDefKind::Lifetime => false, + ty::GenericParamDefKind::Type { has_default, .. } => { + has_default + && substs[param.index as usize] + == GenericArg::from( + self.tcx().type_of(param.def_id).subst(self.tcx(), substs), + ) + } + ty::GenericParamDefKind::Const { has_default } => { + has_default + && substs[param.index as usize] + == GenericArg::from(crate::ty::Const::from_anon_const( + self.tcx(), + param.def_id.expect_local(), + )) } }) .count(); diff --git a/compiler/rustc_mir/src/monomorphize/collector.rs b/compiler/rustc_mir/src/monomorphize/collector.rs index e48640e1bb965..c5c701082e66c 100644 --- a/compiler/rustc_mir/src/monomorphize/collector.rs +++ b/compiler/rustc_mir/src/monomorphize/collector.rs @@ -1175,7 +1175,8 @@ fn create_mono_items_for_default_impls<'tcx>( let substs = InternalSubsts::for_item(tcx, method.def_id, |param, _| match param.kind { GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { + GenericParamDefKind::Type { .. } + | GenericParamDefKind::Const { .. } => { trait_ref.substs[param.index as usize] } }); diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index de264b5bb0403..9ba9524ee1a08 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -928,8 +928,13 @@ impl ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { self.visit(self.ev.tcx.type_of(param.def_id)); } } - GenericParamDefKind::Const => { + GenericParamDefKind::Const { has_default, .. } => { self.visit(self.ev.tcx.type_of(param.def_id)); + if has_default { + // how should the error case be handled here? + // let default_const = self.ev.tcx.const_eval_poly(param.def_id).unwrap(); + // self.visit(default_const); + } } } } @@ -1741,7 +1746,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> { self.visit(self.tcx.type_of(param.def_id)); } } - GenericParamDefKind::Const => { + GenericParamDefKind::Const { .. } => { self.visit(self.tcx.type_of(param.def_id)); } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index af241ef8afccf..85faa961b1492 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -616,6 +616,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { self.visit_ty(ty); self.ribs[TypeNS].pop().unwrap(); self.ribs[ValueNS].pop().unwrap(); + // FIXME(const_generics:default) do something with default here? } } } diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 2c61c0963ae28..744945c5b0ffb 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -2004,7 +2004,9 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> { GenericParamDefKind::Type { object_lifetime_default, .. } => { Some(object_lifetime_default) } - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None, + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => { + None + } }) .collect() }) diff --git a/compiler/rustc_save_analysis/src/sig.rs b/compiler/rustc_save_analysis/src/sig.rs index 53150a9266434..c3bc1c191ff09 100644 --- a/compiler/rustc_save_analysis/src/sig.rs +++ b/compiler/rustc_save_analysis/src/sig.rs @@ -614,11 +614,12 @@ 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, ref default } = param.kind { + if let hir::GenericParamKind::Const { ref ty, 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 + if let Some(default) = default { + param_text.push_str(" = "); + param_text.push_str(&id_to_string(&scx.tcx.hir(), default.hir_id)); } } if !param.bounds.is_empty() { diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 42e01f1b8d1fe..116519855d776 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -384,6 +384,7 @@ symbols! { const_fn_fn_ptr_basics, const_fn_transmute, const_fn_union, + const_generic_defaults, const_generics, const_generics_defaults, const_if_match, diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs index e6a1cf58fe373..cecdcc9789609 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs @@ -176,7 +176,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> { for param in generics.params.iter() { let value = match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { trait_ref.substs[param.index as usize].to_string() } GenericParamDefKind::Lifetime => continue, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 5a8c53a0c4bd4..f26eb159105d7 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -483,7 +483,7 @@ fn vtable_methods<'tcx>( let substs = trait_ref.map_bound(|trait_ref| { InternalSubsts::for_item(tcx, def_id, |param, _| match param.kind { GenericParamDefKind::Lifetime => tcx.lifetimes.re_erased.into(), - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { trait_ref.substs[param.index as usize] } }) diff --git a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs index 75822eadb2ab3..209fd83b3ab34 100644 --- a/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/traits/on_unimplemented.rs @@ -337,7 +337,7 @@ impl<'tcx> OnUnimplementedFormatString { .iter() .filter_map(|param| { let value = match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { trait_ref.substs[param.index as usize].to_string() } GenericParamDefKind::Lifetime => return None, diff --git a/compiler/rustc_traits/src/chalk/db.rs b/compiler/rustc_traits/src/chalk/db.rs index 916186f4204e2..5c0cb2fb83578 100644 --- a/compiler/rustc_traits/src/chalk/db.rs +++ b/compiler/rustc_traits/src/chalk/db.rs @@ -739,7 +739,7 @@ fn bound_vars_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> SubstsRef<'tcx> { tcx.mk_region(ty::RegionKind::ReLateBound(ty::INNERMOST, br)).into() } - ty::GenericParamDefKind::Const => tcx + ty::GenericParamDefKind::Const { .. } => tcx .mk_const(ty::Const { val: ty::ConstKind::Bound(ty::INNERMOST, ty::BoundVar::from(param.index)), ty: tcx.type_of(param.def_id), diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs index 0ea0ccaceabd4..604611406afe6 100644 --- a/compiler/rustc_typeck/src/astconv/generics.rs +++ b/compiler/rustc_typeck/src/astconv/generics.rs @@ -64,7 +64,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { kind: hir::TyKind::Path(rustc_hir::QPath::Resolved(_, path)), .. }), - GenericParamDefKind::Const, + GenericParamDefKind::Const { .. }, ) => match path.res { Res::Err => { add_braces_suggestion(arg, &mut err); @@ -93,7 +93,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }, ( GenericArg::Type(hir::Ty { kind: hir::TyKind::Path(_), .. }), - GenericParamDefKind::Const, + GenericParamDefKind::Const { .. }, ) => add_braces_suggestion(arg, &mut err), ( GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }), @@ -236,7 +236,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { match (arg, ¶m.kind, arg_count.explicit_late_bound) { (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _) | (GenericArg::Type(_), GenericParamDefKind::Type { .. }, _) - | (GenericArg::Const(_), GenericParamDefKind::Const, _) => { + | (GenericArg::Const(_), GenericParamDefKind::Const { .. }, _) => { substs.push(ctx.provided_kind(param, arg)); args.next(); params.next(); @@ -282,7 +282,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { GenericParamDefKind::Type { .. } => { ParamKindOrd::Type } - GenericParamDefKind::Const => { + GenericParamDefKind::Const { .. } => { ParamKindOrd::Const { unordered: tcx .features() diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 7c5398003f3e6..34e5ab9073371 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -443,7 +443,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.astconv.ast_ty_to_ty(&ty).into() } } - (GenericParamDefKind::Const, GenericArg::Const(ct)) => { + (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { ty::Const::from_opt_const_arg_anon_const( tcx, ty::WithOptConstParam { @@ -504,16 +504,34 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { tcx.ty_error().into() } } - GenericParamDefKind::Const => { + GenericParamDefKind::Const { has_default } => { let ty = tcx.at(self.span).type_of(param.def_id); - // FIXME(const_generics_defaults) - if infer_args { + if !infer_args && has_default { + let c = ty::Const::from_anon_const(tcx, param.def_id.expect_local()); + ty::subst::GenericArg::from(c) + } else 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() + } + /* + if !infer_args && has_default { + /* + if default_needs_object_self(param) { + missing_type_params.push(param.name.to_string()); + tcx.const_error(ty).into() + } else { + } + */ + } 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/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs index a30a81079335d..ddb11b9f3b16b 100644 --- a/compiler/rustc_typeck/src/check/compare_method.rs +++ b/compiler/rustc_typeck/src/check/compare_method.rs @@ -792,11 +792,11 @@ fn compare_synthetic_generics<'tcx>( let trait_m_generics = tcx.generics_of(trait_m.def_id); let impl_m_type_params = impl_m_generics.params.iter().filter_map(|param| match param.kind { GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)), - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None, + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None, }); let trait_m_type_params = trait_m_generics.params.iter().filter_map(|param| match param.kind { GenericParamDefKind::Type { synthetic, .. } => Some((param.def_id, synthetic)), - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => None, + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => None, }); for ((impl_def_id, impl_synthetic), (trait_def_id, trait_synthetic)) in impl_m_type_params.zip(trait_m_type_params) diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index dc8a804bfea98..a5733c9637d4f 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1405,7 +1405,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { self.fcx.to_ty(ty).into() } - (GenericParamDefKind::Const, GenericArg::Const(ct)) => { + (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { self.fcx.const_arg_to_const(&ct.value, param.def_id).into() } _ => unreachable!(), @@ -1443,10 +1443,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.fcx.var_for_def(self.span, param) } } - GenericParamDefKind::Const => { - // FIXME(const_generics_defaults) + GenericParamDefKind::Const { has_default, .. } => { + if infer_args || !has_default { + return self.fcx.var_for_def(self.span, param); + } + // FIXME(const_generics:defaults) // No const parameters were provided, we have to infer them. - self.fcx.var_for_def(self.span, param) + todo!() } } } diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs index 4a2dd6faf0c32..731a72ff024dc 100644 --- a/compiler/rustc_typeck/src/check/method/confirm.rs +++ b/compiler/rustc_typeck/src/check/method/confirm.rs @@ -358,7 +358,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { self.cfcx.to_ty(ty).into() } - (GenericParamDefKind::Const, GenericArg::Const(ct)) => { + (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => { self.cfcx.const_arg_to_const(&ct.value, param.def_id).into() } _ => unreachable!(), diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs index 9a3d1e42b732a..d6fa6bf0067f9 100644 --- a/compiler/rustc_typeck/src/check/method/mod.rs +++ b/compiler/rustc_typeck/src/check/method/mod.rs @@ -308,7 +308,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Construct a trait-reference `self_ty : Trait` let substs = InternalSubsts::for_item(self.tcx, trait_def_id, |param, _| { match param.kind { - GenericParamDefKind::Lifetime | GenericParamDefKind::Const => {} + GenericParamDefKind::Lifetime | GenericParamDefKind::Const { .. } => {} GenericParamDefKind::Type { .. } => { if param.index == 0 { return self_ty.into(); diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs index 3006cabc632fd..0742549f8904e 100644 --- a/compiler/rustc_typeck/src/check/method/probe.rs +++ b/compiler/rustc_typeck/src/check/method/probe.rs @@ -1700,7 +1700,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // In general, during probe we erase regions. self.tcx.lifetimes.re_erased.into() } - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const => { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { self.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 00c6550835b43..d257ea22dc1c9 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -758,7 +758,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); @@ -771,11 +771,6 @@ fn check_where_clauses<'tcx, 'fcx>( fcx.tcx.mk_param_from_def(param) } - - GenericParamDefKind::Const => { - // 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 162fccc602036..424e5ab900dbc 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1549,13 +1549,13 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics { i += 1; Some(param_def) } - GenericParamKind::Const { .. } => { + GenericParamKind::Const { default, .. } => { let param_def = ty::GenericParamDef { index: type_start + i as u32, name: param.name.ident().name, def_id: tcx.hir().local_def_id(param.hir_id).to_def_id(), pure_wrt_drop: param.pure_wrt_drop, - kind: ty::GenericParamDefKind::Const, + kind: ty::GenericParamDefKind::Const { has_default: default.is_some() }, }; i += 1; Some(param_def) diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 3f2f244e44fd2..b7f7b8355ff2b 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -83,7 +83,8 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< return generics .params .iter() - .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const)) + .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. + })) .nth(arg_index) .map(|param| param.def_id); } @@ -121,7 +122,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< tcx.generics_of(type_dependent_def) .params .iter() - .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const)) + .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. })) .nth(idx) .map(|param| param.def_id) } @@ -211,7 +212,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< generics .params .iter() - .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const)) + .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. })) .nth(arg_index) .map(|param| param.def_id) } diff --git a/compiler/rustc_typeck/src/impl_wf_check.rs b/compiler/rustc_typeck/src/impl_wf_check.rs index 7713381e62e46..1240946860573 100644 --- a/compiler/rustc_typeck/src/impl_wf_check.rs +++ b/compiler/rustc_typeck/src/impl_wf_check.rs @@ -173,7 +173,7 @@ fn enforce_impl_params_are_constrained( ); } } - ty::GenericParamDefKind::Const => { + ty::GenericParamDefKind::Const { .. } => { let param_ct = ty::ParamConst::for_def(param); if !input_parameters.contains(&cgp::Parameter::from(param_ct)) { report_unused_parameter( diff --git a/compiler/rustc_typeck/src/variance/solve.rs b/compiler/rustc_typeck/src/variance/solve.rs index 2d3369cba7a1e..1a4d88ced0e45 100644 --- a/compiler/rustc_typeck/src/variance/solve.rs +++ b/compiler/rustc_typeck/src/variance/solve.rs @@ -78,7 +78,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> { // Make all const parameters invariant. for param in generics.params.iter() { - if let ty::GenericParamDefKind::Const = param.kind { + if let ty::GenericParamDefKind::Const { .. } = param.kind { variances[param.index as usize] = ty::Invariant; } } diff --git a/src/test/ui/const-generics/defaults/const-default.rs b/src/test/ui/const-generics/defaults/const-default.rs new file mode 100644 index 0000000000000..b2286e7d5bd98 --- /dev/null +++ b/src/test/ui/const-generics/defaults/const-default.rs @@ -0,0 +1,15 @@ +// check-pass + +#![feature(const_generics)] +#![feature(const_generic_defaults)] +#![allow(incomplete_features)] + + +#[derive(Default)] +pub struct ConstDefault { + items: [u32; N] +} + +pub fn main() { + let s = ConstDefault::default(); +} 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 5b0a42a45565c..e4044eaaa7cf3 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,3 +1,6 @@ +#![feature(const_generic_defaults)] +#![feature(min_const_generics)] + fn foo() {} //~^ ERROR default values for const generic parameters are experimental 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 14bac473ed9a0..c3581aca1cf42 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,2 @@ trait Foo {} //~^ ERROR default values for const generic parameters are experimental - -fn main() {} diff --git a/src/test/ui/feature-gate/feature-gate-const_generic_defaults.rs b/src/test/ui/feature-gate/feature-gate-const_generic_defaults.rs new file mode 100644 index 0000000000000..6ba314666e2e5 --- /dev/null +++ b/src/test/ui/feature-gate/feature-gate-const_generic_defaults.rs @@ -0,0 +1,5 @@ +#![feature(min_const_generics)] +#![crate_type="lib"] + +struct A; +//~^ ERROR default values for diff --git a/src/test/ui/feature-gate/feature-gate-const_generic_defaults.stderr b/src/test/ui/feature-gate/feature-gate-const_generic_defaults.stderr new file mode 100644 index 0000000000000..0b7140c0c0f80 --- /dev/null +++ b/src/test/ui/feature-gate/feature-gate-const_generic_defaults.stderr @@ -0,0 +1,10 @@ +error: default values for const generic parameters are unstable + --> $DIR/feature-gate-const_generic_defaults.rs:4:27 + | +LL | struct A; + | ^ + | + = note: to enable them use #![feature(const_generic_defaults)] + +error: aborting due to previous error + diff --git a/src/tools/clippy/clippy_utils/src/ast_utils.rs b/src/tools/clippy/clippy_utils/src/ast_utils.rs index ea9a910d1b920..e202b5061a678 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils.rs @@ -408,6 +408,10 @@ pub fn eq_use_tree(l: &UseTree, r: &UseTree) -> bool { eq_path(&l.prefix, &r.prefix) && eq_use_tree_kind(&l.kind, &r.kind) } +pub fn eq_anon_const(l: &AnonConst, r: &AnonConst) -> bool { + eq_expr(&l.value, &r.value) +} + pub fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool { use UseTreeKind::*; match (l, r) { @@ -418,10 +422,6 @@ 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), From 8ef81388e2def7b12d3b527705bf32402c8d7c8a Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 30 Dec 2020 15:34:53 +0000 Subject: [PATCH 2/8] Some refactoring --- compiler/rustc_ast/src/mut_visit.rs | 2 +- .../rustc_ast_passes/src/ast_validation.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 1 + .../src/infer/error_reporting/mod.rs | 5 ++-- compiler/rustc_metadata/src/rmeta/encoder.rs | 7 +++-- compiler/rustc_passes/src/stability.rs | 7 ++--- compiler/rustc_privacy/src/lib.rs | 1 + compiler/rustc_resolve/src/diagnostics.rs | 4 +-- compiler/rustc_resolve/src/late.rs | 28 +++++++++---------- compiler/rustc_resolve/src/lib.rs | 14 ++++++---- compiler/rustc_typeck/src/astconv/mod.rs | 3 +- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 2 +- compiler/rustc_typeck/src/check/wfcheck.rs | 7 +++-- compiler/rustc_typeck/src/collect.rs | 6 +++- compiler/rustc_typeck/src/collect/type_of.rs | 3 +- .../const-generics/defaults/const-default.rs | 5 +--- .../default_function_param.rs | 9 +++--- .../default_function_param.stderr | 11 +++----- .../min_const_generics/default_trait_param.rs | 2 ++ src/test/ui/error-codes/E0128.stderr | 4 +-- .../feature-gate-const_generic_defaults.rs | 5 ---- ...feature-gate-const_generic_defaults.stderr | 10 ------- .../generic-non-trailing-defaults.stderr | 9 +----- ...generic-type-params-forward-mention.stderr | 4 +-- src/test/ui/issues/issue-18183.stderr | 4 +-- src/test/ui/issues/issue-26812.stderr | 4 +-- .../ui/panic-handler/weak-lang-item.stderr | 4 +-- 27 files changed, 74 insertions(+), 89 deletions(-) delete mode 100644 src/test/ui/feature-gate/feature-gate-const_generic_defaults.rs delete mode 100644 src/test/ui/feature-gate/feature-gate-const_generic_defaults.stderr diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs index c5378fb47bc2a..f426f2c7fece5 100644 --- a/compiler/rustc_ast/src/mut_visit.rs +++ b/compiler/rustc_ast/src/mut_visit.rs @@ -785,8 +785,8 @@ pub fn noop_flat_map_generic_param( visit_opt(default, |default| vis.visit_ty(default)); } GenericParamKind::Const { ty, kw_span: _, default } => { - visit_opt(default, |default| vis.visit_anon_const(default)); vis.visit_ty(ty); + visit_opt(default, |default| vis.visit_anon_const(default)); } } smallvec![param] diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 235528d6b02bf..d4d7713f70565 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -1180,7 +1180,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { default.value.span, "default values for const generic parameters are unstable", ); - err.note("to enable them use #![feature(const_generic_defaults)]"); + err.help("add `#![feature(const_generic_defaults)]` to the crate attributes to enable"); err.emit(); break; } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 3a7ec3a8df1dd..d6f2773cc47ce 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -2659,6 +2659,7 @@ impl<'a> State<'a> { s.word_space(":"); s.print_type(ty); s.print_type_bounds(":", ¶m.bounds); + // FIXME(const_generic_defaults) if let Some(ref _default) = default { // FIXME(const_generics_defaults): print the `default` value here s.s.space(); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index d614f18610683..7df80b2b5b9a4 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -963,9 +963,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .rev() .filter_map(|param| match param.kind { ty::GenericParamDefKind::Lifetime => None, - - ty::GenericParamDefKind::Type { has_default, .. } - | ty::GenericParamDefKind::Const { has_default } => { + ty::GenericParamDefKind::Const { has_default } + | ty::GenericParamDefKind::Type { has_default, .. } => { Some((param.def_id, has_default)) } }) diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index ff8ec1d551323..3237857452736 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1876,13 +1876,16 @@ impl EncodeContext<'a, 'tcx> { default.is_some(), ); } - GenericParamKind::Const { .. } => { + GenericParamKind::Const { ref default, .. } => { self.encode_info_for_generic_param( def_id.to_def_id(), EntryKind::ConstParam, true, ); - // FIXME(const_generics_defaults) + if default.is_some() { + self.encode_stability(def_id.to_def_id()); + } + // FIXME(const_generic_defaults) } } } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index dd9cb51c858b4..8a6ac843534c6 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -507,10 +507,9 @@ 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) - hir::GenericParamKind::Type { default, .. } if default.is_some() => { - AnnotationKind::Container - } + // Allow stability attributes on default generic arguments. + hir::GenericParamKind::Type { default: Some(_), .. } + | hir::GenericParamKind::Const { default: Some(_), .. } => AnnotationKind::Container, _ => AnnotationKind::Prohibited, }; diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 9ba9524ee1a08..d9789dda2ea9e 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -931,6 +931,7 @@ impl ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { GenericParamDefKind::Const { has_default, .. } => { self.visit(self.ev.tcx.type_of(param.def_id)); if has_default { + // FIXME(const_generic_defaults) // how should the error case be handled here? // let default_const = self.ev.tcx.const_eval_poly(param.def_id).unwrap(); // self.visit(default_const); diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7493fd68505fe..d402fa4f8494f 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -450,12 +450,12 @@ impl<'a> Resolver<'a> { self.session, span, E0128, - "type parameters with a default cannot use \ + "generic parameters with a default cannot use \ forward declared identifiers" ); err.span_label( span, - "defaulted type parameters cannot be forward declared".to_string(), + "defaulted generic parameters cannot be forward declared".to_string(), ); err } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 85faa961b1492..f9f33492a1ec3 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -132,10 +132,10 @@ crate enum RibKind<'a> { /// We passed through a `macro_rules!` statement MacroDefinition(DefId), - /// All bindings in this rib are type parameters that can't be used - /// from the default of a type parameter because they're not declared - /// before said type parameter. Also see the `visit_generics` override. - ForwardTyParamBanRibKind, + /// All bindings in this rib are generic parameters that can't be used + /// from the default of a generic parameter because they're not declared + /// before said generic parameter. Also see the `visit_generics` override. + ForwardGenericParamBanRibKind, /// We are inside of the type of a const parameter. Can't refer to any /// parameters. @@ -154,7 +154,7 @@ impl RibKind<'_> { | ModuleRibKind(_) | MacroDefinition(_) | ConstParamTyRibKind => false, - AssocItemRibKind | ItemRibKind(_) | ForwardTyParamBanRibKind => true, + AssocItemRibKind | ItemRibKind(_) | ForwardGenericParamBanRibKind => true, } } } @@ -555,15 +555,16 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { // provide previous type parameters as they're built. We // put all the parameters on the ban list and then remove // them one by one as they are processed and become available. - let mut default_ban_rib = Rib::new(ForwardTyParamBanRibKind); + let mut default_ban_rib = Rib::new(ForwardGenericParamBanRibKind); let mut found_default = false; default_ban_rib.bindings.extend(generics.params.iter().filter_map( |param| match param.kind { - GenericParamKind::Const { .. } | GenericParamKind::Lifetime { .. } => None, - GenericParamKind::Type { ref default, .. } => { - found_default |= default.is_some(); - found_default.then_some((Ident::with_dummy_span(param.ident.name), Res::Err)) + GenericParamKind::Type { default: Some(_), .. } + | GenericParamKind::Const { default: Some(_), .. } => { + found_default = true; + Some((Ident::with_dummy_span(param.ident.name), Res::Err)) } + _ => None, }, )); @@ -591,8 +592,8 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { if let Some(ref ty) = default { self.ribs[TypeNS].push(default_ban_rib); - self.with_rib(ValueNS, ForwardTyParamBanRibKind, |this| { - // HACK: We use an empty `ForwardTyParamBanRibKind` here which + self.with_rib(ValueNS, ForwardGenericParamBanRibKind, |this| { + // HACK: We use an empty `ForwardGenericParamBanRibKind` here which // is only used to forbid the use of const parameters inside of // type defaults. // @@ -616,7 +617,6 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { self.visit_ty(ty); self.ribs[TypeNS].pop().unwrap(); self.ribs[ValueNS].pop().unwrap(); - // FIXME(const_generics:default) do something with default here? } } } @@ -866,7 +866,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { | ItemRibKind(..) | ConstantItemRibKind(..) | ModuleRibKind(..) - | ForwardTyParamBanRibKind + | ForwardGenericParamBanRibKind | ConstParamTyRibKind => { return false; } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index d8f201fd0d8fa..4eda1220599c7 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2592,8 +2592,8 @@ impl<'a> Resolver<'a> { debug!("validate_res_from_ribs({:?})", res); let ribs = &all_ribs[rib_index + 1..]; - // An invalid forward use of a type parameter from a previous default. - if let ForwardTyParamBanRibKind = all_ribs[rib_index].kind { + // An invalid forward use of a generic parameter from a previous default. + if let ForwardGenericParamBanRibKind = all_ribs[rib_index].kind { if record_used { let res_error = if rib_ident.name == kw::SelfUpper { ResolutionError::SelfInTyParamDefault @@ -2617,7 +2617,7 @@ impl<'a> Resolver<'a> { | ClosureOrAsyncRibKind | ModuleRibKind(..) | MacroDefinition(..) - | ForwardTyParamBanRibKind => { + | ForwardGenericParamBanRibKind => { // Nothing to do. Continue. } ItemRibKind(_) | FnItemRibKind | AssocItemRibKind => { @@ -2689,7 +2689,9 @@ impl<'a> Resolver<'a> { // We only forbid constant items if we are inside of type defaults, // for example `struct Foo()]>` - ForwardTyParamBanRibKind => { + ForwardGenericParamBanRibKind => { + // FIXME(const_generic_defaults): we may need to distinguish between + // being in type parameter defaults and const parameter defaults in_ty_param_default = true; continue; } @@ -2782,7 +2784,9 @@ impl<'a> Resolver<'a> { // We only forbid constant items if we are inside of type defaults, // for example `struct Foo()]>` - ForwardTyParamBanRibKind => { + ForwardGenericParamBanRibKind => { + // FIXME(const_generic_defaults): we may need to distinguish between + // being in type parameter defaults and const parameter defaults in_ty_param_default = true; continue; } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 34e5ab9073371..4328d0acb0a2a 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -507,7 +507,7 @@ 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 = ty::Const::from_anon_const(tcx, param.def_id.expect_local()); + 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() @@ -515,6 +515,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { // We've already errored above about the mismatch. tcx.const_error(ty).into() } + // FIXME(const_generic_defaults) /* if !infer_args && has_default { /* diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index a5733c9637d4f..2c13405b72c99 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1447,7 +1447,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if infer_args || !has_default { return self.fcx.var_for_def(self.span, param); } - // FIXME(const_generics:defaults) + // 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 d257ea22dc1c9..5e61a168270f5 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -713,10 +713,11 @@ fn check_where_clauses<'tcx, 'fcx>( let generics = tcx.generics_of(def_id); let is_our_default = |def: &ty::GenericParamDef| match def.kind { - GenericParamDefKind::Type { has_default, .. } => { + GenericParamDefKind::Type { has_default, .. } + | GenericParamDefKind::Const { has_default } => { has_default && def.index >= generics.parent_count as u32 } - _ => unreachable!(), + GenericParamDefKind::Lifetime => unreachable!(), }; // Check that concrete defaults are well-formed. See test `type-check-defaults.rs`. @@ -758,7 +759,7 @@ fn check_where_clauses<'tcx, 'fcx>( fcx.tcx.mk_param_from_def(param) } - GenericParamDefKind::Const { .. } | GenericParamDefKind::Type { .. } => { + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { // If the param has a default, ... if is_our_default(param) { let default_ty = fcx.tcx.type_of(param.def_id); diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 424e5ab900dbc..44e905c0b0a26 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -254,10 +254,14 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { self.tcx.ensure().type_of(def_id); } hir::GenericParamKind::Type { .. } => {} - hir::GenericParamKind::Const { .. } => { + hir::GenericParamKind::Const { default, .. } => { let def_id = self.tcx.hir().local_def_id(param.hir_id); self.tcx.ensure().type_of(def_id); // FIXME(const_generics_defaults) + if let Some(default) = default { + let def_id = self.tcx.hir().local_def_id(default.hir_id); + self.tcx.ensure().type_of(def_id); + } } } } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index b7f7b8355ff2b..95905b53585a9 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -83,8 +83,7 @@ pub(super) fn opt_const_param_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option< return generics .params .iter() - .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. - })) + .filter(|param| matches!(param.kind, ty::GenericParamDefKind::Const { .. })) .nth(arg_index) .map(|param| param.def_id); } diff --git a/src/test/ui/const-generics/defaults/const-default.rs b/src/test/ui/const-generics/defaults/const-default.rs index b2286e7d5bd98..00410224de5bb 100644 --- a/src/test/ui/const-generics/defaults/const-default.rs +++ b/src/test/ui/const-generics/defaults/const-default.rs @@ -5,10 +5,7 @@ #![allow(incomplete_features)] -#[derive(Default)] -pub struct ConstDefault { - items: [u32; N] -} +pub struct ConstDefault {} pub fn main() { let s = ConstDefault::default(); 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 e4044eaaa7cf3..52803c5b7266a 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,7 +1,6 @@ -#![feature(const_generic_defaults)] +#![crate_type = "lib"] +#![feature(const_generics_defaults)] #![feature(min_const_generics)] +#![allow(incomplete_features)] -fn foo() {} -//~^ ERROR default values for const generic parameters are experimental - -fn main() {} +fn foo() {} 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 31b5ad5123ed2..c7148e8ec071a 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,12 +1,9 @@ -error[E0658]: default values for const generic parameters are experimental - --> $DIR/default_function_param.rs:1:26 +error[E0282]: type annotations needed + --> $DIR/default_function_param.rs:6:28 | LL | fn foo() {} - | ^^^ - | - = note: see issue #44580 for more information - = help: add `#![feature(const_generics_defaults)]` to the crate attributes to enable + | ^ cannot infer type for type `{integer}` error: aborting due to previous error -For more information about this error, try `rustc --explain E0658`. +For more information about this error, try `rustc --explain E0282`. 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 c3581aca1cf42..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,2 +1,4 @@ trait Foo {} //~^ ERROR default values for const generic parameters are experimental + +fn main() {} diff --git a/src/test/ui/error-codes/E0128.stderr b/src/test/ui/error-codes/E0128.stderr index 253aa166bd371..eb66d46936a85 100644 --- a/src/test/ui/error-codes/E0128.stderr +++ b/src/test/ui/error-codes/E0128.stderr @@ -1,8 +1,8 @@ -error[E0128]: type parameters with a default cannot use forward declared identifiers +error[E0128]: generic parameters with a default cannot use forward declared identifiers --> $DIR/E0128.rs:1:14 | LL | struct Foo { - | ^ defaulted type parameters cannot be forward declared + | ^ defaulted generic parameters cannot be forward declared error: aborting due to previous error diff --git a/src/test/ui/feature-gate/feature-gate-const_generic_defaults.rs b/src/test/ui/feature-gate/feature-gate-const_generic_defaults.rs deleted file mode 100644 index 6ba314666e2e5..0000000000000 --- a/src/test/ui/feature-gate/feature-gate-const_generic_defaults.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![feature(min_const_generics)] -#![crate_type="lib"] - -struct A; -//~^ ERROR default values for diff --git a/src/test/ui/feature-gate/feature-gate-const_generic_defaults.stderr b/src/test/ui/feature-gate/feature-gate-const_generic_defaults.stderr deleted file mode 100644 index 0b7140c0c0f80..0000000000000 --- a/src/test/ui/feature-gate/feature-gate-const_generic_defaults.stderr +++ /dev/null @@ -1,10 +0,0 @@ -error: default values for const generic parameters are unstable - --> $DIR/feature-gate-const_generic_defaults.rs:4:27 - | -LL | struct A; - | ^ - | - = note: to enable them use #![feature(const_generic_defaults)] - -error: aborting due to previous error - diff --git a/src/test/ui/generics/generic-non-trailing-defaults.stderr b/src/test/ui/generics/generic-non-trailing-defaults.stderr index fb359f673a95e..33dd442972208 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.stderr +++ b/src/test/ui/generics/generic-non-trailing-defaults.stderr @@ -10,12 +10,5 @@ error: type parameters with a default must be trailing LL | struct Foo, C>(A, B, C); | ^ -error[E0128]: type parameters with a default cannot use forward declared identifiers - --> $DIR/generic-non-trailing-defaults.rs:6:23 - | -LL | struct Foo, C>(A, B, C); - | ^ defaulted type parameters cannot be forward declared - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0128`. diff --git a/src/test/ui/generics/generic-type-params-forward-mention.stderr b/src/test/ui/generics/generic-type-params-forward-mention.stderr index 97389c337fcbe..fa661c274ebca 100644 --- a/src/test/ui/generics/generic-type-params-forward-mention.stderr +++ b/src/test/ui/generics/generic-type-params-forward-mention.stderr @@ -1,8 +1,8 @@ -error[E0128]: type parameters with a default cannot use forward declared identifiers +error[E0128]: generic parameters with a default cannot use forward declared identifiers --> $DIR/generic-type-params-forward-mention.rs:2:23 | LL | struct Foo, U = bool>(T, U); - | ^ defaulted type parameters cannot be forward declared + | ^ defaulted generic parameters cannot be forward declared error: aborting due to previous error diff --git a/src/test/ui/issues/issue-18183.stderr b/src/test/ui/issues/issue-18183.stderr index c8f8ac9296dc0..a7dc64708d856 100644 --- a/src/test/ui/issues/issue-18183.stderr +++ b/src/test/ui/issues/issue-18183.stderr @@ -1,8 +1,8 @@ -error[E0128]: type parameters with a default cannot use forward declared identifiers +error[E0128]: generic parameters with a default cannot use forward declared identifiers --> $DIR/issue-18183.rs:1:20 | LL | pub struct Foo(Bar); - | ^^^ defaulted type parameters cannot be forward declared + | ^^^ defaulted generic parameters cannot be forward declared error: aborting due to previous error diff --git a/src/test/ui/issues/issue-26812.stderr b/src/test/ui/issues/issue-26812.stderr index 8d507a7ea0144..fd1bbb9c5673d 100644 --- a/src/test/ui/issues/issue-26812.stderr +++ b/src/test/ui/issues/issue-26812.stderr @@ -1,8 +1,8 @@ -error[E0128]: type parameters with a default cannot use forward declared identifiers +error[E0128]: generic parameters with a default cannot use forward declared identifiers --> $DIR/issue-26812.rs:3:10 | LL | fn avg(_: T) {} - | ^^^^^^^ defaulted type parameters cannot be forward declared + | ^^^^^^^ defaulted generic parameters cannot be forward declared error: aborting due to previous error diff --git a/src/test/ui/panic-handler/weak-lang-item.stderr b/src/test/ui/panic-handler/weak-lang-item.stderr index 68e3e21df3e08..b7c040c7a850b 100644 --- a/src/test/ui/panic-handler/weak-lang-item.stderr +++ b/src/test/ui/panic-handler/weak-lang-item.stderr @@ -10,10 +10,10 @@ help: you can use `as` to change the binding name of the import LL | extern crate core as other_core; | -error: language item required, but not found: `eh_personality` - error: `#[panic_handler]` function required, but not found +error: language item required, but not found: `eh_personality` + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0259`. From b0feb5be2f045a7611845b92113f7f720c32ae95 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 1 Mar 2021 12:50:09 +0100 Subject: [PATCH 3/8] progress, stuff compiles now --- .../rustc_ast_passes/src/ast_validation.rs | 26 ++++++----------- .../src/error_codes/E0128.md | 2 +- compiler/rustc_hir/src/intravisit.rs | 9 +++++- .../rustc_middle/src/hir/map/collector.rs | 4 +++ compiler/rustc_middle/src/ty/consts.rs | 6 +++- compiler/rustc_resolve/src/lib.rs | 4 +-- compiler/rustc_typeck/src/astconv/generics.rs | 4 ++- compiler/rustc_typeck/src/astconv/mod.rs | 29 ++++--------------- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 9 +++--- compiler/rustc_typeck/src/check/wfcheck.rs | 12 +++++++- compiler/rustc_typeck/src/collect.rs | 10 ++++++- compiler/rustc_typeck/src/collect/type_of.rs | 6 ++++ .../const-generics/defaults/const-default.rs | 26 ++++++++++++++--- .../defaults/wrong-order.full.stderr | 2 +- .../defaults/wrong-order.min.stderr | 2 +- .../ui/const-generics/defaults/wrong-order.rs | 2 +- .../default_function_param.rs | 2 +- .../default_function_param.stderr | 9 +++--- ...ms-in-ct-in-ty-param-lazy-norm.full.stderr | 2 +- ...ams-in-ct-in-ty-param-lazy-norm.min.stderr | 2 +- .../params-in-ct-in-ty-param-lazy-norm.rs | 2 +- .../generics/generic-non-trailing-defaults.rs | 6 ++-- .../generic-non-trailing-defaults.stderr | 4 +-- .../generic-type-params-forward-mention.rs | 2 +- src/test/ui/issues/issue-26812.rs | 2 +- 25 files changed, 108 insertions(+), 76 deletions(-) diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index d4d7713f70565..96bb9cfb1a6bb 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 6f8dfe3a73b9e..2ea8ae68ef877 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 701e4a6329394..9b908b141af14 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 a3d891fd1ba5e..4602ed695fe68 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 779d6c90f973f..9cd4c09082cef 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 4eda1220599c7..14e3d8498b0d8 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 604611406afe6..9625211109d10 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 4328d0acb0a2a..1a765772e3ca9 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 2c13405b72c99..49b6e506eb1aa 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 5e61a168270f5..7fd49ccc8e46a 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 44e905c0b0a26..933618e3a7b9f 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 95905b53585a9..a05cc36fd4c1c 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 00410224de5bb..150c70770ae51 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 96deb4a8b5abb..accc73134d899 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 b19da76f415d7..c8f1d471b244b 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 4f1c05011b0bf..5c2d9b8ad4751 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 52803c5b7266a..ebdb5a65bc351 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 c7148e8ec071a..243ac0db5f55f 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 debb272da3608..c2b7b206653a6 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 171efca193831..4a462c328bf64 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 a85e2a2f2c4f1..c7be8bdaf9c3d 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 8d9883dc7a939..bd076b1f72579 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 33dd442972208..6d76861750335 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 ac0cab20d78a2..000c47095d27c 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 b2494a91a3f8a..3391ea4b350af 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() {} From 0e56a086f72f9319f9c32f209bc07510dfedb70c Mon Sep 17 00:00:00 2001 From: kadmin Date: Mon, 1 Mar 2021 21:41:49 +0000 Subject: [PATCH 4/8] Update tests --- .../feature-gate-default_type_parameter_fallback.stderr | 4 ++-- src/test/ui/generics/generic-non-trailing-defaults.rs | 1 - src/test/ui/panic-handler/weak-lang-item.stderr | 4 ++-- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr index f13803b80f308..5cd38ebab370e 100644 --- a/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr +++ b/src/test/ui/feature-gates/feature-gate-default_type_parameter_fallback.stderr @@ -1,4 +1,4 @@ -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions. +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions --> $DIR/feature-gate-default_type_parameter_fallback.rs:3:8 | LL | fn avg(_: T) {} @@ -8,7 +8,7 @@ LL | fn avg(_: T) {} = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #36887 -error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions. +error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions --> $DIR/feature-gate-default_type_parameter_fallback.rs:8:6 | LL | impl S {} diff --git a/src/test/ui/generics/generic-non-trailing-defaults.rs b/src/test/ui/generics/generic-non-trailing-defaults.rs index bd076b1f72579..cb2bb2832b70e 100644 --- a/src/test/ui/generics/generic-non-trailing-defaults.rs +++ b/src/test/ui/generics/generic-non-trailing-defaults.rs @@ -5,6 +5,5 @@ struct Vec(A, T); struct Foo, C>(A, B, C); //~^ 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/panic-handler/weak-lang-item.stderr b/src/test/ui/panic-handler/weak-lang-item.stderr index b7c040c7a850b..68e3e21df3e08 100644 --- a/src/test/ui/panic-handler/weak-lang-item.stderr +++ b/src/test/ui/panic-handler/weak-lang-item.stderr @@ -10,10 +10,10 @@ help: you can use `as` to change the binding name of the import LL | extern crate core as other_core; | -error: `#[panic_handler]` function required, but not found - error: language item required, but not found: `eh_personality` +error: `#[panic_handler]` function required, but not found + error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0259`. From 9fe793ae5df4bc9ea73c8e55c66616bd6e5fe565 Mon Sep 17 00:00:00 2001 From: kadmin Date: Wed, 3 Mar 2021 06:38:02 +0000 Subject: [PATCH 5/8] Add query for const_param_default --- compiler/rustc_ast/src/ast.rs | 1 - compiler/rustc_metadata/src/rmeta/decoder.rs | 8 ++++++ .../src/rmeta/decoder/cstore_impl.rs | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 11 +++----- compiler/rustc_metadata/src/rmeta/mod.rs | 3 ++- compiler/rustc_middle/src/query/mod.rs | 6 +++++ compiler/rustc_middle/src/ty/consts.rs | 24 ++++++++++++----- compiler/rustc_middle/src/ty/generics.rs | 8 +++--- compiler/rustc_middle/src/ty/mod.rs | 1 + compiler/rustc_middle/src/ty/print/mod.rs | 5 +--- compiler/rustc_typeck/src/astconv/mod.rs | 4 +-- .../rustc_typeck/src/check/fn_ctxt/_impl.rs | 2 +- compiler/rustc_typeck/src/check/wfcheck.rs | 2 +- compiler/rustc_typeck/src/collect.rs | 3 ++- .../defaults/auxiliary/const_defaulty.rs | 15 +++++++++++ .../ui/const-generics/defaults/external.rs | 27 +++++++++++++++++++ .../type_and_const_defaults.rs | 14 ++++++++++ 17 files changed, 108 insertions(+), 27 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs create mode 100644 src/test/ui/const-generics/defaults/external.rs create mode 100644 src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 4b9bf273c70f7..7e82d7ff77d96 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -385,7 +385,6 @@ 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_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index e8891e471f9da..3d0a9d553b028 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -953,6 +953,14 @@ impl<'a, 'tcx> CrateMetadataRef<'a> { self.root.tables.expn_that_defined.get(self, id).unwrap().decode((self, sess)) } + fn get_const_param_default( + &self, + tcx: TyCtxt<'tcx>, + id: DefIndex, + ) -> rustc_middle::ty::Const<'tcx> { + self.root.tables.const_defaults.get(self, id).unwrap().decode((self, tcx)) + } + /// Iterates over all the stability attributes in the given crate. fn get_lib_features(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Option)] { // FIXME: For a proc macro crate, not sure whether we should return the "host" diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 0f860d11dc21a..7f8f5ef442701 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -122,6 +122,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) } mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) } unused_generic_params => { cdata.get_unused_generic_params(def_id.index) } + const_param_default => { tcx.arena.alloc(cdata.get_const_param_default(tcx, def_id.index)) } mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 3237857452736..fea7ea44c674a 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1877,15 +1877,12 @@ impl EncodeContext<'a, 'tcx> { ); } GenericParamKind::Const { ref default, .. } => { - self.encode_info_for_generic_param( - def_id.to_def_id(), - EntryKind::ConstParam, - true, - ); + let def_id = def_id.to_def_id(); + self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true); if default.is_some() { - self.encode_stability(def_id.to_def_id()); + self.encode_stability(def_id); + record!(self.tables.const_defaults[def_id] <- self.tcx.const_param_default(def_id)) } - // FIXME(const_generic_defaults) } } } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 610528956d0a1..94722ad2051bd 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -313,7 +313,8 @@ define_tables! { // `DefPathTable` up front, since we may only ever use a few // definitions from any given crate. def_keys: Table>, - def_path_hashes: Table> + def_path_hashes: Table>, + const_defaults: Table>>, } #[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)] diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 53a7d8528d36e..1666c6065b7de 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -93,6 +93,12 @@ rustc_queries! { desc { |tcx| "computing the optional const parameter of `{}`", tcx.def_path_str(key.to_def_id()) } } + /// Given the def_id of a const-generic parameter, computes the associated default const + /// parameter. i.e. `fn example` called on N would return 3. + query const_param_default(param: DefId) -> &'tcx ty::Const<'tcx> { + desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param) } + } + /// Records the type of every item. query type_of(key: DefId) -> Ty<'tcx> { desc { |tcx| "computing type of `{}`", tcx.def_path_str(key) } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 9cd4c09082cef..6821efcdcc52b 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -5,7 +5,7 @@ use crate::ty::{self, Ty, TyCtxt}; use crate::ty::{ParamEnv, ParamEnvAnd}; use rustc_errors::ErrorReported; use rustc_hir as hir; -use rustc_hir::def_id::LocalDefId; +use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_macros::HashStable; mod int; @@ -44,11 +44,7 @@ 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) - | hir::Node::GenericParam(hir::GenericParam { - kind: hir::GenericParamKind::Const { ty: _, default: Some(ac) }, - .. - }) => ac.body, + hir::Node::AnonConst(ac) => ac.body, _ => span_bug!( tcx.def_span(def.did.to_def_id()), "from_anon_const can only process anonymous constants" @@ -206,3 +202,19 @@ impl<'tcx> Const<'tcx> { .unwrap_or_else(|| bug!("expected usize, got {:#?}", self)) } } + +pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Const<'tcx> { + let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); + let default_def_id = match tcx.hir().get(hir_id) { + hir::Node::AnonConst(ac) + | hir::Node::GenericParam(hir::GenericParam { + kind: hir::GenericParamKind::Const { ty: _, default: Some(ac) }, + .. + }) => tcx.hir().local_def_id(ac.hir_id), + _ => span_bug!( + tcx.def_span(def_id), + "const_param_defaults expected a generic parameter with a constant" + ), + }; + Const::from_anon_const(tcx, default_def_id) +} diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index ef46a41996488..78a9f2daeb3f7 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -120,8 +120,8 @@ impl<'tcx> Generics { for param in &self.params { match param.kind { GenericParamDefKind::Lifetime => (), - GenericParamDefKind::Type { has_default, .. } | - GenericParamDefKind::Const { has_default } => { + GenericParamDefKind::Type { has_default, .. } + | GenericParamDefKind::Const { has_default } => { own_defaults.types += has_default as usize; } } @@ -146,7 +146,9 @@ impl<'tcx> Generics { pub fn own_requires_monomorphization(&self) -> bool { for param in &self.params { match param.kind { - GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => return true, + GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => { + return true; + } GenericParamDefKind::Lifetime => {} } } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e6b4739d0a2f5..ed10a1566223e 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1949,6 +1949,7 @@ pub fn provide(providers: &mut ty::query::Providers) { trait_impls_of: trait_def::trait_impls_of_provider, all_local_trait_impls: trait_def::all_local_trait_impls, type_uninhabited_from: inhabitedness::type_uninhabited_from, + const_param_default: consts::const_param_default, ..*providers }; } diff --git a/compiler/rustc_middle/src/ty/print/mod.rs b/compiler/rustc_middle/src/ty/print/mod.rs index ad323df8a69c1..a47846828bd60 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -205,10 +205,7 @@ pub trait Printer<'tcx>: Sized { ty::GenericParamDefKind::Const { has_default } => { has_default && substs[param.index as usize] - == GenericArg::from(crate::ty::Const::from_anon_const( - self.tcx(), - param.def_id.expect_local(), - )) + == GenericArg::from(self.tcx().const_param_default(param.def_id)) } }) .count(); diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 1a765772e3ca9..8076aa7102c6c 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -505,10 +505,10 @@ 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 { - ty::Const::from_anon_const(tcx, param.def_id.expect_local()).into() + tcx.const_param_default(param.def_id).into() } else { - 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 { diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 49b6e506eb1aa..56ff9293dd87f 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1445,7 +1445,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } GenericParamDefKind::Const { has_default, .. } => { if !infer_args && has_default { - ty::Const::from_anon_const(tcx, param.def_id.expect_local()).into() + tcx.const_param_default(param.def_id).into() } else { 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 7fd49ccc8e46a..8ac24a969f8cb 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -774,7 +774,7 @@ fn check_where_clauses<'tcx, 'fcx>( } GenericParamDefKind::Const { .. } => { if is_our_default(param) { - let default_ct = ty::Const::from_anon_const(tcx, param.def_id.expect_local()); + let default_ct = tcx.const_param_default(param.def_id); // Const params have to currently be concrete. assert!(!default_ct.needs_subst()); default_ct.into() diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 933618e3a7b9f..85c5128591a32 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -257,10 +257,11 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { hir::GenericParamKind::Const { default, .. } => { let def_id = self.tcx.hir().local_def_id(param.hir_id); self.tcx.ensure().type_of(def_id); - // FIXME(const_generics_defaults) if let Some(default) = default { let def_id = self.tcx.hir().local_def_id(default.hir_id); + // need to store default and type of default self.tcx.ensure().type_of(def_id); + self.tcx.ensure().const_param_default(def_id); } } } diff --git a/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs new file mode 100644 index 0000000000000..769b6e952dc9c --- /dev/null +++ b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs @@ -0,0 +1,15 @@ +#![feature(const_generics)] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +pub struct Defaulted; +impl Defaulted { + pub fn new() -> Self { + Defaulted + } +} +impl Defaulted { + pub fn value(&self) -> usize { + N + } +} diff --git a/src/test/ui/const-generics/defaults/external.rs b/src/test/ui/const-generics/defaults/external.rs new file mode 100644 index 0000000000000..b39e69ab10b66 --- /dev/null +++ b/src/test/ui/const-generics/defaults/external.rs @@ -0,0 +1,27 @@ +// aux-build:const_defaulty.rs +// check-pass +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +extern crate const_defaulty; +use const_defaulty::Defaulted; + +struct Local; +impl Local { + fn new() -> Self { + Local + } +} +implLocal { + fn value(&self) -> usize { + N + } +} + +fn main() { + let v = Defaulted::new(); + assert_eq!(v.value(), 3); + + let l = Local::new(); + assert_eq!(l.value(), 4); +} diff --git a/src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs b/src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs new file mode 100644 index 0000000000000..2ce874c8bf4d3 --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs @@ -0,0 +1,14 @@ +// check-pass +#![crate_type = "lib"] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +struct Both { + arr: [T; N] +} + +trait BothTrait {} + +enum BothEnum { + Dummy([T; N]) +} From ea2af704669f630c4184bb2c0befeb6cb7d78d29 Mon Sep 17 00:00:00 2001 From: kadmin Date: Thu, 18 Mar 2021 06:38:11 +0000 Subject: [PATCH 6/8] Update with comments A bunch of nits fixed, and a new test for pretty printing the AST. --- compiler/rustc_ast_pretty/src/pprust/state.rs | 5 ++--- .../src/infer/error_reporting/mod.rs | 5 +++-- .../src/rmeta/decoder/cstore_impl.rs | 2 +- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- compiler/rustc_middle/src/ty/consts.rs | 3 +-- compiler/rustc_middle/src/ty/generics.rs | 6 ++++-- compiler/rustc_privacy/src/lib.rs | 6 ++---- compiler/rustc_typeck/src/collect.rs | 4 ++-- .../defaults/default-annotation.rs | 20 +++++++++++++++++++ .../defaults/pretty-printing-ast.rs | 13 ++++++++++++ .../defaults/pretty-printing-ast.stdout | 20 +++++++++++++++++++ 11 files changed, 69 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/default-annotation.rs create mode 100644 src/test/ui/const-generics/defaults/pretty-printing-ast.rs create mode 100644 src/test/ui/const-generics/defaults/pretty-printing-ast.stdout diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index d6f2773cc47ce..aa9c255c6331c 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -2660,11 +2660,10 @@ impl<'a> State<'a> { s.print_type(ty); s.print_type_bounds(":", ¶m.bounds); // FIXME(const_generic_defaults) - if let Some(ref _default) = default { - // FIXME(const_generics_defaults): print the `default` value here + if let Some(ref default) = default { s.s.space(); s.word_space("="); - // s.print_anon_const(&default); + s.print_expr(&default.value); } } } diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 7df80b2b5b9a4..f4717fc08c78d 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -963,10 +963,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { .rev() .filter_map(|param| match param.kind { ty::GenericParamDefKind::Lifetime => None, - ty::GenericParamDefKind::Const { has_default } - | ty::GenericParamDefKind::Type { has_default, .. } => { + ty::GenericParamDefKind::Type { has_default, .. } => { Some((param.def_id, has_default)) } + // FIXME(const_generics:defaults) + ty::GenericParamDefKind::Const { has_default: _has_default } => None, }) .peekable(); let has_default = { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 7f8f5ef442701..e10041a297142 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -122,7 +122,7 @@ provide! { <'tcx> tcx, def_id, other, cdata, promoted_mir => { tcx.arena.alloc(cdata.get_promoted_mir(tcx, def_id.index)) } mir_abstract_const => { cdata.get_mir_abstract_const(tcx, def_id.index) } unused_generic_params => { cdata.get_unused_generic_params(def_id.index) } - const_param_default => { tcx.arena.alloc(cdata.get_const_param_default(tcx, def_id.index)) } + const_param_default => { tcx.mk_const(cdata.get_const_param_default(tcx, def_id.index)) } mir_const_qualif => { cdata.mir_const_qualif(def_id.index) } fn_sig => { cdata.fn_sig(def_id.index, tcx) } inherent_impls => { cdata.get_inherent_implementations_for_type(tcx, def_id.index) } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 94722ad2051bd..7cfb051e703c5 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -307,6 +307,7 @@ define_tables! { mir_for_ctfe: Table)>, promoted_mir: Table>)>, mir_abstract_consts: Table])>, + const_defaults: Table>>, unused_generic_params: Table>>, // `def_keys` and `def_path_hashes` represent a lazy version of a // `DefPathTable`. This allows us to avoid deserializing an entire @@ -314,7 +315,6 @@ define_tables! { // definitions from any given crate. def_keys: Table>, def_path_hashes: Table>, - const_defaults: Table>>, } #[derive(Copy, Clone, MetadataEncodable, MetadataDecodable)] diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 6821efcdcc52b..343438e975e04 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -206,8 +206,7 @@ impl<'tcx> Const<'tcx> { pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Const<'tcx> { let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local()); let default_def_id = match tcx.hir().get(hir_id) { - hir::Node::AnonConst(ac) - | hir::Node::GenericParam(hir::GenericParam { + hir::Node::GenericParam(hir::GenericParam { kind: hir::GenericParamKind::Const { ty: _, default: Some(ac) }, .. }) => tcx.hir().local_def_id(ac.hir_id), diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs index 78a9f2daeb3f7..d30a8693959f3 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -120,10 +120,12 @@ impl<'tcx> Generics { for param in &self.params { match param.kind { GenericParamDefKind::Lifetime => (), - GenericParamDefKind::Type { has_default, .. } - | GenericParamDefKind::Const { has_default } => { + GenericParamDefKind::Type { has_default, .. } => { own_defaults.types += has_default as usize; } + GenericParamDefKind::Const { has_default } => { + own_defaults.consts += has_default as usize; + } } } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index d9789dda2ea9e..e092bb845ffac 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -931,10 +931,7 @@ impl ReachEverythingInTheInterfaceVisitor<'_, 'tcx> { GenericParamDefKind::Const { has_default, .. } => { self.visit(self.ev.tcx.type_of(param.def_id)); if has_default { - // FIXME(const_generic_defaults) - // how should the error case be handled here? - // let default_const = self.ev.tcx.const_eval_poly(param.def_id).unwrap(); - // self.visit(default_const); + self.visit(self.ev.tcx.const_param_default(param.def_id)); } } } @@ -1747,6 +1744,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'tcx> { self.visit(self.tcx.type_of(param.def_id)); } } + // FIXME(const_evaluatable_checked): May want to look inside const here GenericParamDefKind::Const { .. } => { self.visit(self.tcx.type_of(param.def_id)); } diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 85c5128591a32..cb0eea1b7067c 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -258,9 +258,9 @@ impl Visitor<'tcx> for CollectItemTypesVisitor<'tcx> { let def_id = self.tcx.hir().local_def_id(param.hir_id); self.tcx.ensure().type_of(def_id); if let Some(default) = default { - let def_id = self.tcx.hir().local_def_id(default.hir_id); + let default_def_id = self.tcx.hir().local_def_id(default.hir_id); // need to store default and type of default - self.tcx.ensure().type_of(def_id); + self.tcx.ensure().type_of(default_def_id); self.tcx.ensure().const_param_default(def_id); } } diff --git a/src/test/ui/const-generics/defaults/default-annotation.rs b/src/test/ui/const-generics/defaults/default-annotation.rs new file mode 100644 index 0000000000000..e6e8d732beef3 --- /dev/null +++ b/src/test/ui/const-generics/defaults/default-annotation.rs @@ -0,0 +1,20 @@ +// run-pass +#![feature(staged_api)] + +#![feature(const_generics)] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +#![stable(feature = "const_default_test", since="none")] + + +#[unstable(feature = "const_default_stable", issue="none")] +pub struct ConstDefaultUnstable; + +#[stable(feature = "const_default_unstable", since="none")] +pub struct ConstDefaultStable; + +fn main() {} diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs new file mode 100644 index 0000000000000..a25d4baca1a97 --- /dev/null +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs @@ -0,0 +1,13 @@ +// Test the AST pretty printer correctly handles default values for const generics +// check-pass +// compile-flags: -Z unpretty=expanded + +#![crate_type = "lib"] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +trait Foo {} + +fn foo() {} + +struct Range; diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout new file mode 100644 index 0000000000000..f7a1d2ca4b2ef --- /dev/null +++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout @@ -0,0 +1,20 @@ +#![feature(prelude_import)] +#![no_std] +// Test the AST pretty printer correctly handles default values for const generics +// check-pass +// compile-flags: -Z unpretty=expanded + +#![crate_type = "lib"] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] +#[prelude_import] +use ::std::prelude::rust_2015::*; +#[macro_use] +extern crate std; + +trait Foo { } + +fn foo() { } + +struct Range; From 7116bb5c33c1b0d12a7dade3fa20c9b0e2e08218 Mon Sep 17 00:00:00 2001 From: kadmin Date: Sat, 20 Mar 2021 22:34:58 +0000 Subject: [PATCH 7/8] Update with comments --- compiler/rustc_ast_pretty/src/pprust/state.rs | 1 - .../src/infer/error_reporting/mod.rs | 61 +++++++++++-------- compiler/rustc_metadata/src/rmeta/encoder.rs | 1 - compiler/rustc_middle/src/query/mod.rs | 2 +- compiler/rustc_middle/src/ty/consts.rs | 2 +- compiler/rustc_typeck/src/check/wfcheck.rs | 2 +- .../min_const_generics/const_default_first.rs | 9 +++ .../const_default_first.stderr | 8 +++ .../type_and_const_defaults.rs | 19 +++++- 9 files changed, 72 insertions(+), 33 deletions(-) create mode 100644 src/test/ui/const-generics/min_const_generics/const_default_first.rs create mode 100644 src/test/ui/const-generics/min_const_generics/const_default_first.stderr diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index aa9c255c6331c..84f8ce5706ae6 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -2659,7 +2659,6 @@ impl<'a> State<'a> { s.word_space(":"); s.print_type(ty); s.print_type_bounds(":", ¶m.bounds); - // FIXME(const_generic_defaults) if let Some(ref default) = default { s.s.space(); s.word_space("="); diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index f4717fc08c78d..98904206b215c 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -957,34 +957,45 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { ) -> SubstsRef<'tcx> { let generics = self.tcx.generics_of(def_id); let mut num_supplied_defaults = 0; - let mut type_params = generics - .params - .iter() - .rev() - .filter_map(|param| match param.kind { - ty::GenericParamDefKind::Lifetime => None, - ty::GenericParamDefKind::Type { has_default, .. } => { - Some((param.def_id, has_default)) - } - // FIXME(const_generics:defaults) - ty::GenericParamDefKind::Const { has_default: _has_default } => None, - }) - .peekable(); - let has_default = { - let has_default = type_params.peek().map(|(_, has_default)| has_default); - *has_default.unwrap_or(&false) - }; - if has_default { - let types = substs.types().rev(); - for ((def_id, has_default), actual) in type_params.zip(types) { - if !has_default { - break; + + #[derive(PartialEq, Eq, Copy, Clone)] + enum Kind { + Const, + Type, + } + let default_params = generics.params.iter().rev().filter_map(|param| match param.kind { + ty::GenericParamDefKind::Type { has_default: true, .. } => { + Some((param.def_id, Kind::Type)) + } + ty::GenericParamDefKind::Const { has_default: true } => { + Some((param.def_id, Kind::Const)) + } + _ => None, + }); + let mut types = substs.types().rev(); + let mut consts = substs.consts().rev(); + for (def_id, kind) in default_params { + match kind { + Kind::Const => { + if let Some(actual) = consts.next() { + if ty::Const::from_anon_const(self.tcx, def_id.expect_local()) != actual { + break; + } + } else { + break; + } } - if self.tcx.type_of(def_id).subst(self.tcx, substs) != actual { - break; + Kind::Type => { + if let Some(actual) = types.next() { + if self.tcx.type_of(def_id).subst(self.tcx, substs) != actual { + break; + } + } else { + break; + } } - num_supplied_defaults += 1; } + num_supplied_defaults += 1; } let len = generics.params.len(); let mut generics = generics.clone(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index fea7ea44c674a..d055c275299a6 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1880,7 +1880,6 @@ impl EncodeContext<'a, 'tcx> { let def_id = def_id.to_def_id(); self.encode_info_for_generic_param(def_id, EntryKind::ConstParam, true); if default.is_some() { - self.encode_stability(def_id); record!(self.tables.const_defaults[def_id] <- self.tcx.const_param_default(def_id)) } } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 1666c6065b7de..36162cfe92452 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -94,7 +94,7 @@ rustc_queries! { } /// Given the def_id of a const-generic parameter, computes the associated default const - /// parameter. i.e. `fn example` called on N would return 3. + /// parameter. e.g. `fn example` called on `N` would return `3`. query const_param_default(param: DefId) -> &'tcx ty::Const<'tcx> { desc { |tcx| "compute const default for a given parameter `{}`", tcx.def_path_str(param) } } diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 343438e975e04..c78151271c171 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -212,7 +212,7 @@ pub fn const_param_default<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx Cons }) => tcx.hir().local_def_id(ac.hir_id), _ => span_bug!( tcx.def_span(def_id), - "const_param_defaults expected a generic parameter with a constant" + "`const_param_default` expected a generic parameter with a constant" ), }; Const::from_anon_const(tcx, default_def_id) diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 8ac24a969f8cb..5f302f7d0a94e 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -775,7 +775,7 @@ fn check_where_clauses<'tcx, 'fcx>( GenericParamDefKind::Const { .. } => { if is_our_default(param) { let default_ct = tcx.const_param_default(param.def_id); - // Const params have to currently be concrete. + // Const params currently have to be concrete. assert!(!default_ct.needs_subst()); default_ct.into() } else { diff --git a/src/test/ui/const-generics/min_const_generics/const_default_first.rs b/src/test/ui/const-generics/min_const_generics/const_default_first.rs new file mode 100644 index 0000000000000..ae82c85eb7e4b --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/const_default_first.rs @@ -0,0 +1,9 @@ +#![crate_type = "lib"] +#![feature(const_generics)] +#![feature(const_generics_defaults)] +#![allow(incomplete_features, dead_code)] + +struct Both { +//~^ ERROR: generic parameters with a default must be + v: T +} diff --git a/src/test/ui/const-generics/min_const_generics/const_default_first.stderr b/src/test/ui/const-generics/min_const_generics/const_default_first.stderr new file mode 100644 index 0000000000000..f7a2e484fc61b --- /dev/null +++ b/src/test/ui/const-generics/min_const_generics/const_default_first.stderr @@ -0,0 +1,8 @@ +error: generic parameters with a default must be trailing + --> $DIR/const_default_first.rs:6:19 + | +LL | struct Both { + | ^ + +error: aborting due to previous error + diff --git a/src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs b/src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs index 2ce874c8bf4d3..435a63a528345 100644 --- a/src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs +++ b/src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs @@ -1,7 +1,7 @@ -// check-pass -#![crate_type = "lib"] +// run-pass +#![feature(const_generics)] #![feature(const_generics_defaults)] -#![allow(incomplete_features)] +#![allow(incomplete_features, dead_code)] struct Both { arr: [T; N] @@ -12,3 +12,16 @@ trait BothTrait {} enum BothEnum { Dummy([T; N]) } + +struct OppOrder { + arr: [T; N] +} + +fn main() { + let _ = OppOrder::<3, u32> { + arr: [0,0,0], + }; + let _ = Both:: { + arr: [0], + }; +} From 33370fd9829c5bb843b117d11cc7e948f4b824f6 Mon Sep 17 00:00:00 2001 From: kadmin Date: Mon, 22 Mar 2021 23:26:07 +0000 Subject: [PATCH 8/8] Update to not have extra match --- .../src/infer/error_reporting/mod.rs | 38 ++++---------- .../ui/const-generics/defaults/mismatch.rs | 23 ++++++++ .../const-generics/defaults/mismatch.stderr | 52 +++++++++++++++++++ 3 files changed, 85 insertions(+), 28 deletions(-) create mode 100644 src/test/ui/const-generics/defaults/mismatch.rs create mode 100644 src/test/ui/const-generics/defaults/mismatch.stderr diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 98904206b215c..c171b11e3ffa7 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -67,7 +67,7 @@ use rustc_hir::{Item, ItemKind, Node}; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ self, - subst::{Subst, SubstsRef}, + subst::{GenericArgKind, Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable, }; use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span}; @@ -958,42 +958,24 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let generics = self.tcx.generics_of(def_id); let mut num_supplied_defaults = 0; - #[derive(PartialEq, Eq, Copy, Clone)] - enum Kind { - Const, - Type, - } let default_params = generics.params.iter().rev().filter_map(|param| match param.kind { - ty::GenericParamDefKind::Type { has_default: true, .. } => { - Some((param.def_id, Kind::Type)) - } - ty::GenericParamDefKind::Const { has_default: true } => { - Some((param.def_id, Kind::Const)) - } + ty::GenericParamDefKind::Type { has_default: true, .. } => Some(param.def_id), + ty::GenericParamDefKind::Const { has_default: true } => Some(param.def_id), _ => None, }); - let mut types = substs.types().rev(); - let mut consts = substs.consts().rev(); - for (def_id, kind) in default_params { - match kind { - Kind::Const => { - if let Some(actual) = consts.next() { - if ty::Const::from_anon_const(self.tcx, def_id.expect_local()) != actual { - break; - } - } else { + for (def_id, actual) in default_params.zip(substs.iter().rev()) { + match actual.unpack() { + GenericArgKind::Const(c) => { + if self.tcx.const_param_default(def_id).subst(self.tcx, substs) != c { break; } } - Kind::Type => { - if let Some(actual) = types.next() { - if self.tcx.type_of(def_id).subst(self.tcx, substs) != actual { - break; - } - } else { + GenericArgKind::Type(ty) => { + if self.tcx.type_of(def_id).subst(self.tcx, substs) != ty { break; } } + _ => break, } num_supplied_defaults += 1; } diff --git a/src/test/ui/const-generics/defaults/mismatch.rs b/src/test/ui/const-generics/defaults/mismatch.rs new file mode 100644 index 0000000000000..bf578468bb617 --- /dev/null +++ b/src/test/ui/const-generics/defaults/mismatch.rs @@ -0,0 +1,23 @@ +#![feature(const_generics)] +#![feature(const_generics_defaults)] +#![allow(incomplete_features)] + +pub struct Example; +pub struct Example2(T); +pub struct Example3(T); +pub struct Example4; + +fn main() { + let e: Example::<13> = (); + //~^ Error: mismatched types + let e: Example2:: = (); + //~^ Error: mismatched types + let e: Example3::<13, u32> = (); + //~^ Error: mismatched types + let e: Example3::<7> = (); + //~^ Error: mismatched types + // FIXME(const_generics_defaults): There should be a note for the error below, but it is + // missing. + let e: Example4::<7> = (); + //~^ Error: mismatched types +} diff --git a/src/test/ui/const-generics/defaults/mismatch.stderr b/src/test/ui/const-generics/defaults/mismatch.stderr new file mode 100644 index 0000000000000..c66eb4cd64594 --- /dev/null +++ b/src/test/ui/const-generics/defaults/mismatch.stderr @@ -0,0 +1,52 @@ +error[E0308]: mismatched types + --> $DIR/mismatch.rs:11:26 + | +LL | let e: Example::<13> = (); + | ------------- ^^ expected struct `Example`, found `()` + | | + | expected due to this + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:13:32 + | +LL | let e: Example2:: = (); + | ------------------- ^^ expected struct `Example2`, found `()` + | | + | expected due to this + | + = note: expected struct `Example2` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:15:32 + | +LL | let e: Example3::<13, u32> = (); + | ------------------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:17:26 + | +LL | let e: Example3::<7> = (); + | ------------- ^^ expected struct `Example3`, found `()` + | | + | expected due to this + | + = note: expected struct `Example3<7_usize>` + found unit type `()` + +error[E0308]: mismatched types + --> $DIR/mismatch.rs:21:26 + | +LL | let e: Example4::<7> = (); + | ------------- ^^ expected struct `Example4`, found `()` + | | + | expected due to this + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0308`.