about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-04-25 14:00:49 +0000
committerbors <bors@rust-lang.org>2021-04-25 14:00:49 +0000
commit58bdb08947f5b3c18a2fbafc5cf36af7b5677d83 (patch)
tree0d765ee7eb8eeb41cf8e285dc319bc0c8c71836c
parent06f0adb34570ba83fee391abeb0bec0eec28a234 (diff)
parentd3e0d2f53dd69bf10b4260760e5fbaddc77c2a3d (diff)
downloadrust-58bdb08947f5b3c18a2fbafc5cf36af7b5677d83.tar.gz
rust-58bdb08947f5b3c18a2fbafc5cf36af7b5677d83.zip
Auto merge of #84299 - lcnr:const-generics-defaults-name-res, r=varkor
various const parameter defaults improvements

Actually resolve names in const parameter defaults, fixing `struct Foo<const N: usize = { usize::MAX }>`.

---
Split generic parameter ban rib for types and consts, allowing
```rust
#![feature(const_generics_defaults)]
struct Q;
struct Foo<T = Q, const Q: usize = 3>(T);
```

---
Remove the type/const ordering restriction if `const_generics_defaults` is active, even if `const_generics` is not. allowing us to stabilize and test const param defaults separately.

---
Check well formedness of const parameter defaults, eagerly emitting an error for `struct Foo<const N: usize = { 0 - 1 }>`

---
Do not forbid const parameters in param defaults, allowing `struct Foo<const N: usize, T = [u8; N]>(T)` and `struct Foo<const N: usize, const M: usize = N>`. Note that this should not change anything which is stabilized, as on stable, type parameters must be in front of const parameters, which means that type parameter defaults are only allowed if no const parameters exist.

We still forbid generic parameters inside of const param types.

r? `@varkor` `@petrochenkov`
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs2
-rw-r--r--compiler/rustc_feature/src/active.rs4
-rw-r--r--compiler/rustc_hir/src/hir.rs4
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs2
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs11
-rw-r--r--compiler/rustc_resolve/src/late.rs69
-rw-r--r--compiler/rustc_resolve/src/lib.rs58
-rw-r--r--compiler/rustc_typeck/src/astconv/generics.rs6
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs4
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs4
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs53
-rw-r--r--compiler/rustc_typeck/src/collect.rs39
-rw-r--r--src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs2
-rw-r--r--src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr18
-rw-r--r--src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr20
-rw-r--r--src/test/ui/const-generics/defaults/complex-generic-default-expr.rs14
-rw-r--r--src/test/ui/const-generics/defaults/const-default.rs4
-rw-r--r--src/test/ui/const-generics/defaults/const-param-as-default-value.rs23
-rw-r--r--src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs14
-rw-r--r--src/test/ui/const-generics/defaults/default-on-impl.full.stderr8
-rw-r--r--src/test/ui/const-generics/defaults/default-on-impl.min.stderr8
-rw-r--r--src/test/ui/const-generics/defaults/default-on-impl.rs11
-rw-r--r--src/test/ui/const-generics/defaults/default-param-wf-concrete.rs5
-rw-r--r--src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr9
-rw-r--r--src/test/ui/const-generics/defaults/external.rs2
-rw-r--r--src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr2
-rw-r--r--src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr22
-rw-r--r--src/test/ui/const-generics/defaults/intermixed-lifetime.rs10
-rw-r--r--src/test/ui/const-generics/defaults/mismatch.full.stderr (renamed from src/test/ui/const-generics/defaults/mismatch.stderr)10
-rw-r--r--src/test/ui/const-generics/defaults/mismatch.min.stderr52
-rw-r--r--src/test/ui/const-generics/defaults/mismatch.rs3
-rw-r--r--src/test/ui/const-generics/defaults/pretty-printing-ast.rs2
-rw-r--r--src/test/ui/const-generics/defaults/pretty-printing-ast.stdout2
-rw-r--r--src/test/ui/const-generics/defaults/repr-c-issue-82792.rs2
-rw-r--r--src/test/ui/const-generics/defaults/simple-defaults.min.stderr8
-rw-r--r--src/test/ui/const-generics/defaults/simple-defaults.rs10
-rw-r--r--src/test/ui/const-generics/defaults/type-default-const-param-name.rs19
-rw-r--r--src/test/ui/const-generics/defaults/wrong-order.full.stderr15
-rw-r--r--src/test/ui/const-generics/defaults/wrong-order.min.stderr4
-rw-r--r--src/test/ui/const-generics/defaults/wrong-order.rs4
-rw-r--r--src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.full.stderr17
-rw-r--r--src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr11
-rw-r--r--src/test/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.rs7
-rw-r--r--src/test/ui/generics/generic-non-trailing-defaults.rs1
-rw-r--r--src/test/ui/generics/generic-non-trailing-defaults.stderr9
45 files changed, 386 insertions, 218 deletions
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 8a3f7641596..6d6438920c0 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -754,7 +754,7 @@ fn validate_generic_param_order(
             GenericParamKind::Type { default: _ } => (ParamKindOrd::Type, ident),
             GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
                 let ty = pprust::ty_to_string(ty);
-                let unordered = sess.features_untracked().const_generics;
+                let unordered = sess.features_untracked().unordered_const_ty_params();
                 (ParamKindOrd::Const { unordered }, Some(format!("const {}: {}", param.ident, ty)))
             }
         };
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 72babb7aec1..7ae7e0094c6 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -63,6 +63,10 @@ macro_rules! declare_features {
                     _ => panic!("`{}` was not listed in `declare_features`", feature),
                 }
             }
