about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast/src/ast.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs8
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs1
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs11
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs3
-rw-r--r--compiler/rustc_middle/src/query/mod.rs6
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs24
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs8
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs1
-rw-r--r--compiler/rustc_middle/src/ty/print/mod.rs5
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs4
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs2
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs2
-rw-r--r--compiler/rustc_typeck/src/collect.rs3
-rw-r--r--src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs15
-rw-r--r--src/test/ui/const-generics/defaults/external.rs27
-rw-r--r--src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs14
17 files changed, 108 insertions, 27 deletions
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<Ty>,
         /// Span of the `const` keyword.
         kw_span: Span,
-
         /// Optional default value for the const generic param
         default: Option<AnonConst>,
     },
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 @@ 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<Symbol>)] {
         // 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 @@ 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 32378574527..fea7ea44c67 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 610528956d0..94722ad2051 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<DefIndex, Lazy<DefKey>>,
-    def_path_hashes: Table<DefIndex, Lazy<DefPathHash>>
+    def_path_hashes: Table<DefIndex, Lazy<DefPathHash>>,
+    const_defaults: Table<DefIndex, Lazy<rustc_middle::ty::Const<'tcx>>>,
 }
 
 #[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 @@ 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<const N: usize=3>` 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::{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 ef46a419964..78a9f2daeb3 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 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 @@ 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 1a765772e3c..8076aa7102c 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 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 @@ 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 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 @@ 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 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<const N: usize=3>;
+impl Defaulted {
+    pub fn new() -> Self {
+        Defaulted
+    }
+}
+impl<const N: usize> Defaulted<N> {
+    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<const N: usize=4>;
+impl Local {
+    fn new() -> Self {
+        Local
+    }
+}
+impl<const N: usize>Local<N> {
+    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<T=u32, const N: usize=3> {
+  arr: [T; N]
+}
+
+trait BothTrait<T=u32, const N: usize=3> {}
+
+enum BothEnum<T=u32, const N: usize=3> {
+  Dummy([T; N])
+}