about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2020-08-08 01:48:35 +0000
committerbors <bors@rust-lang.org>2020-08-08 01:48:35 +0000
commitf9c2177ddc605f9c75ca1a3e6ddb33835b8a178d (patch)
treed8f6d0b66e018cde836a6fb6faa7a7f38116c84b
parentf3a9de9b08659e20ce7c282ed77bc43ddd149107 (diff)
parent644c8949121da0c16f65b772bf6e217748d94530 (diff)
downloadrust-f9c2177ddc605f9c75ca1a3e6ddb33835b8a178d.tar.gz
rust-f9c2177ddc605f9c75ca1a3e6ddb33835b8a178d.zip
Auto merge of #74877 - lcnr:min_const_generics, r=oli-obk
Implement the `min_const_generics` feature gate

Implements both https://github.com/rust-lang/lang-team/issues/37 and https://github.com/rust-lang/compiler-team/issues/332.

Adds the new feature gate `#![feature(min_const_generics)]`.
This feature gate adds the following limitations to using const generics:
- generic parameters must only be used in types if they are trivial. (either `N` or `{ N }`)
- generic parameters must be either integers, `bool` or `char`.

We do allow arbitrary expressions in associated consts though, meaning that the following is allowed,
even if `<[u8; 0] as Foo>::ASSOC` is not const evaluatable.
```rust
trait Foo {
    const ASSOC: usize;
}

impl<const N: usize> Foo for [u8; N] {
    const ASSOC: usize = 64 / N;
}
```

r? @varkor cc @eddyb @withoutboats
-rw-r--r--src/librustc_ast/ast.rs24
-rw-r--r--src/librustc_ast_passes/ast_validation.rs8
-rw-r--r--src/librustc_ast_passes/feature_gate.rs7
-rw-r--r--src/librustc_feature/active.rs3
-rw-r--r--src/librustc_middle/ty/context.rs4
-rw-r--r--src/librustc_parse/parser/generics.rs2
-rw-r--r--src/librustc_resolve/diagnostics.rs17
-rw-r--r--src/librustc_resolve/late.rs40
-rw-r--r--src/librustc_resolve/lib.rs32
-rw-r--r--src/librustc_span/symbol.rs1
-rw-r--r--src/librustc_typeck/collect.rs3
-rw-r--r--src/librustc_typeck/collect/type_of.rs44
-rw-r--r--src/test/ui/const-generics/const-param-in-trait-ungated.stderr4
-rw-r--r--src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr4
-rw-r--r--src/test/ui/const-generics/defaults/wrong-order.full.stderr (renamed from src/test/ui/const-generics/defaults/wrong-order.stderr)8
-rw-r--r--src/test/ui/const-generics/defaults/wrong-order.min.stderr10
-rw-r--r--src/test/ui/const-generics/defaults/wrong-order.rs4
-rw-r--r--src/test/ui/const-generics/issues/issue-56445.full.stderr (renamed from src/test/ui/const-generics/issues/issue-56445.stderr)6
-rw-r--r--src/test/ui/const-generics/issues/issue-56445.min.stderr20
-rw-r--r--src/test/ui/const-generics/issues/issue-56445.rs7
-rw-r--r--src/test/ui/const-generics/issues/issue-60263.stderr4
-rw-r--r--src/test/ui/const-generics/issues/issue-60818-struct-constructors.full.stderr (renamed from src/test/ui/const-generics/issues/issue-61336-1.stderr)6
-rw-r--r--src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs6
-rw-r--r--src/test/ui/const-generics/issues/issue-61336-1.full.stderr (renamed from src/test/ui/const-generics/issues/issue-60818-struct-constructors.stderr)6
-rw-r--r--src/test/ui/const-generics/issues/issue-61336-1.rs6
-rw-r--r--src/test/ui/const-generics/issues/issue-61336-2.full.stderr (renamed from src/test/ui/const-generics/issues/issue-61336-2.stderr)8
-rw-r--r--src/test/ui/const-generics/issues/issue-61336-2.min.stderr15
-rw-r--r--src/test/ui/const-generics/issues/issue-61336-2.rs5
-rw-r--r--src/test/ui/const-generics/issues/issue-61336.full.stderr24
-rw-r--r--src/test/ui/const-generics/issues/issue-61336.min.stderr15
-rw-r--r--src/test/ui/const-generics/issues/issue-61336.rs5
-rw-r--r--src/test/ui/const-generics/issues/issue-61422.full.stderr (renamed from src/test/ui/const-generics/issues/issue-61432.stderr)6
-rw-r--r--src/test/ui/const-generics/issues/issue-61422.rs6
-rw-r--r--src/test/ui/const-generics/issues/issue-61432.full.stderr (renamed from src/test/ui/const-generics/issues/issue-61422.stderr)6
-rw-r--r--src/test/ui/const-generics/issues/issue-61432.rs6
-rw-r--r--src/test/ui/const-generics/issues/issue-61747.full.stderr (renamed from src/test/ui/const-generics/issues/issue-61747.stderr)8
-rw-r--r--src/test/ui/const-generics/issues/issue-61747.min.stderr10
-rw-r--r--src/test/ui/const-generics/issues/issue-61747.rs8
-rw-r--r--src/test/ui/const-generics/min_const_generics/assoc_const.rs18
-rw-r--r--src/test/ui/const-generics/min_const_generics/complex-expression.rs29
-rw-r--r--src/test/ui/const-generics/min_const_generics/complex-expression.stderr34
-rw-r--r--src/test/ui/const-generics/min_const_generics/complex-types.rs18
-rw-r--r--src/test/ui/const-generics/min_const_generics/complex-types.stderr38
-rw-r--r--src/test/ui/const-generics/min_const_generics/feature-gate-min_const_generics.rs4
-rw-r--r--src/test/ui/const-generics/min_const_generics/feature-gate-min_const_generics.stderr12
-rw-r--r--src/test/ui/const-generics/type-dependent/const-arg-in-const-arg.rs5
-rw-r--r--src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr8
-rw-r--r--src/test/ui/feature-gates/feature-gate-const_generics.stderr8
48 files changed, 471 insertions, 101 deletions
diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs
index 9337b27e5e9..3d262591747 100644
--- a/src/librustc_ast/ast.rs
+++ b/src/librustc_ast/ast.rs
@@ -1052,6 +1052,30 @@ impl Expr {
         }
     }
 
