From e4e5db4e4207e21c38c07640d44005dab022f1b8 Mon Sep 17 00:00:00 2001
From: kadmin <julianknodt@gmail.com>
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<Expr> 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<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_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<T: MutVisitor>(
             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(":", &param.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<hir::SyntheticTyParamKind>,
     },
-    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, &param.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<input_tys>`
         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<const N: usize = 3> {
+  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<const SIZE: usize = 5>() {}
 //~^ 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<const KIND: bool = true> {}
 //~^ 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<const N: usize = 3>;
+//~^ 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<const N: usize = 3>;
+   |                           ^
+   |
+   = 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 <github@varkor.com>
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<T: MutVisitor>(
             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(":", &param.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<T, U = [u8; std::mem::size_of::<T>()]>`
-                        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<T, U = [u8; std::mem::size_of::<T>()]>`
-                        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<const N: usize = 3> {
-  items: [u32; N]
-}
+pub struct ConstDefault<const N: usize = 3> {}
 
 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<const SIZE: usize = 5>() {}
-//~^ ERROR default values for const generic parameters are experimental
-
-fn main() {}
+fn foo<const SIZE: usize = 5usize>() {}
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<const SIZE: usize = 5>() {}
-   |                          ^^^
-   |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/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<const KIND: bool = true> {}
 //~^ 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<T=U, 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/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<const N: usize = 3>;
-//~^ 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<const N: usize = 3>;
-   |                           ^
-   |
-   = 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<A, B = Vec<C>, 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<A, B = Vec<C>, 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<T = Option<U>, 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=Bar>(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=T::Item>(_: 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 <rust@lcnr.de>
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<T = U, U = ()> {
     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<LabelSuggestion> },
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<const N: usize = 3> {}
+pub struct ConstDefault<const N: usize = 3>;
+
+impl<const N: usize> ConstDefault<N> {
+    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<T = u32, const N: usize> {
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<T = u32, const N: usize> {
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<T = u32, const N: usize> {
-    //~^ 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<const SIZE: usize = 5usize>() {}
+//~^ 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<const SIZE: usize = 5>() {}
-   |                            ^ cannot infer type for type `{integer}`
+LL | fn foo<const SIZE: usize = 5usize>() {}
+   |              ^^^^
 
 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 = [u8; N], const N: usize>(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 = [u8; N], const N: usize>(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 = [u8; std::mem::size_of::<T>()]>(T, U);
 // FIXME(const_generics_defaults): We still don't know how to deal with type defaults.
 struct Bar<T = [u8; N], const N: usize>(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 = Heap, T>(A, T);
-//~^ ERROR type parameters with a default must be trailing
+//~^ ERROR generic parameters with a default must be trailing
 
 struct Foo<A, B = Vec<C>, 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 = Heap, T>(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<A, B = Vec<C>, 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<T = Option<U>, 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=T::Item>(_: 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 <julianknodt@gmail.com>
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=i32>(_: T) {}
@@ -8,7 +8,7 @@ LL | fn avg<T=i32>(_: 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 <https://github.com/rust-lang/rust/issues/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<T=i32> S<T> {}
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 = Heap, T>(A, T);
 
 struct Foo<A, B = Vec<C>, 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 <julianknodt@gmail.com>
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<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 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<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 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<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 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<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 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<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 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<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 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<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])
+}

From ea2af704669f630c4184bb2c0befeb6cb7d78d29 Mon Sep 17 00:00:00 2001
From: kadmin <julianknodt@gmail.com>
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(":", &param.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<DefIndex, Lazy!(mir::Body<'tcx>)>,
     promoted_mir: Table<DefIndex, Lazy!(IndexVec<mir::Promoted, mir::Body<'tcx>>)>,
     mir_abstract_consts: Table<DefIndex, Lazy!(&'tcx [mir::abstract_const::Node<'tcx>])>,
+    const_defaults: Table<DefIndex, Lazy<rustc_middle::ty::Const<'tcx>>>,
     unused_generic_params: Table<DefIndex, Lazy<FiniteBitSet<u32>>>,
     // `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<DefIndex, Lazy<DefKey>>,
     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/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<const N: usize = 3>;
+
+#[stable(feature = "const_default_unstable", since="none")]
+pub struct ConstDefaultStable<const N: usize = {
+  #[stable(feature = "const_default_unstable_val", since="none")]
+  3
+}>;
+
+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<const KIND: bool = true> {}
+
+fn foo<const SIZE: usize = 5>() {}
+
+struct Range<const FROM: usize = 0, const LEN: usize = 0, const TO: usize = {FROM + LEN}>;
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<const KIND : bool = true> { }
+
+fn foo<const SIZE : usize = 5>() { }
+
+struct Range<const FROM : usize = 0, const LEN : usize = 0, const TO : usize =
+             { FROM + LEN }>;

From 7116bb5c33c1b0d12a7dade3fa20c9b0e2e08218 Mon Sep 17 00:00:00 2001
From: kadmin <julianknodt@gmail.com>
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(":", &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 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<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 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<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 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<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 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<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],
+  };
+}

From 33370fd9829c5bb843b117d11cc7e948f4b824f6 Mon Sep 17 00:00:00 2001
From: kadmin <julianknodt@gmail.com>
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<const N: usize=13>;
+pub struct Example2<T=u32, const N: usize=13>(T);
+pub struct Example3<const N: usize=13, T=u32>(T);
+pub struct Example4<const N: usize=13, const M: usize=4>;
+
+fn main() {
+  let e: Example::<13> = ();
+  //~^ Error: mismatched types
+  let e: Example2::<u32, 13> = ();
+  //~^ 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::<u32, 13> = ();
+   |          -------------------   ^^ 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`.