@@ -104,19 +104,27 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
104104}
105105}
106106107-if in_param_ty {
108-// We do not allow generic parameters in anon consts if we are inside
109-// of a const parameter type, e.g. `struct Foo<const N: usize, const M: [u8; N]>` is not allowed.
110-None
111-} else if tcx.features().generic_const_exprs() {
112-let parent_node = tcx.parent_hir_node(hir_id);
113-debug!(?parent_node);
114-if let Node::Variant(Variant { disr_expr: Some(constant), .. }) = parent_node
115-&& constant.hir_id == hir_id
116-{
117-// enum variant discriminants are not allowed to use any kind of generics
118-None
119-} else if let Some(param_id) = tcx.hir_opt_const_param_default_param_def_id(hir_id)
107+match tcx.anon_const_kind(def_id) {
108+// Stable: anon consts are not able to use any generic parameters...
109+ ty::AnonConstKind::MCGConst => None,
110+// we provide generics to repeat expr counts as a backwards compatibility hack. #76200
111+ ty::AnonConstKind::RepeatExprCount => Some(parent_did),
112+113+// Even GCE anon const should not be allowed to use generic parameters as it would be
114+// trivially forward declared uses once desugared. E.g. `const N: [u8; ANON::<N>]`.
115+//
116+// We could potentially mirror the hack done for defaults of generic parameters but
117+// this case just doesn't come up much compared to `const N: u32 = ...`. Long term the
118+// hack for defaulted parameters should be removed eventually anyway.
119+ ty::AnonConstKind::GCEConst if in_param_ty => None,
120+// GCE anon consts as a default for a generic parameter should have their provided generics
121+// "truncated" up to whatever generic parameter this anon const is within the default of.
122+//
123+// FIXME(generic_const_exprs): This only handles `const N: usize = /*defid*/` but not type
124+// parameter defaults, e.g. `T = Foo</*defid*/>`.
125+ ty::AnonConstKind::GCEConst
126+if let Some(param_id) =
127+ tcx.hir_opt_const_param_default_param_def_id(hir_id) =>
120128{
121129// If the def_id we are calling generics_of on is an anon ct default i.e:
122130//
@@ -160,36 +168,17 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
160168has_self: generics.has_self,
161169has_late_bound_regions: generics.has_late_bound_regions,
162170};
163-} else {
164-// HACK(eddyb) this provides the correct generics when
165-// `feature(generic_const_expressions)` is enabled, so that const expressions
166-// used with const generics, e.g. `Foo<{N+1}>`, can work at all.
167-//
168-// Note that we do not supply the parent generics when using
169-// `min_const_generics`.
170-Some(parent_did)
171171}
172-} else {
173-let parent_node = tcx.parent_hir_node(hir_id);
174-let parent_node = match parent_node {
175-Node::ConstArg(ca) => tcx.parent_hir_node(ca.hir_id),
176- _ => parent_node,
177-};
178-match parent_node {
179-// HACK(eddyb) this provides the correct generics for repeat
180-// expressions' count (i.e. `N` in `[x; N]`), and explicit
181-// `enum` discriminants (i.e. `D` in `enum Foo { Bar = D }`),
182-// as they shouldn't be able to cause query cycle errors.
183-Node::Expr(Expr { kind: ExprKind::Repeat(_, ct), .. })
184-if ct.anon_const_hir_id() == Some(hir_id) =>
185-{
186-Some(parent_did)
187-}
188-Node::TyPat(_) => Some(parent_did),
189-// Field default values inherit the ADT's generics.
190-Node::Field(_) => Some(parent_did),
191- _ => None,
172+ ty::AnonConstKind::GCEConst => Some(parent_did),
173+174+// Field defaults are allowed to use generic parameters, e.g. `field: u32 = /*defid: N + 1*/`
175+ ty::AnonConstKind::NonTypeSystem
176+if matches!(tcx.parent_hir_node(hir_id), Node::TyPat(_) | Node::Field(_)) =>
177+{
178+Some(parent_did)
192179}
180+// Default to no generic parameters for other kinds of anon consts
181+ ty::AnonConstKind::NonTypeSystem => None,
193182}
194183}
195184Node::ConstBlock(_)