+
+            pub fn unordered_const_ty_params(&self) -> bool {
+                self.const_generics || self.const_generics_defaults
+            }
         }
     };
 }
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 685429863fa..5baaaad7370 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -296,7 +296,9 @@ impl GenericArg<'_> {
         match self {
             GenericArg::Lifetime(_) => ast::ParamKindOrd::Lifetime,
             GenericArg::Type(_) => ast::ParamKindOrd::Type,
-            GenericArg::Const(_) => ast::ParamKindOrd::Const { unordered: feats.const_generics },
+            GenericArg::Const(_) => {
+                ast::ParamKindOrd::Const { unordered: feats.unordered_const_ty_params() }
+            }
         }
     }
 }
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index d30a8693959..c8fdbc30d15 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -36,7 +36,7 @@ impl GenericParamDefKind {
             GenericParamDefKind::Lifetime => ast::ParamKindOrd::Lifetime,
             GenericParamDefKind::Type { .. } => ast::ParamKindOrd::Type,
             GenericParamDefKind::Const { .. } => {
-                ast::ParamKindOrd::Const { unordered: tcx.features().const_generics }
+                ast::ParamKindOrd::Const { unordered: tcx.features().unordered_const_ty_params() }
             }
         }
     }
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 87e28f7fcc5..c5f12c0c691 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -472,17 +472,6 @@ impl<'a> Resolver<'a> {
                 );
                 err
             }
-            ResolutionError::ParamInAnonConstInTyDefault(name) => {
-                let mut err = self.session.struct_span_err(
-                    span,
-                    "constant values inside of type parameter defaults must not depend on generic parameters",
-                );
-                err.span_label(
-                    span,
-                    format!("the anonymous constant must not depend on the parameter `{}`", name),
-                );
-                err
-            }
             ResolutionError::ParamInNonTrivialAnonConst { name, is_type } => {
                 let mut err = self.session.struct_span_err(
                     span,
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 9321f11f659..92f21191de4 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -555,18 +555,23 @@ 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(ForwardGenericParamBanRibKind);
-        let mut found_default = false;
-        default_ban_rib.bindings.extend(generics.params.iter().filter_map(
-            |param| match param.kind {
-                GenericParamKind::Type { default: Some(_), .. }
-                | GenericParamKind::Const { default: Some(_), .. } => {
-                    found_default = true;
-                    Some((Ident::with_dummy_span(param.ident.name), Res::Err))
+        let mut forward_ty_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
+        let mut forward_const_ban_rib = Rib::new(ForwardGenericParamBanRibKind);
+        for param in generics.params.iter() {
+            match param.kind {
+                GenericParamKind::Type { .. } => {
+                    forward_ty_ban_rib
+                        .bindings
+                        .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
                 }
-                _ => None,
-            },
-        ));
+                GenericParamKind::Const { .. } => {
+                    forward_const_ban_rib
+                        .bindings
+                        .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
+                }
+                GenericParamKind::Lifetime => {}
+            }
+        }
 
         // rust-lang/rust#61631: The type `Self` is essentially
         // another type parameter. For ADTs, we consider it
@@ -579,7 +584,7 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
         // such as in the case of `trait Add<Rhs = Self>`.)
         if self.diagnostic_metadata.current_self_item.is_some() {
             // (`Some` if + only if we are in ADT's generics.)
-            default_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
+            forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
         }
 
         for param in &generics.params {
@@ -591,32 +596,38 @@ 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, ForwardGenericParamBanRibKind, |this| {
-                            // HACK: We use an empty `ForwardGenericParamBanRibKind` here which
-                            // is only used to forbid the use of const parameters inside of
-                            // type defaults.
-                            //
-                            // While the rib name doesn't really fit here, it does allow us to use the same
-                            // code for both const and type parameters.
-                            this.visit_ty(ty);
-                        });
-                        default_ban_rib = self.ribs[TypeNS].pop().unwrap();
+                        self.ribs[TypeNS].push(forward_ty_ban_rib);
+                        self.ribs[ValueNS].push(forward_const_ban_rib);
+                        self.visit_ty(ty);
+                        forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap();
+                        forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap();
                     }
 
                     // Allow all following defaults to refer to this type parameter.
-                    default_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
+                    forward_ty_ban_rib.bindings.remove(&Ident::with_dummy_span(param.ident.name));
                 }
-                GenericParamKind::Const { ref ty, kw_span: _, default: _ } => {
-                    // FIXME(const_generics_defaults): handle `default` value here
-                    for bound in &param.bounds {
-                        self.visit_param_bound(bound);
-                    }
+                GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
+                    // Const parameters can't have param bounds.
+                    assert!(param.bounds.is_empty());
+
                     self.ribs[TypeNS].push(Rib::new(ConstParamTyRibKind));
                     self.ribs[ValueNS].push(Rib::new(ConstParamTyRibKind));
                     self.visit_ty(ty);
                     self.ribs[TypeNS].pop().unwrap();
                     self.ribs[ValueNS].pop().unwrap();
+
+                    if let Some(ref expr) = default {
+                        self.ribs[TypeNS].push(forward_ty_ban_rib);
+                        self.ribs[ValueNS].push(forward_const_ban_rib);
+                        self.visit_anon_const(expr);
+                        forward_const_ban_rib = self.ribs[ValueNS].pop().unwrap();
+                        forward_ty_ban_rib = self.ribs[TypeNS].pop().unwrap();
+                    }
+
+                    // Allow all following defaults to refer to this const parameter.
+                    forward_const_ban_rib
+                        .bindings
+                        .remove(&Ident::with_dummy_span(param.ident.name));
                 }
             }
         }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 129954381c9..1d1969f7e78 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -239,8 +239,6 @@ enum ResolutionError<'a> {
     ForwardDeclaredTyParam, // FIXME(const_generics_defaults)
     /// ERROR E0770: the type of const parameters must not depend on other generic parameters.
     ParamInTyOfConstParam(Symbol),
