From 9fe793ae5df4bc9ea73c8e55c66616bd6e5fe565 Mon Sep 17 00:00:00 2001 From: kadmin Date: Wed, 3 Mar 2021 06:38:02 +0000 Subject: [PATCH] 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 4b9bf273c70..7e82d7ff77d 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 e8891e471f9..3d0a9d553b0 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -953,6 +953,14 @@ fn get_expn_that_defined(&self, id: DefIndex, sess: &Session) -> ExpnId { 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 0f860d11dc2..7f8f5ef4427 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 @@ fn into_args(self) -> (DefId, DefId) { 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 32378574527..fea7ea44c67 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -1877,15 +1877,12 @@ fn encode_info_for_generics(&mut self, generics: &hir::Generics<'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 610528956d0..94722ad2051 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -313,7 +313,8 @@ fn encode(&self, buf: &mut Encoder) -> LazyTables<'tcx> { // `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 53a7d8528d3..1666c6065b7 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -93,6 +93,12 @@ 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 9cd4c09082c..6821efcdcc5 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -5,7 +5,7 @@ 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 @@ pub fn from_opt_const_arg_anon_const( let hir_id = tcx.hir().local_def_id_to_hir_id(def.did); let body_id = match tcx.hir().get(hir_id) { - hir::Node::AnonConst(ac) - | 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 @@ pub fn eval_usize(&self, tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>) -> u64 { .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 ef46a419964..78a9f2daeb3 100644 --- a/compiler/rustc_middle/src/ty/generics.rs +++ b/compiler/rustc_middle/src/ty/generics.rs @@ -120,8 +120,8 @@ pub fn own_defaults(&self) -> GenericParamCount { 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 @@ pub fn requires_monomorphization(&self, tcx: TyCtxt<'tcx>) -> bool { 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 e6b4739d0a2..ed10a156622 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 ad323df8a69..a47846828bd 100644 --- a/compiler/rustc_middle/src/ty/print/mod.rs +++ b/compiler/rustc_middle/src/ty/print/mod.rs @@ -205,10 +205,7 @@ fn generic_args_to_print( 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 1a765772e3c..8076aa7102c 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -505,10 +505,10 @@ fn inferred_kind( } } 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 49b6e506eb1..56ff9293dd8 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 @@ fn inferred_kind( } 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 7fd49ccc8e4..8ac24a969f8 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 933618e3a7b..85c5128591a 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -257,10 +257,11 @@ fn visit_generics(&mut self, generics: &'tcx hir::Generics<'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 00000000000..769b6e952dc --- /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 00000000000..b39e69ab10b --- /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 00000000000..2ce874c8bf4 --- /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]) +}