about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs1
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs61
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs1
-rw-r--r--compiler/rustc_middle/src/query/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/consts.rs2
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs2
-rw-r--r--src/test/ui/const-generics/min_const_generics/const_default_first.rs9
-rw-r--r--src/test/ui/const-generics/min_const_generics/const_default_first.stderr8
-rw-r--r--src/test/ui/const-generics/min_const_generics/type_and_const_defaults.rs19
9 files changed, 72 insertions, 33 deletions
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index aa9c255c633..84f8ce5706a 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(":", &param.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 f4717fc08c7..98904206b21 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 fea7ea44c67..d055c275299 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 1666c6065b7..36162cfe924 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<const N: usize=3>` called on N would return 3.
+    /// parameter. e.g. `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)  }
     }
diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs
index 343438e975e..c78151271c1 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 8ac24a969f8..5f302f7d0a9 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 00000000000..ae82c85eb7e
--- /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<const N: usize=3, T> {
+//~^ 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 00000000000..f7a2e484fc6
--- /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<const N: usize=3, T> {
+   |                   ^
+
+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 2ce874c8bf4..435a63a5283 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<T=u32, const N: usize=3> {
   arr: [T; N]
@@ -12,3 +12,16 @@ trait BothTrait<T=u32, const N: usize=3> {}
 enum BothEnum<T=u32, const N: usize=3> {
   Dummy([T; N])
 }
+
+struct OppOrder<const N: usize=3, T=u32> {
+  arr: [T; N]
+}
+
+fn main() {
+  let _ = OppOrder::<3, u32> {
+    arr: [0,0,0],
+  };
+  let _ = Both::<u8, 1> {
+    arr: [0],
+  };
+}