From 71523aacfe8a5dc7dd7c4bd922c8dc4b7208a5f5 Mon Sep 17 00:00:00 2001 From: LaneAsade Date: Tue, 9 Jun 2026 13:54:37 +0530 Subject: [PATCH] Remove AnonConstKind::GCA and reject generic anon consts --- compiler/rustc_hir_analysis/src/collect.rs | 63 +------------------ .../src/collect/generics_of.rs | 2 - .../src/hir_ty_lowering/mod.rs | 6 +- compiler/rustc_resolve/src/errors.rs | 2 +- .../rustc_trait_selection/src/traits/mod.rs | 3 +- compiler/rustc_type_ir/src/const_kind.rs | 3 - .../gca/basic-different-definitions.rs | 4 +- tests/ui/const-generics/gca/basic.rs | 2 +- tests/ui/const-generics/gca/coherence-fail.rs | 10 +-- tests/ui/const-generics/gca/coherence-ok.rs | 2 +- .../gca/gca-anon-const-rejected.rs | 9 +++ .../gca/gca-anon-const-rejected.stderr | 10 +++ .../const-generics/gca/generic-param-rhs.rs | 2 +- .../gca/generic-param-rhs.stderr | 2 +- .../ui/const-generics/gca/rhs-but-not-root.rs | 2 +- .../gca/rhs-but-not-root.stderr | 2 +- 16 files changed, 38 insertions(+), 86 deletions(-) create mode 100644 tests/ui/const-generics/gca/gca-anon-const-rejected.rs create mode 100644 tests/ui/const-generics/gca/gca-anon-const-rejected.stderr diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 35ab34c6c0e4d..48b281851d3db 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -15,7 +15,6 @@ //! crate as a kind of pass. This should eventually be factored away. use std::cell::Cell; -use std::ops::ControlFlow; use std::{assert_matches, iter}; use rustc_abi::{ExternAbi, Size}; @@ -24,13 +23,12 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, Diagnostic, E0228, ErrorGuaranteed, Level, StashKey, }; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::{self, InferKind, Visitor, VisitorExt}; +use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt}; use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind, find_attr}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause}; -use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{ @@ -1636,20 +1634,6 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin let parent_hir_node = tcx.hir_node(tcx.parent_hir_id(const_arg_id)); if tcx.features().generic_const_exprs() { ty::AnonConstKind::GCE - } else if tcx.features().generic_const_args() { - // Only anon consts that are the RHS of a const item can be GCA. - // Note: We can't just check tcx.parent because it needs to be EXACTLY - // the RHS, not just part of the RHS. - if !is_anon_const_rhs_of_const_item(tcx, def) { - return ty::AnonConstKind::MCG; - } - - let body = tcx.hir_body_owned_by(def); - let mut visitor = GCAParamVisitor(tcx); - match visitor.visit_body(body) { - ControlFlow::Break(UsesParam) => ty::AnonConstKind::GCA, - ControlFlow::Continue(()) => ty::AnonConstKind::MCG, - } } else if tcx.features().min_generic_const_args() { ty::AnonConstKind::MCG } else if let hir::Node::Expr(hir::Expr { @@ -1667,49 +1651,6 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin } } -fn is_anon_const_rhs_of_const_item<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool { - let hir_id = tcx.local_def_id_to_hir_id(def_id); - let Some((_, grandparent_node)) = tcx.hir_parent_iter(hir_id).nth(1) else { return false }; - let (Node::Item(hir::Item { kind: hir::ItemKind::Const(_, _, _, ct_rhs), .. }) - | Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(_, ct_rhs), .. }) - | Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Const(_, Some(ct_rhs)), .. - })) = grandparent_node - else { - return false; - }; - let hir::ConstItemRhs::TypeConst(hir::ConstArg { - kind: hir::ConstArgKind::Anon(rhs_anon), .. - }) = ct_rhs - else { - return false; - }; - def_id == rhs_anon.def_id -} - -struct GCAParamVisitor<'tcx>(TyCtxt<'tcx>); - -struct UsesParam; - -impl<'tcx> Visitor<'tcx> for GCAParamVisitor<'tcx> { - type NestedFilter = nested_filter::OnlyBodies; - type Result = ControlFlow; - - fn maybe_tcx(&mut self) -> TyCtxt<'tcx> { - self.0 - } - - fn visit_path(&mut self, path: &hir::Path<'tcx>, _id: HirId) -> ControlFlow { - if let Res::Def(DefKind::TyParam | DefKind::ConstParam | DefKind::LifetimeParam, _) = - path.res - { - return ControlFlow::Break(UsesParam); - } - - intravisit::walk_path(self, path) - } -} - #[instrument(level = "debug", skip(tcx), ret)] fn const_of_item<'tcx>( tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 94bd2b1d2a056..64f12fd6644c5 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -97,8 +97,6 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { match tcx.anon_const_kind(def_id) { // Stable: anon consts are not able to use any generic parameters... ty::AnonConstKind::MCG => None, - // GCA anon consts inherit their parent's generics. - ty::AnonConstKind::GCA => Some(parent_did), // we provide generics to repeat expr counts as a backwards compatibility hack. #76200 ty::AnonConstKind::RepeatExprCount => Some(parent_did), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 62f5d63362a28..5e3e83b9361e3 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -409,7 +409,7 @@ impl<'tcx> ForbidParamUsesFolder<'tcx> { } ForbidParamContext::ConstArgument => { if self.tcx.features().generic_const_args() { - "generic parameters in const blocks are only allowed as the direct value of a `type const`" + "generic parameters in const blocks are not allowed; use a named `const` item instead" } else { "generic parameters may not be used in const operations" } @@ -535,9 +535,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { None } } - ty::AnonConstKind::GCE - | ty::AnonConstKind::GCA - | ty::AnonConstKind::RepeatExprCount => None, + ty::AnonConstKind::GCE | ty::AnonConstKind::RepeatExprCount => None, } } diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 4bcc7a5eb02e8..2baf423e296d6 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -389,7 +389,7 @@ pub(crate) struct SelfInConstGenericTy { #[derive(Diagnostic)] #[diag( "{$is_gca -> - [true] generic parameters in const blocks are only allowed as the direct value of a `type const` + [true] generic parameters in const blocks are not allowed; use a named `const` item instead *[false] generic parameters may not be used in const operations }" )] diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 678f1ee96abbb..5ddfaf361940c 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -688,8 +688,7 @@ pub fn try_evaluate_const<'tcx>( (args, typing_env) } - Some((_, ty::AnonConstKind::GCA)) - | Some((_, ty::AnonConstKind::MCG)) + Some((_, ty::AnonConstKind::MCG)) | Some((_, ty::AnonConstKind::NonTypeSystem)) | None => { // We are only dealing with "truly" generic/uninferred constants here: diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index ddcdca9e2370d..b3a33b775ad10 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -289,9 +289,6 @@ pub enum AnonConstKind { GCE, /// stable `min_const_generics` anon consts are not allowed to use any generic parameters MCG, - /// `feature(generic_const_args)` anon consts are allowed to use arbitrary - /// generic parameters in scope, but only if they syntactically reference them. - GCA, /// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters /// but must not depend on the actual instantiation. See #76200 for more information RepeatExprCount, diff --git a/tests/ui/const-generics/gca/basic-different-definitions.rs b/tests/ui/const-generics/gca/basic-different-definitions.rs index ec26f26630a57..bd07cc2d5a26c 100644 --- a/tests/ui/const-generics/gca/basic-different-definitions.rs +++ b/tests/ui/const-generics/gca/basic-different-definitions.rs @@ -6,9 +6,9 @@ #![feature(generic_const_args)] #![expect(incomplete_features)] -type const ADD1: usize = const { N + 1 }; +const ADD1: usize = N + 1; -type const INC: usize = const { N + 1 }; +const INC: usize = N + 1; type const ONE: usize = ADD1::<0>; diff --git a/tests/ui/const-generics/gca/basic.rs b/tests/ui/const-generics/gca/basic.rs index 40c28c3d38c0e..b4ff018dfa483 100644 --- a/tests/ui/const-generics/gca/basic.rs +++ b/tests/ui/const-generics/gca/basic.rs @@ -6,7 +6,7 @@ #![feature(generic_const_args)] #![expect(incomplete_features)] -type const ADD1: usize = const { N + 1 }; +const ADD1: usize = N + 1; type const INC: usize = ADD1::; diff --git a/tests/ui/const-generics/gca/coherence-fail.rs b/tests/ui/const-generics/gca/coherence-fail.rs index 079c8cf63e144..9b92fec952ce9 100644 --- a/tests/ui/const-generics/gca/coherence-fail.rs +++ b/tests/ui/const-generics/gca/coherence-fail.rs @@ -4,14 +4,14 @@ // computing the same value with different constant items but same generic arguments should fail trait Trait1 {} -type const FOO: usize = const { N + 1 }; -type const BAR: usize = const { N + 1 }; +const FOO: usize = N + 1; +const BAR: usize = N + 1; impl Trait1 for [(); FOO::<1>] {} impl Trait1 for [(); BAR::<1>] {} //~^ ERROR conflicting implementations of trait `Trait1` for type `[(); 2]` // computing the same value with the same constant item but different generic arguments should fail -type const DIV2: usize = const { N / 2 }; +const DIV2: usize = N / 2; trait Trait2 {} impl Trait2 for [(); DIV2::<2>] {} impl Trait2 for [(); DIV2::<3>] {} @@ -20,8 +20,8 @@ impl Trait2 for [(); DIV2::<3>] {} // computing the same value with different constant items and different generic arguments should // fail trait Trait3 {} -type const ADD1: usize = const { N + 1 }; -type const SUB1: usize = const { N - 1 }; +const ADD1: usize = N + 1; +const SUB1: usize = N - 1; impl Trait3 for [(); ADD1::<1>] {} impl Trait3 for [(); SUB1::<3>] {} //~^ ERROR conflicting implementations of trait `Trait3` for type `[(); 2]` diff --git a/tests/ui/const-generics/gca/coherence-ok.rs b/tests/ui/const-generics/gca/coherence-ok.rs index 38899badf5f03..1d55c08d3820f 100644 --- a/tests/ui/const-generics/gca/coherence-ok.rs +++ b/tests/ui/const-generics/gca/coherence-ok.rs @@ -5,7 +5,7 @@ // computing different values with the same type const item should be fine -type const ADD1: usize = const { N + 1 }; +const ADD1: usize = N + 1; trait Trait {} diff --git a/tests/ui/const-generics/gca/gca-anon-const-rejected.rs b/tests/ui/const-generics/gca/gca-anon-const-rejected.rs new file mode 100644 index 0000000000000..297beba7eb539 --- /dev/null +++ b/tests/ui/const-generics/gca/gca-anon-const-rejected.rs @@ -0,0 +1,9 @@ +//@ compile-flags: -Znext-solver +// Test that anonymous const blocks using generic parameters are rejected +// under `generic_const_args`. Users should use named const items instead: +// `const FOO: usize = N + 1;` +#![feature(generic_const_args, min_generic_const_args, generic_const_items)] + +type const FOO: usize = const { N + 1 }; //~ ERROR generic parameters in const blocks are not allowed; use a named `const` item instead + +fn main() {} diff --git a/tests/ui/const-generics/gca/gca-anon-const-rejected.stderr b/tests/ui/const-generics/gca/gca-anon-const-rejected.stderr new file mode 100644 index 0000000000000..45ba264b53a39 --- /dev/null +++ b/tests/ui/const-generics/gca/gca-anon-const-rejected.stderr @@ -0,0 +1,10 @@ +error: generic parameters in const blocks are not allowed; use a named `const` item instead + --> $DIR/gca-anon-const-rejected.rs:7:49 + | +LL | type const FOO: usize = const { N + 1 }; + | ^ + | + = help: consider factoring the expression into a `type const` item and use it as the const argument instead + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/gca/generic-param-rhs.rs b/tests/ui/const-generics/gca/generic-param-rhs.rs index ea6e2d7398b57..19a57347a9056 100644 --- a/tests/ui/const-generics/gca/generic-param-rhs.rs +++ b/tests/ui/const-generics/gca/generic-param-rhs.rs @@ -5,6 +5,6 @@ fn foo() {} fn bar() { foo::(); - //~^ ERROR: generic parameters in const blocks are only allowed as the direct value of a `type const` + //~^ ERROR: generic parameters in const blocks are not allowed; use a named `const` item instead } fn main(){} diff --git a/tests/ui/const-generics/gca/generic-param-rhs.stderr b/tests/ui/const-generics/gca/generic-param-rhs.stderr index ca0ce899b8b0d..e4b5e76dbabf3 100644 --- a/tests/ui/const-generics/gca/generic-param-rhs.stderr +++ b/tests/ui/const-generics/gca/generic-param-rhs.stderr @@ -1,4 +1,4 @@ -error: generic parameters in const blocks are only allowed as the direct value of a `type const` +error: generic parameters in const blocks are not allowed; use a named `const` item instead --> $DIR/generic-param-rhs.rs:7:19 | LL | foo::(); diff --git a/tests/ui/const-generics/gca/rhs-but-not-root.rs b/tests/ui/const-generics/gca/rhs-but-not-root.rs index 61762a2851356..9c068bf02b756 100644 --- a/tests/ui/const-generics/gca/rhs-but-not-root.rs +++ b/tests/ui/const-generics/gca/rhs-but-not-root.rs @@ -6,7 +6,7 @@ // Anon consts must be the root of the RHS to be GCA. type const FOO: usize = ID::; -//~^ ERROR generic parameters in const blocks are only allowed as the direct value of a `type const` +//~^ ERROR generic parameters in const blocks are not allowed; use a named `const` item instead type const ID: usize = N; fn main() {} diff --git a/tests/ui/const-generics/gca/rhs-but-not-root.stderr b/tests/ui/const-generics/gca/rhs-but-not-root.stderr index 06f5ae248ac14..7d6f9ae479547 100644 --- a/tests/ui/const-generics/gca/rhs-but-not-root.stderr +++ b/tests/ui/const-generics/gca/rhs-but-not-root.stderr @@ -1,4 +1,4 @@ -error: generic parameters in const blocks are only allowed as the direct value of a `type const` +error: generic parameters in const blocks are not allowed; use a named `const` item instead --> $DIR/rhs-but-not-root.rs:8:54 | LL | type const FOO: usize = ID::;