-    /// constant values inside of type parameter defaults must not depend on generic parameters.
-    ParamInAnonConstInTyDefault(Symbol),
     /// generic parameters must not be used inside const evaluations.
     ///
     /// This error is only emitted when using `min_const_generics`.
@@ -2672,26 +2670,18 @@ impl<'a> Resolver<'a> {
                 }
             }
             Res::Def(DefKind::TyParam, _) | Res::SelfTy(..) => {
-                let mut in_ty_param_default = false;
                 for rib in ribs {
-                    let has_generic_params = match rib.kind {
+                    let has_generic_params: HasGenericParams = match rib.kind {
                         NormalRibKind
                         | ClosureOrAsyncRibKind
                         | AssocItemRibKind
                         | ModuleRibKind(..)
-                        | MacroDefinition(..) => {
+                        | MacroDefinition(..)
+                        | ForwardGenericParamBanRibKind => {
                             // Nothing to do. Continue.
                             continue;
                         }
 
-                        // We only forbid constant items if we are inside of type defaults,
-                        // for example `struct Foo<T, U = [u8; std::mem::size_of::<T>()]>`
-                        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;
-                        }
                         ConstantItemRibKind(trivial, _) => {
                             let features = self.session.features_untracked();
                             // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
@@ -2720,19 +2710,7 @@ impl<'a> Resolver<'a> {
                                 }
                             }
 
-                            if in_ty_param_default {
-                                if record_used {
-                                    self.report_error(
-                                        span,
-                                        ResolutionError::ParamInAnonConstInTyDefault(
-                                            rib_ident.name,
-                                        ),
-                                    );
-                                }
-                                return Res::Err;
-                            } else {
-                                continue;
-                            }
+                            continue;
                         }
 
                         // This was an attempt to use a type parameter outside its scope.
@@ -2770,23 +2748,15 @@ impl<'a> Resolver<'a> {
                     ribs.next();
                 }
 
-                let mut in_ty_param_default = false;
                 for rib in ribs {
                     let has_generic_params = match rib.kind {
                         NormalRibKind
                         | ClosureOrAsyncRibKind
                         | AssocItemRibKind
                         | ModuleRibKind(..)
-                        | MacroDefinition(..) => continue,
-
-                        // We only forbid constant items if we are inside of type defaults,
-                        // for example `struct Foo<T, U = [u8; std::mem::size_of::<T>()]>`
-                        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;
-                        }
+                        | MacroDefinition(..)
+                        | ForwardGenericParamBanRibKind => continue,
+
                         ConstantItemRibKind(trivial, _) => {
                             let features = self.session.features_untracked();
                             // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
@@ -2808,19 +2778,7 @@ impl<'a> Resolver<'a> {
                                 return Res::Err;
                             }
 
-                            if in_ty_param_default {
-                                if record_used {
-                                    self.report_error(
-                                        span,
-                                        ResolutionError::ParamInAnonConstInTyDefault(
-                                            rib_ident.name,
-                                        ),
-                                    );
-                                }
-                                return Res::Err;
-                            } else {
-                                continue;
-                            }
+                            continue;
                         }
 
                         ItemRibKind(has_generic_params) => has_generic_params,
diff --git a/compiler/rustc_typeck/src/astconv/generics.rs b/compiler/rustc_typeck/src/astconv/generics.rs
index 7a297f2c65f..2bbb38c294d 100644
--- a/compiler/rustc_typeck/src/astconv/generics.rs
+++ b/compiler/rustc_typeck/src/astconv/generics.rs
@@ -286,7 +286,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                                         ParamKindOrd::Const {
                                                             unordered: tcx
                                                                 .features()
-                                                                .const_generics,
+                                                                .unordered_const_ty_params(),
                                                         }
                                                     }
                                                 },
@@ -309,7 +309,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                             GenericArg::Lifetime(_) => ParamKindOrd::Lifetime,
                                             GenericArg::Type(_) => ParamKindOrd::Type,
                                             GenericArg::Const(_) => ParamKindOrd::Const {
-                                                unordered: tcx.features().const_generics,
+                                                unordered: tcx
+                                                    .features()
+                                                    .unordered_const_ty_params(),
                                             },
                                         }),
                                         Some(&format!(
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index b6de491911a..62a1584d16b 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -513,7 +513,9 @@ 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 {
-                            tcx.const_param_default(param.def_id).into()
+                            tcx.const_param_default(param.def_id)
+                                .subst_spanned(tcx, substs.unwrap(), Some(self.span))
+                                .into()
                         } else {
                             if infer_args {
                                 self.astconv.ct_infer(ty, Some(param), self.span).into()
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index 9ace4550421..a50f8e1c655 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -1446,7 +1446,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     GenericParamDefKind::Const { has_default, .. } => {
                         if !infer_args && has_default {
-                            tcx.const_param_default(param.def_id).into()
+                            tcx.const_param_default(param.def_id)
+                                .subst_spanned(tcx, substs.unwrap(), Some(self.span))
+                                .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 887cc42a1dd..26871d6f028 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -728,20 +728,36 @@ fn check_where_clauses<'tcx, 'fcx>(
     //
     // Here, the default `Vec<[u32]>` is not WF because `[u32]: Sized` does not hold.
     for param in &generics.params {
-        if let GenericParamDefKind::Type { .. } = param.kind {
-            if is_our_default(&param) {
-                let ty = fcx.tcx.type_of(param.def_id);
-                // Ignore dependent defaults -- that is, where the default of one type
-                // parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
-                // be sure if it will error or not as user might always specify the other.
-                if !ty.needs_subst() {
+        match param.kind {
+            GenericParamDefKind::Type { .. } => {
+                if is_our_default(&param) {
+                    let ty = fcx.tcx.type_of(param.def_id);
+                    // Ignore dependent defaults -- that is, where the default of one type
+                    // parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
+                    // be sure if it will error or not as user might always specify the other.
+                    if !ty.needs_subst() {
+                        fcx.register_wf_obligation(
+                            ty.into(),
+                            fcx.tcx.def_span(param.def_id),
+                            ObligationCauseCode::MiscObligation,
+                        );
+                    }
+                }
+            }
+            GenericParamDefKind::Const { .. } => {
+                // FIXME(const_generics_defaults): Figure out if this
+                // is the behavior we want, see the comment further below.
+                if is_our_default(&param) {
+                    let default_ct = tcx.const_param_default(param.def_id);
                     fcx.register_wf_obligation(
-                        ty.into(),
+                        default_ct.into(),
                         fcx.tcx.def_span(param.def_id),
                         ObligationCauseCode::MiscObligation,
                     );
                 }
             }
+            // Doesn't have defaults.
+            GenericParamDefKind::Lifetime => {}
         }
     }
 
@@ -774,14 +790,25 @@ fn check_where_clauses<'tcx, 'fcx>(
                 fcx.tcx.mk_param_from_def(param)
             }
             GenericParamDefKind::Const { .. } => {
+                // FIXME(const_generics_defaults): I(@lcnr) feel like always
+                // using the const parameter is the right choice here, even
+                // if it needs substs.
+                //
+                // Before stabilizing this we probably want to get some tests
+                // where this makes a difference and figure out what's the exact
+                // behavior we want here.
+
+                // If the param has a default, ...
                 if is_our_default(param) {
                     let default_ct = tcx.const_param_default(param.def_id);
-                    // Const params currently have to be concrete.
-                    assert!(!default_ct.needs_subst());
-                    default_ct.into()
-                } else {
-                    fcx.tcx.mk_param_from_def(param)
+                    // ... and it's not a dependent default, ...
+                    if !default_ct.needs_subst() {
+                        // ... then substitute it with the default.
+                        return default_ct.into();
+                    }
                 }
+
+                fcx.tcx.mk_param_from_def(param)
             }
         }
     });
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 3692642b6e2..46ee8245432 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -1327,13 +1327,13 @@ fn has_late_bound_regions<'tcx>(tcx: TyCtxt<'tcx>, node: Node<'tcx>) -> Option<S
     }
 }
 
-struct AnonConstInParamListDetector {
-    in_param_list: bool,
-    found_anon_const_in_list: bool,
+struct AnonConstInParamTyDetector {
+    in_param_ty: bool,
+    found_anon_const_in_param_ty: bool,
     ct: HirId,
 }
 
-impl<'v> Visitor<'v> for AnonConstInParamListDetector {
+impl<'v> Visitor<'v> for AnonConstInParamTyDetector {
     type Map = intravisit::ErasedMap<'v>;
 
     fn nested_visit_map(&mut self) -> NestedVisitorMap<Self::Map> {
@@ -1341,15 +1341,17 @@ impl<'v> Visitor<'v> for AnonConstInParamListDetector {
     }
 
     fn visit_generic_param(&mut self, p: &'v hir::GenericParam<'v>) {
-        let prev = self.in_param_list;
-        self.in_param_list = true;
-        intravisit::walk_generic_param(self, p);
-        self.in_param_list = prev;
+        if let GenericParamKind::Const { ref ty, default: _ } = p.kind {
+            let prev = self.in_param_ty;
+            self.in_param_ty = true;
+            self.visit_ty(ty);
+            self.in_param_ty = prev;
+        }
     }
 
     fn visit_anon_const(&mut self, c: &'v hir::AnonConst) {
-        if self.in_param_list && self.ct == c.hir_id {
-            self.found_anon_const_in_list = true;
+        if self.in_param_ty && self.ct == c.hir_id {
+            self.found_anon_const_in_param_ty = true;
         } else {
             intravisit::walk_anon_const(self, c)
         }
@@ -1377,27 +1379,24 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
             let parent_id = tcx.hir().get_parent_item(hir_id);
             let parent_def_id = tcx.hir().local_def_id(parent_id);
 
-            let mut in_param_list = false;
+            let mut in_param_ty = false;
             for (_parent, node) in tcx.hir().parent_iter(hir_id) {
                 if let Some(generics) = node.generics() {
-                    let mut visitor = AnonConstInParamListDetector {
-                        in_param_list: false,
-                        found_anon_const_in_list: false,
+                    let mut visitor = AnonConstInParamTyDetector {
+                        in_param_ty: false,
+                        found_anon_const_in_param_ty: false,
                         ct: hir_id,
                     };
 
                     visitor.visit_generics(generics);
-                    in_param_list = visitor.found_anon_const_in_list;
+                    in_param_ty = visitor.found_anon_const_in_param_ty;
                     break;
                 }
             }
 
-            if in_param_list {
+            if in_param_ty {
                 // We do not allow generic parameters in anon consts if we are inside
-                // of a param list.
-                //
-                // This affects both default type bindings, e.g. `struct<T, U = [u8; std::mem::size_of::<T>()]>(T, U)`,
-                // and the types of const parameters, e.g. `struct V<const N: usize, const M: [u8; N]>();`.
+                // of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
                 None
             } else if tcx.lazy_normalization() {
                 // HACK(eddyb) this provides the correct generics when
diff --git a/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs
index 769b6e952dc..6514409698e 100644
--- a/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs
+++ b/src/test/ui/const-generics/defaults/auxiliary/const_defaulty.rs
@@ -1,4 +1,4 @@
-#![feature(const_generics)]
+#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
 
diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr
new file mode 100644
index 00000000000..e0e2b6c69f2
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.full.stderr
@@ -0,0 +1,18 @@
+error: constant expression depends on a generic parameter
+  --> $DIR/complex-generic-default-expr.rs:6:34
+   |
+LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
+   |                                  ^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: constant expression depends on a generic parameter
+  --> $DIR/complex-generic-default-expr.rs:10:21
+   |
+LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
+   |                     ^^^^^^^^^
+   |
+   = note: this may fail depending on what value the parameter takes
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr
new file mode 100644
index 00000000000..58abd8db9f0
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.min.stderr
@@ -0,0 +1,20 @@
+error: generic parameters may not be used in const operations
+  --> $DIR/complex-generic-default-expr.rs:6:47
+   |
+LL | struct Foo<const N: usize, const M: usize = { N + 1 }>;
+   |                                               ^ cannot perform const operation using `N`
+   |
+   = help: const parameters may only be used as standalone arguments, i.e. `N`
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error: generic parameters may not be used in const operations
+  --> $DIR/complex-generic-default-expr.rs:10:62
+   |
+LL | struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
+   |                                                              ^ cannot perform const operation using `T`
+   |
+   = note: type parameters may not be used in const expressions
+   = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
+
+error: aborting due to 2 previous errors
+
diff --git a/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs
new file mode 100644
index 00000000000..a7b712f7b4b
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/complex-generic-default-expr.rs
@@ -0,0 +1,14 @@
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: usize, const M: usize = { N + 1 }>;
+//[full]~^ ERROR constant expression depends on a generic parameter
+//[min]~^^ ERROR generic parameters may not be used in const operations
+
+struct Bar<T, const TYPE_SIZE: usize = { std::mem::size_of::<T>() }>(T);
+//[full]~^ ERROR constant expression depends on a generic parameter
+//[min]~^^ ERROR generic parameters may not be used in const operations
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/const-default.rs b/src/test/ui/const-generics/defaults/const-default.rs
index 150c70770ae..4fa21b8b1fb 100644
--- a/src/test/ui/const-generics/defaults/const-default.rs
+++ b/src/test/ui/const-generics/defaults/const-default.rs
@@ -1,6 +1,6 @@
 // run-pass
-
-#![feature(const_generics)]
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
 
diff --git a/src/test/ui/const-generics/defaults/const-param-as-default-value.rs b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs
new file mode 100644
index 00000000000..59ac261f44f
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/const-param-as-default-value.rs
@@ -0,0 +1,23 @@
+// run-pass
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
+struct Foo<const N: usize, const M: usize = N>([u8; N], [u8; M]);
+
+fn foo<const N: usize>() -> Foo<N> {
+    let x = [0; N];
+    Foo(x, x)
+}
+
+// To check that we actually apply the correct substs for const param defaults.
+fn concrete_foo() -> Foo<13> {
+    Foo(Default::default(), Default::default())
+}
+
+
+fn main() {
+    let val = foo::<13>();
+    assert_eq!(val.0, val.1);
+
+    let val = concrete_foo();
+    assert_eq!(val.0, val.1);
+}
diff --git a/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs
new file mode 100644
index 00000000000..3f534ca0308
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/const-param-in-ty-defaults.rs
@@ -0,0 +1,14 @@
+// run-pass
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
+struct Foo<const N: usize, T = [u8; N]>(T);
+
+impl<const N: usize> Foo<N> {
+    fn new() -> Self {
+        Foo([0; N])
+    }
+}
+
+fn main() {
+    assert_eq!(Foo::new().0, [0; 10]);
+}
diff --git a/src/test/ui/const-generics/defaults/default-on-impl.full.stderr b/src/test/ui/const-generics/defaults/default-on-impl.full.stderr
new file mode 100644
index 00000000000..c417a26842e
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/default-on-impl.full.stderr
@@ -0,0 +1,8 @@
+error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/default-on-impl.rs:8:12
+   |
+LL | impl<const N: usize = 1> Foo<N> {}
+   |            ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/defaults/default-on-impl.min.stderr b/src/test/ui/const-generics/defaults/default-on-impl.min.stderr
new file mode 100644
index 00000000000..c417a26842e
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/default-on-impl.min.stderr
@@ -0,0 +1,8 @@
+error: defaults for const parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
+  --> $DIR/default-on-impl.rs:8:12
+   |
+LL | impl<const N: usize = 1> Foo<N> {}
+   |            ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/defaults/default-on-impl.rs b/src/test/ui/const-generics/defaults/default-on-impl.rs
new file mode 100644
index 00000000000..735549defea
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/default-on-impl.rs
@@ -0,0 +1,11 @@
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
+
+struct Foo<const N: usize>;
+
+impl<const N: usize = 1> Foo<N> {}
+//~^ ERROR defaults for const parameters are only allowed
+
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs b/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs
new file mode 100644
index 00000000000..4bb56c6a1c0
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/default-param-wf-concrete.rs
@@ -0,0 +1,5 @@
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
+struct Foo<const N: u8 = { 255 + 1 }>;
+//~^ ERROR evaluation of constant value failed
+fn main() {}
diff --git a/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr b/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr
new file mode 100644
index 00000000000..8464ea98bf6
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/default-param-wf-concrete.stderr
@@ -0,0 +1,9 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/default-param-wf-concrete.rs:3:28
+   |
+LL | struct Foo<const N: u8 = { 255 + 1 }>;
+   |                            ^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/const-generics/defaults/external.rs b/src/test/ui/const-generics/defaults/external.rs
index b39e69ab10b..32acf567cf2 100644
--- a/src/test/ui/const-generics/defaults/external.rs
+++ b/src/test/ui/const-generics/defaults/external.rs
@@ -1,5 +1,7 @@
 // aux-build:const_defaulty.rs
 // check-pass
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
 
diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr
index c4a666a829d..29d835e36c6 100644
--- a/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr
+++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.full.stderr
@@ -1,5 +1,5 @@
 error: lifetime parameters must be declared prior to const parameters
-  --> $DIR/intermixed-lifetime.rs:6:28
+  --> $DIR/intermixed-lifetime.rs:7:28
    |
 LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
    |           -----------------^^---------- help: reorder the parameters: lifetimes, then consts and types: `<'a, const N: usize, T = u32>`
diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr
index 69a490978d1..985e7b655ec 100644
--- a/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr
+++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.min.stderr
@@ -1,26 +1,14 @@
 error: lifetime parameters must be declared prior to const parameters
-  --> $DIR/intermixed-lifetime.rs:6:28
+  --> $DIR/intermixed-lifetime.rs:7:28
    |
 LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
-   |           -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
+   |           -----------------^^---------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const N: usize, T = u32>`
 
-error: type parameters must be declared prior to const parameters
-  --> $DIR/intermixed-lifetime.rs:6:32
-   |
-LL | struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
-   |           ---------------------^------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
-
-error: lifetime parameters must be declared prior to const parameters
+error: lifetime parameters must be declared prior to type parameters
   --> $DIR/intermixed-lifetime.rs:10:37
    |
 LL | struct Bar<const N: usize, T = u32, 'a>(&'a (), T);
-   |           --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
-
-error: type parameters must be declared prior to const parameters
-  --> $DIR/intermixed-lifetime.rs:10:28
-   |
-LL | struct Bar<const N: usize, T = u32, 'a>(&'a (), T);
-   |           -----------------^----------- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
+   |           --------------------------^^- help: reorder the parameters: lifetimes, then types, then consts: `<'a, const N: usize, T = u32>`
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs
index 9e83bf92a59..307e3aaf1fb 100644
--- a/src/test/ui/const-generics/defaults/intermixed-lifetime.rs
+++ b/src/test/ui/const-generics/defaults/intermixed-lifetime.rs
@@ -1,15 +1,13 @@
-// revisions: full min
 // Checks that lifetimes cannot be interspersed between consts and types.
+// revisions: full min
 #![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
 
 struct Foo<const N: usize, 'a, T = u32>(&'a (), T);
 //~^ Error lifetime parameters must be declared prior to const parameters
-//[min]~^^ Error type parameters must be declared prior to const parameters
 
 struct Bar<const N: usize, T = u32, 'a>(&'a (), T);
-//[full]~^ Error lifetime parameters must be declared prior to type parameters
-//[min]~^^ Error type parameters must be declared prior to const parameters
-//[min]~| Error lifetime parameters must be declared prior to const parameters
+//~^ Error lifetime parameters must be declared prior to type parameters
 
 fn main() {}
diff --git a/src/test/ui/const-generics/defaults/mismatch.stderr b/src/test/ui/const-generics/defaults/mismatch.full.stderr
index ff72c71c40f..be4f364d8ee 100644
--- a/src/test/ui/const-generics/defaults/mismatch.stderr
+++ b/src/test/ui/const-generics/defaults/mismatch.full.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:11:28
+  --> $DIR/mismatch.rs:12:28
    |
 LL |     let e: Example::<13> = ();
    |            -------------   ^^ expected struct `Example`, found `()`
@@ -7,7 +7,7 @@ LL |     let e: Example::<13> = ();
    |            expected due to this
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:13:34
+  --> $DIR/mismatch.rs:14:34
    |
 LL |     let e: Example2::<u32, 13> = ();
    |            -------------------   ^^ expected struct `Example2`, found `()`
@@ -18,7 +18,7 @@ LL |     let e: Example2::<u32, 13> = ();
            found unit type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:15:34
+  --> $DIR/mismatch.rs:16:34
    |
 LL |     let e: Example3::<13, u32> = ();
    |            -------------------   ^^ expected struct `Example3`, found `()`
@@ -29,7 +29,7 @@ LL |     let e: Example3::<13, u32> = ();
            found unit type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:17:28
+  --> $DIR/mismatch.rs:18:28
    |
 LL |     let e: Example3::<7> = ();
    |            -------------   ^^ expected struct `Example3`, found `()`
@@ -40,7 +40,7 @@ LL |     let e: Example3::<7> = ();
            found unit type `()`
 
 error[E0308]: mismatched types
-  --> $DIR/mismatch.rs:21:28
+  --> $DIR/mismatch.rs:22:28
    |
 LL |     let e: Example4::<7> = ();
    |            -------------   ^^ expected struct `Example4`, found `()`
diff --git a/src/test/ui/const-generics/defaults/mismatch.min.stderr b/src/test/ui/const-generics/defaults/mismatch.min.stderr
new file mode 100644
index 00000000000..be4f364d8ee
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/mismatch.min.stderr
@@ -0,0 +1,52 @@
+error[E0308]: mismatched types
+  --> $DIR/mismatch.rs:12:28
+   |
+LL |     let e: Example::<13> = ();
+   |            -------------   ^^ expected struct `Example`, found `()`
+   |            |
+   |            expected due to this
+
+error[E0308]: mismatched types
+  --> $DIR/mismatch.rs:14:34
+   |
+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:16:34
+   |
+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:18:28
+   |
+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:22:28
+   |
+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`.
diff --git a/src/test/ui/const-generics/defaults/mismatch.rs b/src/test/ui/const-generics/defaults/mismatch.rs
index d85b756f538..68a640c0a08 100644
--- a/src/test/ui/const-generics/defaults/mismatch.rs
+++ b/src/test/ui/const-generics/defaults/mismatch.rs
@@ -1,4 +1,5 @@
-#![feature(const_generics)]
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
 #![feature(const_generics_defaults)]
 #![allow(incomplete_features)]
 
diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs
index a25d4baca1a..7a57950dfc9 100644
--- a/src/test/ui/const-generics/defaults/pretty-printing-ast.rs
+++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.rs
@@ -10,4 +10,4 @@ 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}>;
+struct Range<const FROM: usize = 0, const LEN: usize = 0, const TO: usize = FROM>;
diff --git a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout
index f7a1d2ca4b2..f549993c413 100644
--- a/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout
+++ b/src/test/ui/const-generics/defaults/pretty-printing-ast.stdout
@@ -17,4 +17,4 @@ 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>;
diff --git a/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs
index 18ecf467299..c64c2974c8f 100644
--- a/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs
+++ b/src/test/ui/const-generics/defaults/repr-c-issue-82792.rs
@@ -6,7 +6,7 @@
 #![allow(incomplete_features)]
 
 #[repr(C)]
-pub struct Loaf<T: Sized, const N: usize = 1usize> {
+pub struct Loaf<T: Sized, const N: usize = 1> {
     head: [T; N],
     slice: [T],
 }
diff --git a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr b/src/test/ui/const-generics/defaults/simple-defaults.min.stderr
deleted file mode 100644
index 0746c64ac8c..00000000000
--- a/src/test/ui/const-generics/defaults/simple-defaults.min.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: type parameters must be declared prior to const parameters
-  --> $DIR/simple-defaults.rs:8:40
-   |
-LL | struct FixedOutput<'a, const N: usize, T=u32> {
-   |                   ---------------------^----- help: reorder the parameters: lifetimes, then types, then consts: `<'a, T = u32, const N: usize>`
-
-error: aborting due to previous error
-
diff --git a/src/test/ui/const-generics/defaults/simple-defaults.rs b/src/test/ui/const-generics/defaults/simple-defaults.rs
index cb66c7769bb..c003cb2c5a6 100644
--- a/src/test/ui/const-generics/defaults/simple-defaults.rs
+++ b/src/test/ui/const-generics/defaults/simple-defaults.rs
@@ -1,12 +1,12 @@
-// [full] run-pass
-// revisions: min full
-// Checks some basic test cases for defaults.
+// run-pass
+// Checks that type param defaults are allowed after const params.
+// revisions: full min
 #![cfg_attr(full, feature(const_generics))]
-#![cfg_attr(full, allow(incomplete_features))]
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
 #![allow(dead_code)]
 
 struct FixedOutput<'a, const N: usize, T=u32> {
-    //[min]~^ ERROR type parameters must be declared prior to const parameters
     out: &'a [T; N],
 }
 
diff --git a/src/test/ui/const-generics/defaults/type-default-const-param-name.rs b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs
new file mode 100644
index 00000000000..e68075ee3c6
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/type-default-const-param-name.rs
@@ -0,0 +1,19 @@
+// check-pass
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
+
+struct N;
+
+struct Foo<const N: usize = 1, T = N>(T);
+
+impl Foo {
+    fn new() -> Self {
+        Foo(N)
+    }
+}
+
+fn main() {
+    let Foo::<1, N>(N) = Foo::new();
+}
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 accc73134d8..eb0bcb28215 100644
--- a/src/test/ui/const-generics/defaults/wrong-order.full.stderr
+++ b/src/test/ui/const-generics/defaults/wrong-order.full.stderr
@@ -1,19 +1,8 @@
 error: generic parameters with a default must be trailing
-  --> $DIR/wrong-order.rs:4:10
+  --> $DIR/wrong-order.rs:6:10
    |
 LL | struct A<T = u32, const N: usize> {
    |          ^
-   |
-   = note: using type defaults and const parameters in the same parameter list is currently not permitted
-
-warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/wrong-order.rs:2:27
-   |
-LL | #![cfg_attr(full, feature(const_generics))]
-   |                           ^^^^^^^^^^^^^^
-   |
-   = note: `#[warn(incomplete_features)]` on by default
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
 
-error: aborting due to previous error; 1 warning emitted
+error: aborting due to previous error
 
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 c8f1d471b24..eb0bcb28215 100644
--- a/src/test/ui/const-generics/defaults/wrong-order.min.stderr
+++ b/src/test/ui/const-generics/defaults/wrong-order.min.stderr
@@ -1,10 +1,8 @@
 error: generic parameters with a default must be trailing
-  --> $DIR/wrong-order.rs:4:10
+  --> $DIR/wrong-order.rs:6:10
    |
 LL | struct A<T = u32, const N: usize> {
    |          ^
-   |
-   = note: using type defaults and const parameters in the same parameter list is currently not permitted
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/defaults/wrong-order.rs b/src/test/ui/const-generics/defaults/wrong-order.rs
index 5c2d9b8ad47..88e9e96ba43 100644
--- a/src/test/ui/const-generics/defaults/wrong-order.rs
+++ b/src/test/ui/const-generics/defaults/wrong-order.rs
@@ -1,5 +1,7 @@
 // revisions: full min
-#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
+#![cfg_attr(full, feature(const_generics))]
+#![feature(const_generics_defaults)]
+#![allow(incomplete_features)]
 
 struct A<T = u32, const N: usize> {
     //~^ ERROR generic parameters with a default must be trailing
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 c2b7b206653..e8fd9e7769b 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,22 +1,17 @@
 error: generic parameters with a default must be trailing
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
    |            ^
    |
    = note: using type defaults and const parameters in the same parameter list is currently not permitted
 
-error: constant values inside of type parameter defaults must not depend on generic parameters
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44
-   |
-LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
-   |                                            ^ the anonymous constant must not depend on the parameter `T`
-
-error: constant values inside of type parameter defaults must not depend on generic parameters
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21
+error[E0128]: generic parameters with a default cannot use forward declared identifiers
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
-   |                     ^ the anonymous constant must not depend on the parameter `N`
+   |                     ^ defaulted generic 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/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 4a462c328bf..5fa6423306c 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,5 +1,5 @@
 error: generic parameters with a default must be trailing
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:12
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:12
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
    |            ^
@@ -7,7 +7,7 @@ LL | struct Bar<T = [u8; N], const N: usize>(T);
    = note: using type defaults and const parameters in the same parameter list is currently not permitted
 
 error: generic parameters may not be used in const operations
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:6:44
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:5:44
    |
 LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
    |                                            ^ cannot perform const operation using `T`
@@ -15,11 +15,12 @@ LL | struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
    = note: type parameters may not be used in const expressions
    = help: use `#![feature(const_generics)]` and `#![feature(const_evaluatable_checked)]` to allow generic const expressions
 
-error: constant values inside of type parameter defaults must not depend on generic parameters
-  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:11:21
+error[E0128]: generic parameters with a default cannot use forward declared identifiers
+  --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21
    |
 LL | struct Bar<T = [u8; N], const N: usize>(T);
-   |                     ^ the anonymous constant must not depend on the parameter `N`
+   |                     ^ defaulted generic parameters cannot be forward declared
 
 error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0128`.
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 c7be8bdaf9c..76c1b84aef5 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
@@ -1,15 +1,12 @@
 // revisions: full min
-
 #![cfg_attr(full, feature(const_generics))]
 #![cfg_attr(full, allow(incomplete_features))]
 
 struct Foo<T, U = [u8; std::mem::size_of::<T>()]>(T, U);
-//[full]~^ ERROR constant values inside of type parameter defaults
-//[min]~^^ ERROR generic parameters may not be used in const operations
+//[min]~^ ERROR generic parameters may not be used in const operations
 
-// 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 generic parameters with a default cannot use forward declared identifiers
 //~| 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 cb2bb2832b7..16ea71d48c8 100644
--- a/src/test/ui/generics/generic-non-trailing-defaults.rs
+++ b/src/test/ui/generics/generic-non-trailing-defaults.rs
@@ -5,5 +5,6 @@ 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
 
 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 6d768617503..713ba091b86 100644
--- a/src/test/ui/generics/generic-non-trailing-defaults.stderr
+++ b/src/test/ui/generics/generic-non-trailing-defaults.stderr
@@ -10,5 +10,12 @@ error: generic parameters with a default must be trailing
 LL | struct Foo<A, B = Vec<C>, C>(A, B, C);
    |               ^
 
-error: aborting due to 2 previous errors
+error[E0128]: generic 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 generic parameters cannot be forward declared
+
+error: aborting due to 3 previous errors
 
+For more information about this error, try `rustc --explain E0128`.