+    /// Is this expr either `N`, or `{ N }`.
+    ///
+    /// If this is not the case, name resolution does not resolve `N` when using
+    /// `feature(min_const_generics)` as more complex expressions are not supported.
+    pub fn is_potential_trivial_const_param(&self) -> bool {
+        let this = if let ExprKind::Block(ref block, None) = self.kind {
+            if block.stmts.len() == 1 {
+                if let StmtKind::Expr(ref expr) = block.stmts[0].kind { expr } else { self }
+            } else {
+                self
+            }
+        } else {
+            self
+        };
+
+        if let ExprKind::Path(None, ref path) = this.kind {
+            if path.segments.len() == 1 && path.segments[0].args.is_none() {
+                return true;
+            }
+        }
+
+        false
+    }
+
     pub fn to_bound(&self) -> Option<GenericBound> {
         match &self.kind {
             ExprKind::Path(None, path) => Some(GenericBound::Trait(
diff --git a/src/librustc_ast_passes/ast_validation.rs b/src/librustc_ast_passes/ast_validation.rs
index daf3e23d6a1..0e98c047c2f 100644
--- a/src/librustc_ast_passes/ast_validation.rs
+++ b/src/librustc_ast_passes/ast_validation.rs
@@ -776,7 +776,13 @@ fn validate_generic_param_order<'a>(
             span,
             &format!(
                 "reorder the parameters: lifetimes, then types{}",
-                if sess.features_untracked().const_generics { ", then consts" } else { "" },
+                if sess.features_untracked().const_generics
+                    || sess.features_untracked().min_const_generics
+                {
+                    ", then consts"
+                } else {
+                    ""
+                },
             ),
             ordered_params.clone(),
             Applicability::MachineApplicable,
diff --git a/src/librustc_ast_passes/feature_gate.rs b/src/librustc_ast_passes/feature_gate.rs
index 22eaca4f071..8dcd445721a 100644
--- a/src/librustc_ast_passes/feature_gate.rs
+++ b/src/librustc_ast_passes/feature_gate.rs
@@ -526,12 +526,13 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
 
     fn visit_generic_param(&mut self, param: &'a GenericParam) {
         if let GenericParamKind::Const { .. } = param.kind {
-            gate_feature_post!(
+            gate_feature_fn!(
                 &self,
-                const_generics,
+                |x: &Features| x.const_generics || x.min_const_generics,
                 param.ident.span,
+                sym::min_const_generics,
                 "const generics are unstable"
-            )
+            );
         }
         visit::walk_generic_param(self, param)
     }
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 7e42f219ce2..077f6cf3ca4 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -579,6 +579,9 @@ declare_features! (
     /// Allows calling `transmute` in const fn
     (active, const_fn_transmute, "1.46.0", Some(53605), None),
 
+    /// The smallest useful subset of `const_generics`.
+    (active, min_const_generics, "1.46.0", Some(74878), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index 6cbf5db8373..16f5e9a42d3 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -1380,7 +1380,9 @@ impl<'tcx> TyCtxt<'tcx> {
     /// we still evaluate them eagerly.
     #[inline]
     pub fn lazy_normalization(self) -> bool {
-        self.features().const_generics || self.features().lazy_normalization_consts
+        let features = self.features();
+        // Note: We do not enable lazy normalization for `features.min_const_generics`.
+        features.const_generics || features.lazy_normalization_consts
     }
 
     #[inline]
diff --git a/src/librustc_parse/parser/generics.rs b/src/librustc_parse/parser/generics.rs
index 47794746126..be72ed6dffb 100644
--- a/src/librustc_parse/parser/generics.rs
+++ b/src/librustc_parse/parser/generics.rs
@@ -54,7 +54,7 @@ impl<'a> Parser<'a> {
         self.expect(&token::Colon)?;
         let ty = self.parse_ty()?;
 
-        self.sess.gated_spans.gate(sym::const_generics, const_span.to(self.prev_token.span));
+        self.sess.gated_spans.gate(sym::min_const_generics, const_span.to(self.prev_token.span));
 
         Ok(GenericParam {
             ident,
diff --git a/src/librustc_resolve/diagnostics.rs b/src/librustc_resolve/diagnostics.rs
index a6b5b0ff301..9502be728de 100644
--- a/src/librustc_resolve/diagnostics.rs
+++ b/src/librustc_resolve/diagnostics.rs
@@ -466,6 +466,23 @@ impl<'a> Resolver<'a> {
                 );
                 err
             }
+            ResolutionError::ParamInNonTrivialAnonConst(name) => {
+                let mut err = self.session.struct_span_err(
+                    span,
+                    "generic parameters must not be used inside of non trivial constant values",
+                );
+                err.span_label(
+                    span,
+                    &format!(
+                        "non-trivial anonymous constants must not depend on the parameter `{}`",
+                        name
+                    ),
+                );
+                err.help(
+                    &format!("it is currently only allowed to use either `{0}` or `{{ {0} }}` as generic constants", name)
+                );
+                err
+            }
             ResolutionError::SelfInTyParamDefault => {
                 let mut err = struct_span_err!(
                     self.session,
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index 44ff4209095..b5fc69f9f31 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -111,7 +111,7 @@ crate enum RibKind<'a> {
     ItemRibKind(HasGenericParams),
 
     /// We're in a constant item. Can't refer to dynamic stuff.
-    ConstantItemRibKind,
+    ConstantItemRibKind(bool),
 
     /// We passed through a module.
     ModuleRibKind(Module<'a>),
@@ -137,7 +137,7 @@ impl RibKind<'_> {
             NormalRibKind
             | ClosureOrAsyncRibKind
             | FnItemRibKind
-            | ConstantItemRibKind
+            | ConstantItemRibKind(_)
             | ModuleRibKind(_)
             | MacroDefinition(_)
             | ConstParamTyRibKind => false,
@@ -426,7 +426,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
     }
     fn visit_anon_const(&mut self, constant: &'ast AnonConst) {
         debug!("visit_anon_const {:?}", constant);
-        self.with_constant_rib(|this| {
+        self.with_constant_rib(constant.value.is_potential_trivial_const_param(), |this| {
             visit::walk_anon_const(this, constant);
         });
     }
@@ -628,7 +628,7 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
                         if !check_ns(TypeNS) && check_ns(ValueNS) {
                             // This must be equivalent to `visit_anon_const`, but we cannot call it
                             // directly due to visitor lifetimes so we have to copy-paste some code.
-                            self.with_constant_rib(|this| {
+                            self.with_constant_rib(true, |this| {
                                 this.smart_resolve_path(
                                     ty.id,
                                     qself.as_ref(),
@@ -829,7 +829,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 | ClosureOrAsyncRibKind
                 | FnItemRibKind
                 | ItemRibKind(..)
-                | ConstantItemRibKind
+                | ConstantItemRibKind(_)
                 | ModuleRibKind(..)
                 | ForwardTyParamBanRibKind
                 | ConstParamTyRibKind => {
@@ -948,7 +948,14 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                         // Only impose the restrictions of `ConstRibKind` for an
                                         // actual constant expression in a provided default.
                                         if let Some(expr) = default {
-                                            this.with_constant_rib(|this| this.visit_expr(expr));
+                                            // We allow arbitrary const expressions inside of associated consts,
+                                            // even if they are potentially not const evaluatable.
+                                            //
+                                            // Type parameters can already be used and as associated consts are
+                                            // not used as part of the type system, this is far less surprising.
+                                            this.with_constant_rib(true, |this| {
+                                                this.visit_expr(expr)
+                                            });
                                         }
                                     }
                                     AssocItemKind::Fn(_, _, generics, _) => {
@@ -989,7 +996,9 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                 self.with_item_rib(HasGenericParams::No, |this| {
                     this.visit_ty(ty);
                     if let Some(expr) = expr {
-                        this.with_constant_rib(|this| this.visit_expr(expr));
+                        this.with_constant_rib(expr.is_potential_trivial_const_param(), |this| {
+                            this.visit_expr(expr)
+                        });
                     }
                 });
             }
@@ -1086,11 +1095,11 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
     }
 
-    fn with_constant_rib(&mut self, f: impl FnOnce(&mut Self)) {
+    fn with_constant_rib(&mut self, trivial: bool, f: impl FnOnce(&mut Self)) {
         debug!("with_constant_rib");
-        self.with_rib(ValueNS, ConstantItemRibKind, |this| {
-            this.with_rib(TypeNS, ConstantItemRibKind, |this| {
-                this.with_label_rib(ConstantItemRibKind, f);
+        self.with_rib(ValueNS, ConstantItemRibKind(trivial), |this| {
+            this.with_rib(TypeNS, ConstantItemRibKind(trivial), |this| {
+                this.with_label_rib(ConstantItemRibKind(trivial), f);
             })
         });
     }
@@ -1220,7 +1229,7 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                 for item in impl_items {
                                     use crate::ResolutionError::*;
                                     match &item.kind {
-                                        AssocItemKind::Const(..) => {
+                                        AssocItemKind::Const(_default, _ty, _expr) => {
                                             debug!("resolve_implementation AssocItemKind::Const",);
                                             // If this is a trait impl, ensure the const
                                             // exists in trait
@@ -1231,7 +1240,12 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
                                                 |n, s| ConstNotMemberOfTrait(n, s),
                                             );
 
-                                            this.with_constant_rib(|this| {
+                                            // We allow arbitrary const expressions inside of associated consts,
+                                            // even if they are potentially not const evaluatable.
+                                            //
+                                            // Type parameters can already be used and as associated consts are
+                                            // not used as part of the type system, this is far less surprising.
+                                            this.with_constant_rib(true, |this| {
                                                 visit::walk_assoc_item(this, item, AssocCtxt::Impl)
                                             });
                                         }
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 234fcd789ee..1425efcb54d 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -218,6 +218,10 @@ enum ResolutionError<'a> {
     ParamInTyOfConstParam(Symbol),
     /// constant values inside of type parameter defaults must not depend on generic parameters.
     ParamInAnonConstInTyDefault(Symbol),
+    /// generic parameters must not be used inside of non trivial constant values.
+    ///
+    /// This error is only emitted when using `min_const_generics`.
+    ParamInNonTrivialAnonConst(Symbol),
     /// Error E0735: type parameters with a default cannot use `Self`
     SelfInTyParamDefault,
     /// Error E0767: use of unreachable label
@@ -2507,7 +2511,7 @@ impl<'a> Resolver<'a> {
                                 res_err = Some(CannotCaptureDynamicEnvironmentInFnItem);
                             }
                         }
-                        ConstantItemRibKind => {
+                        ConstantItemRibKind(_) => {
                             // Still doesn't deal with upvars
                             if record_used {
                                 self.report_error(span, AttemptToUseNonConstantValueInConstant);
@@ -2546,7 +2550,18 @@ impl<'a> Resolver<'a> {
                             in_ty_param_default = true;
                             continue;
                         }
-                        ConstantItemRibKind => {
+                        ConstantItemRibKind(trivial) => {
+                            // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
+                            if !trivial && self.session.features_untracked().min_const_generics {
+                                if record_used {
+                                    self.report_error(
+                                        span,
+                                        ResolutionError::ParamInNonTrivialAnonConst(rib_ident.name),
+                                    );
+                                }
+                                return Res::Err;
+                            }
+
                             if in_ty_param_default {
                                 if record_used {
                                     self.report_error(
@@ -2612,7 +2627,18 @@ impl<'a> Resolver<'a> {
                             in_ty_param_default = true;
                             continue;
                         }
-                        ConstantItemRibKind => {
+                        ConstantItemRibKind(trivial) => {
+                            // HACK(min_const_generics): We currently only allow `N` or `{ N }`.
+                            if !trivial && self.session.features_untracked().min_const_generics {
+                                if record_used {
+                                    self.report_error(
+                                        span,
+                                        ResolutionError::ParamInNonTrivialAnonConst(rib_ident.name),
+                                    );
+                                }
+                                return Res::Err;
+                            }
+
                             if in_ty_param_default {
                                 if record_used {
                                     self.report_error(
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index 98776a04782..5203bfdb3b7 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -672,6 +672,7 @@ symbols! {
         min_align_of,
         min_align_of_val,
         min_const_fn,
+        min_const_generics,
         min_const_unsafe_fn,
         min_specialization,
         minnumf32,
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 97df065500a..bab8db46a9d 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -1238,6 +1238,9 @@ fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
                 // HACK(eddyb) this provides the correct generics when
                 // `feature(const_generics)` is enabled, so that const expressions
                 // used with const generics, e.g. `Foo<{N+1}>`, can work at all.
+                //
+                // Note that we do not supply the parent generics when using
+                // `feature(min_const_generics)`.
                 Some(parent_def_id.to_def_id())
             } else {
                 let parent_node = tcx.hir().get(tcx.hir().get_parent_node(hir_id));
diff --git a/src/librustc_typeck/collect/type_of.rs b/src/librustc_typeck/collect/type_of.rs
index 8c9cd50a17d..17444c6d0ac 100644
--- a/src/librustc_typeck/collect/type_of.rs
+++ b/src/librustc_typeck/collect/type_of.rs
@@ -326,21 +326,39 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
             GenericParamKind::Type { default: Some(ref ty), .. } => icx.to_ty(ty),
             GenericParamKind::Const { ty: ref hir_ty, .. } => {
                 let ty = icx.to_ty(hir_ty);
-                let err = match ty.peel_refs().kind {
-                    ty::FnPtr(_) => Some("function pointers"),
-                    ty::RawPtr(_) => Some("raw pointers"),
-                    _ => None,
+                let err_ty_str;
+                let err = if tcx.features().min_const_generics {
+                    match ty.kind {
+                        ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::Error(_) => None,
+                        ty::FnPtr(_) => Some("function pointers"),
+                        ty::RawPtr(_) => Some("raw pointers"),
+                        _ => {
+                            err_ty_str = format!("`{}`", ty);
+                            Some(err_ty_str.as_str())
+                        }
+                    }
+                } else {
+                    match ty.peel_refs().kind {
+                        ty::FnPtr(_) => Some("function pointers"),
+                        ty::RawPtr(_) => Some("raw pointers"),
+                        _ => None,
+                    }
                 };
                 if let Some(unsupported_type) = err {
-                    tcx.sess
-                        .struct_span_err(
-                            hir_ty.span,
-                            &format!(
-                                "using {} as const generic parameters is forbidden",
-                                unsupported_type
-                            ),
-                        )
-                        .emit();
+                    let mut err = tcx.sess.struct_span_err(
+                        hir_ty.span,
+                        &format!(
+                            "using {} as const generic parameters is forbidden",
+                            unsupported_type
+                        ),
+                    );
+
+                    if tcx.features().min_const_generics {
+                        err.note("the only supported types are integers, `bool` and `char`")
+                        .note("more complex types are supported with `#[feature(const_generics)]`").emit()
+                    } else {
+                        err.emit();
+                    }
                 };
                 if traits::search_for_structural_match_violation(param.hir_id, param.span, tcx, ty)
                     .is_some()
diff --git a/src/test/ui/const-generics/const-param-in-trait-ungated.stderr b/src/test/ui/const-generics/const-param-in-trait-ungated.stderr
index bdae6bc362c..d53a4ac2d4c 100644
--- a/src/test/ui/const-generics/const-param-in-trait-ungated.stderr
+++ b/src/test/ui/const-generics/const-param-in-trait-ungated.stderr
@@ -4,8 +4,8 @@ error[E0658]: const generics are unstable
 LL | trait Trait<const T: ()> {}
    |                   ^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
+   = help: add `#![feature(min_const_generics)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
index 616f0fa8f1a..5d379ff083c 100644
--- a/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
+++ b/src/test/ui/const-generics/const-param-type-depends-on-type-param-ungated.stderr
@@ -10,8 +10,8 @@ error[E0658]: const generics are unstable
 LL | struct B<T, const N: T>(PhantomData<[T; N]>);
    |                   ^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
+   = help: add `#![feature(min_const_generics)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/const-generics/defaults/wrong-order.stderr b/src/test/ui/const-generics/defaults/wrong-order.full.stderr
index 283f6656121..c51028d5b20 100644
--- a/src/test/ui/const-generics/defaults/wrong-order.stderr
+++ b/src/test/ui/const-generics/defaults/wrong-order.full.stderr
@@ -1,5 +1,5 @@
 error: type parameters with a default must be trailing
-  --> $DIR/wrong-order.rs:3:10
+  --> $DIR/wrong-order.rs:5:10
    |
 LL | struct A<T = u32, const N: usize> {
    |          ^
@@ -7,10 +7,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:1:12
+  --> $DIR/wrong-order.rs:2:27
    |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
+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
diff --git a/src/test/ui/const-generics/defaults/wrong-order.min.stderr b/src/test/ui/const-generics/defaults/wrong-order.min.stderr
new file mode 100644
index 00000000000..29a46367004
--- /dev/null
+++ b/src/test/ui/const-generics/defaults/wrong-order.min.stderr
@@ -0,0 +1,10 @@
+error: type parameters with a default must be trailing
+  --> $DIR/wrong-order.rs:5: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 7f17c6358b7..cb36d456f38 100644
--- a/src/test/ui/const-generics/defaults/wrong-order.rs
+++ b/src/test/ui/const-generics/defaults/wrong-order.rs
@@ -1,4 +1,6 @@
-#![feature(const_generics)] //~ WARN the feature `const_generics` is incomplete
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct A<T = u32, const N: usize> {
     //~^ ERROR type parameters with a default must be trailing
diff --git a/src/test/ui/const-generics/issues/issue-56445.stderr b/src/test/ui/const-generics/issues/issue-56445.full.stderr
index fba638b0b2b..d853ec5015e 100644
--- a/src/test/ui/const-generics/issues/issue-56445.stderr
+++ b/src/test/ui/const-generics/issues/issue-56445.full.stderr
@@ -1,8 +1,8 @@
 warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-56445.rs:3:12
+  --> $DIR/issue-56445.rs:3:27
    |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
+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
diff --git a/src/test/ui/const-generics/issues/issue-56445.min.stderr b/src/test/ui/const-generics/issues/issue-56445.min.stderr
new file mode 100644
index 00000000000..ca35ee5b290
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-56445.min.stderr
@@ -0,0 +1,20 @@
+error[E0771]: use of non-static lifetime `'a` in const generic
+  --> $DIR/issue-56445.rs:9:26
+   |
+LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
+   |                          ^^
+   |
+   = note: for more information, see issue #74052 <https://github.com/rust-lang/rust/issues/74052>
+
+error: using `&'static str` as const generic parameters is forbidden
+  --> $DIR/issue-56445.rs:9:25
+   |
+LL | struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
+   |                         ^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0771`.
diff --git a/src/test/ui/const-generics/issues/issue-56445.rs b/src/test/ui/const-generics/issues/issue-56445.rs
index 26441512e3f..174eb16abfc 100644
--- a/src/test/ui/const-generics/issues/issue-56445.rs
+++ b/src/test/ui/const-generics/issues/issue-56445.rs
@@ -1,12 +1,13 @@
 // Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-518402995.
-
-#![feature(const_generics)]
-//~^ WARN: the feature `const_generics` is incomplete
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
+#![cfg_attr(min, feature(min_const_generics))]
 #![crate_type = "lib"]
 
 use std::marker::PhantomData;
 
 struct Bug<'a, const S: &'a str>(PhantomData<&'a ()>);
 //~^ ERROR: use of non-static lifetime `'a` in const generic
+//[min]~| ERROR: using `&'static str` as const
 
 impl Bug<'_, ""> {}
diff --git a/src/test/ui/const-generics/issues/issue-60263.stderr b/src/test/ui/const-generics/issues/issue-60263.stderr
index 7b50c442d2f..aeef296f385 100644
--- a/src/test/ui/const-generics/issues/issue-60263.stderr
+++ b/src/test/ui/const-generics/issues/issue-60263.stderr
@@ -4,8 +4,8 @@ error[E0658]: const generics are unstable
 LL | struct B<const I: u8>;
    |                ^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
+   = help: add `#![feature(min_const_generics)]` to the crate attributes to enable
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/issues/issue-61336-1.stderr b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.full.stderr
index b2c69d57c40..c03b7252a3c 100644
--- a/src/test/ui/const-generics/issues/issue-61336-1.stderr
+++ b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.full.stderr
@@ -1,8 +1,8 @@
 warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-61336-1.rs:1:12
+  --> $DIR/issue-60818-struct-constructors.rs:3:27
    |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
+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
diff --git a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs
index 26d74ffb254..ae2b0520fb1 100644
--- a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs
+++ b/src/test/ui/const-generics/issues/issue-60818-struct-constructors.rs
@@ -1,7 +1,7 @@
 // check-pass
-
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct Generic<const V: usize>;
 
diff --git a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.stderr b/src/test/ui/const-generics/issues/issue-61336-1.full.stderr
index 94a2b673a51..f18728eabbb 100644
--- a/src/test/ui/const-generics/issues/issue-60818-struct-constructors.stderr
+++ b/src/test/ui/const-generics/issues/issue-61336-1.full.stderr
@@ -1,8 +1,8 @@
 warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-60818-struct-constructors.rs:3:12
+  --> $DIR/issue-61336-1.rs:3:27
    |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
+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
diff --git a/src/test/ui/const-generics/issues/issue-61336-1.rs b/src/test/ui/const-generics/issues/issue-61336-1.rs
index 2135c868bbc..201c0d039d9 100644
--- a/src/test/ui/const-generics/issues/issue-61336-1.rs
+++ b/src/test/ui/const-generics/issues/issue-61336-1.rs
@@ -1,7 +1,7 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
-
 // build-pass
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
     [x; N]
diff --git a/src/test/ui/const-generics/issues/issue-61336-2.stderr b/src/test/ui/const-generics/issues/issue-61336-2.full.stderr
index 5f3395223f9..d21cd9df054 100644
--- a/src/test/ui/const-generics/issues/issue-61336-2.stderr
+++ b/src/test/ui/const-generics/issues/issue-61336-2.full.stderr
@@ -1,14 +1,14 @@
 warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-61336-2.rs:1:12
+  --> $DIR/issue-61336-2.rs:2:27
    |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
+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[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
-  --> $DIR/issue-61336-2.rs:9:5
+  --> $DIR/issue-61336-2.rs:10:5
    |
 LL |     [x; { N }]
    |     ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
diff --git a/src/test/ui/const-generics/issues/issue-61336-2.min.stderr b/src/test/ui/const-generics/issues/issue-61336-2.min.stderr
new file mode 100644
index 00000000000..29ab7b1305e
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-61336-2.min.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/issue-61336-2.rs:10:5
+   |
+LL |     [x; { N }]
+   |     ^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = note: the `Copy` trait is required because the repeated element will be copied
+help: consider restricting type parameter `T`
+   |
+LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
+   |       ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issues/issue-61336-2.rs b/src/test/ui/const-generics/issues/issue-61336-2.rs
index 52969056f00..25b9271105e 100644
--- a/src/test/ui/const-generics/issues/issue-61336-2.rs
+++ b/src/test/ui/const-generics/issues/issue-61336-2.rs
@@ -1,5 +1,6 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
     [x; { N }]
diff --git a/src/test/ui/const-generics/issues/issue-61336.full.stderr b/src/test/ui/const-generics/issues/issue-61336.full.stderr
new file mode 100644
index 00000000000..d1b5d5eb941
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-61336.full.stderr
@@ -0,0 +1,24 @@
+warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-61336.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[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/issue-61336.rs:10:5
+   |
+LL |     [x; N]
+   |     ^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = note: the `Copy` trait is required because the repeated element will be copied
+help: consider restricting type parameter `T`
+   |
+LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
+   |       ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issues/issue-61336.min.stderr b/src/test/ui/const-generics/issues/issue-61336.min.stderr
new file mode 100644
index 00000000000..bced8bbd82f
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-61336.min.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
+  --> $DIR/issue-61336.rs:10:5
+   |
+LL |     [x; N]
+   |     ^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
+   |
+   = note: the `Copy` trait is required because the repeated element will be copied
+help: consider restricting type parameter `T`
+   |
+LL | fn g<T: std::marker::Copy, const N: usize>(x: T) -> [T; N] {
+   |       ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/const-generics/issues/issue-61336.rs b/src/test/ui/const-generics/issues/issue-61336.rs
index eb0f3097627..fb55542a1c9 100644
--- a/src/test/ui/const-generics/issues/issue-61336.rs
+++ b/src/test/ui/const-generics/issues/issue-61336.rs
@@ -1,5 +1,6 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn f<T: Copy, const N: usize>(x: T) -> [T; N] {
     [x; N]
diff --git a/src/test/ui/const-generics/issues/issue-61432.stderr b/src/test/ui/const-generics/issues/issue-61422.full.stderr
index 1d547b1b6c9..ac6c378295d 100644
--- a/src/test/ui/const-generics/issues/issue-61432.stderr
+++ b/src/test/ui/const-generics/issues/issue-61422.full.stderr
@@ -1,8 +1,8 @@
 warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-61432.rs:3:12
+  --> $DIR/issue-61422.rs:3:27
    |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
+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
diff --git a/src/test/ui/const-generics/issues/issue-61422.rs b/src/test/ui/const-generics/issues/issue-61422.rs
index 7e7ef6867ed..649f8b4255b 100644
--- a/src/test/ui/const-generics/issues/issue-61422.rs
+++ b/src/test/ui/const-generics/issues/issue-61422.rs
@@ -1,7 +1,7 @@
 // check-pass
-
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
+#![cfg_attr(min, feature(min_const_generics))]
 
 use std::mem;
 
diff --git a/src/test/ui/const-generics/issues/issue-61422.stderr b/src/test/ui/const-generics/issues/issue-61432.full.stderr
index 69bbaada691..82b36de45a2 100644
--- a/src/test/ui/const-generics/issues/issue-61422.stderr
+++ b/src/test/ui/const-generics/issues/issue-61432.full.stderr
@@ -1,8 +1,8 @@
 warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-61422.rs:3:12
+  --> $DIR/issue-61432.rs:3:27
    |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
+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
diff --git a/src/test/ui/const-generics/issues/issue-61432.rs b/src/test/ui/const-generics/issues/issue-61432.rs
index 0440468e9e6..91a4794099c 100644
--- a/src/test/ui/const-generics/issues/issue-61432.rs
+++ b/src/test/ui/const-generics/issues/issue-61432.rs
@@ -1,7 +1,7 @@
 // run-pass
-
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
+#![cfg_attr(min, feature(min_const_generics))]
 
 fn promote<const N: i32>() {
     // works:
diff --git a/src/test/ui/const-generics/issues/issue-61747.stderr b/src/test/ui/const-generics/issues/issue-61747.full.stderr
index 2685d9fdf16..3ccce5675fc 100644
--- a/src/test/ui/const-generics/issues/issue-61747.stderr
+++ b/src/test/ui/const-generics/issues/issue-61747.full.stderr
@@ -1,14 +1,14 @@
 warning: the feature `const_generics` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-61747.rs:1:12
+  --> $DIR/issue-61747.rs:2:27
    |
-LL | #![feature(const_generics)]
-   |            ^^^^^^^^^^^^^^
+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: constant expression depends on a generic parameter
-  --> $DIR/issue-61747.rs:7:23
+  --> $DIR/issue-61747.rs:8:23
    |
 LL |     fn successor() -> Const<{C + 1}> {
    |                       ^^^^^^^^^^^^^^
diff --git a/src/test/ui/const-generics/issues/issue-61747.min.stderr b/src/test/ui/const-generics/issues/issue-61747.min.stderr
new file mode 100644
index 00000000000..2061b6c55bb
--- /dev/null
+++ b/src/test/ui/const-generics/issues/issue-61747.min.stderr
@@ -0,0 +1,10 @@
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/issue-61747.rs:8:30
+   |
+LL |     fn successor() -> Const<{C + 1}> {
+   |                              ^ non-trivial anonymous constants must not depend on the parameter `C`
+   |
+   = help: it is currently only allowed to use either `C` or `{ C }` as generic constants
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/const-generics/issues/issue-61747.rs b/src/test/ui/const-generics/issues/issue-61747.rs
index cc671163e85..4e5cde17f39 100644
--- a/src/test/ui/const-generics/issues/issue-61747.rs
+++ b/src/test/ui/const-generics/issues/issue-61747.rs
@@ -1,11 +1,13 @@
-#![feature(const_generics)]
-//~^ WARN the feature `const_generics` is incomplete
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))] //[full]~WARN the feature `const_generics` is incomplete
+#![cfg_attr(min, feature(min_const_generics))]
 
 struct Const<const N: usize>;
 
 impl<const C: usize> Const<{C}> {
     fn successor() -> Const<{C + 1}> {
-        //~^ ERROR constant expression depends on a generic parameter
+        //[full]~^ ERROR constant expression depends on a generic parameter
+        //[min]~^^ ERROR generic parameters must not be used
         Const
     }
 }
diff --git a/src/test/ui/const-generics/min_const_generics/assoc_const.rs b/src/test/ui/const-generics/min_const_generics/assoc_const.rs
new file mode 100644
index 00000000000..fa75613d9dd
--- /dev/null
+++ b/src/test/ui/const-generics/min_const_generics/assoc_const.rs
@@ -0,0 +1,18 @@
+// check-pass
+#![feature(min_const_generics)]
+
+struct Foo<const N: usize>;
+
+impl<const N: usize> Foo<N> {
+    const VALUE: usize = N * 2;
+}
+
+trait Bar {
+    const ASSOC: usize;
+}
+
+impl<const N: usize> Bar for Foo<N> {
+    const ASSOC: usize = N * 3;
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/min_const_generics/complex-expression.rs b/src/test/ui/const-generics/min_const_generics/complex-expression.rs
new file mode 100644
index 00000000000..f9cb0d2829d
--- /dev/null
+++ b/src/test/ui/const-generics/min_const_generics/complex-expression.rs
@@ -0,0 +1,29 @@
+#![feature(min_const_generics)]
+
+fn test<const N: usize>() {}
+
+fn ok<const M: usize>() -> [u8; M] {
+    [0; { M }]
+}
+
+struct Break0<const N: usize>([u8; { N + 1 }]);
+//~^ ERROR generic parameters must not be used inside of non trivial constant values
+
+struct Break1<const N: usize>([u8; { { N } }]);
+//~^ ERROR generic parameters must not be used inside of non trivial constant values
+
+fn break2<const N: usize>() {
+    let _: [u8; N + 1];
+    //~^ ERROR generic parameters must not be used inside of non trivial constant values
+}
+
+fn break3<const N: usize>() {
+    let _ = [0; N + 1];
+    //~^ ERROR generic parameters must not be used inside of non trivial constant values
+}
+
+trait Foo {
+    const ASSOC: usize;
+}
+
+fn main() {}
diff --git a/src/test/ui/const-generics/min_const_generics/complex-expression.stderr b/src/test/ui/const-generics/min_const_generics/complex-expression.stderr
new file mode 100644
index 00000000000..baed8d13f00
--- /dev/null
+++ b/src/test/ui/const-generics/min_const_generics/complex-expression.stderr
@@ -0,0 +1,34 @@
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/complex-expression.rs:9:38
+   |
+LL | struct Break0<const N: usize>([u8; { N + 1 }]);
+   |                                      ^ non-trivial anonymous constants must not depend on the parameter `N`
+   |
+   = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
+
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/complex-expression.rs:12:40
+   |
+LL | struct Break1<const N: usize>([u8; { { N } }]);
+   |                                        ^ non-trivial anonymous constants must not depend on the parameter `N`
+   |
+   = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
+
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/complex-expression.rs:16:17
+   |
+LL |     let _: [u8; N + 1];
+   |                 ^ non-trivial anonymous constants must not depend on the parameter `N`
+   |
+   = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
+
+error: generic parameters must not be used inside of non trivial constant values
+  --> $DIR/complex-expression.rs:21:17
+   |
+LL |     let _ = [0; N + 1];
+   |                 ^ non-trivial anonymous constants must not depend on the parameter `N`
+   |
+   = help: it is currently only allowed to use either `N` or `{ N }` as generic constants
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/const-generics/min_const_generics/complex-types.rs b/src/test/ui/const-generics/min_const_generics/complex-types.rs
new file mode 100644
index 00000000000..a396fa83aa6
--- /dev/null
+++ b/src/test/ui/const-generics/min_const_generics/complex-types.rs
@@ -0,0 +1,18 @@
+#![feature(min_const_generics)]
+
+struct Foo<const N: [u8; 0]>;
+//~^ ERROR using `[u8; 0]` as const generic parameters is forbidden
+
+struct Bar<const N: ()>;
+//~^ ERROR using `()` as const generic parameters is forbidden
+
+#[derive(PartialEq, Eq)]
+struct No;
+
+struct Fez<const N: No>;
+//~^ ERROR using `No` as const generic parameters is forbidden
+
+struct Faz<const N: &'static u8>;
+//~^ ERROR using `&'static u8` as const generic parameters is forbidden
+
+fn main() {}
diff --git a/src/test/ui/const-generics/min_const_generics/complex-types.stderr b/src/test/ui/const-generics/min_const_generics/complex-types.stderr
new file mode 100644
index 00000000000..835b1f1a3e8
--- /dev/null
+++ b/src/test/ui/const-generics/min_const_generics/complex-types.stderr
@@ -0,0 +1,38 @@
+error: using `[u8; 0]` as const generic parameters is forbidden
+  --> $DIR/complex-types.rs:3:21
+   |
+LL | struct Foo<const N: [u8; 0]>;
+   |                     ^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `()` as const generic parameters is forbidden
+  --> $DIR/complex-types.rs:6:21
+   |
+LL | struct Bar<const N: ()>;
+   |                     ^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `No` as const generic parameters is forbidden
+  --> $DIR/complex-types.rs:12:21
+   |
+LL | struct Fez<const N: No>;
+   |                     ^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: using `&'static u8` as const generic parameters is forbidden
+  --> $DIR/complex-types.rs:15:21
+   |
+LL | struct Faz<const N: &'static u8>;
+   |                     ^^^^^^^^^^^
+   |
+   = note: the only supported types are integers, `bool` and `char`
+   = note: more complex types are supported with `#[feature(const_generics)]`
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui/const-generics/min_const_generics/feature-gate-min_const_generics.rs b/src/test/ui/const-generics/min_const_generics/feature-gate-min_const_generics.rs
new file mode 100644
index 00000000000..423deae4600
--- /dev/null
+++ b/src/test/ui/const-generics/min_const_generics/feature-gate-min_const_generics.rs
@@ -0,0 +1,4 @@
+fn test<const N: usize>() {}
+//~^ ERROR const generics are unstable
+
+fn main() {}
diff --git a/src/test/ui/const-generics/min_const_generics/feature-gate-min_const_generics.stderr b/src/test/ui/const-generics/min_const_generics/feature-gate-min_const_generics.stderr
new file mode 100644
index 00000000000..7f82a960da2
--- /dev/null
+++ b/src/test/ui/const-generics/min_const_generics/feature-gate-min_const_generics.stderr
@@ -0,0 +1,12 @@
+error[E0658]: const generics are unstable
+  --> $DIR/feature-gate-min_const_generics.rs:1:15
+   |
+LL | fn test<const N: usize>() {}
+   |               ^
+   |
+   = note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
+   = help: add `#![feature(min_const_generics)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/const-generics/type-dependent/const-arg-in-const-arg.rs b/src/test/ui/const-generics/type-dependent/const-arg-in-const-arg.rs
index ae50252facd..3ccdd472613 100644
--- a/src/test/ui/const-generics/type-dependent/const-arg-in-const-arg.rs
+++ b/src/test/ui/const-generics/type-dependent/const-arg-in-const-arg.rs
@@ -1,7 +1,8 @@
 // run-pass
-#![feature(const_generics)]
+// revisions: full min
+#![cfg_attr(full, feature(const_generics))]
+#![cfg_attr(min, feature(min_const_generics))]
 #![allow(incomplete_features)]
-#![feature(const_fn)]
 
 struct Foo;
 
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr
index b2c96d3810f..eef465318a3 100644
--- a/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr
+++ b/src/test/ui/feature-gates/feature-gate-const_generics-ptr.stderr
@@ -4,8 +4,8 @@ error[E0658]: const generics are unstable
 LL | struct ConstFn<const F: fn()>;
    |                      ^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
+   = help: add `#![feature(min_const_generics)]` to the crate attributes to enable
 
 error[E0658]: const generics are unstable
   --> $DIR/feature-gate-const_generics-ptr.rs:5:23
@@ -13,8 +13,8 @@ error[E0658]: const generics are unstable
 LL | struct ConstPtr<const P: *const u32>;
    |                       ^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
+   = help: add `#![feature(min_const_generics)]` to the crate attributes to enable
 
 error: using function pointers as const generic parameters is forbidden
   --> $DIR/feature-gate-const_generics-ptr.rs:1:25
diff --git a/src/test/ui/feature-gates/feature-gate-const_generics.stderr b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
index 02aa1f5a4d8..f80362252f9 100644
--- a/src/test/ui/feature-gates/feature-gate-const_generics.stderr
+++ b/src/test/ui/feature-gates/feature-gate-const_generics.stderr
@@ -4,8 +4,8 @@ error[E0658]: const generics are unstable
 LL | fn foo<const X: ()>() {}
    |              ^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
+   = help: add `#![feature(min_const_generics)]` to the crate attributes to enable
 
 error[E0658]: const generics are unstable
   --> $DIR/feature-gate-const_generics.rs:3:18
@@ -13,8 +13,8 @@ error[E0658]: const generics are unstable
 LL | struct Foo<const X: usize>([(); X]);
    |                  ^
    |
-   = note: see issue #44580 <https://github.com/rust-lang/rust/issues/44580> for more information
-   = help: add `#![feature(const_generics)]` to the crate attributes to enable
+   = note: see issue #74878 <https://github.com/rust-lang/rust/issues/74878> for more information
+   = help: add `#![feature(min_const_generics)]` to the crate attributes to enable
 
 error: aborting due to 2 previous errors