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 3f82375308927..a088fdfa23661 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -385,6 +385,8 @@ impl<'tcx> ForbidMCGParamUsesFolder<'tcx> { fn error(&self) -> ErrorGuaranteed { let msg = if self.is_self_alias { "generic `Self` types are currently not permitted in anonymous constants" + } else if self.tcx.features().opaque_generic_const_args() { + "generic parameters in const blocks are only allowed as the direct value of a `type const`" } else { "generic parameters may not be used in const operations" }; @@ -403,11 +405,13 @@ impl<'tcx> ForbidMCGParamUsesFolder<'tcx> { diag.span_note(impl_.self_ty.span, "not a concrete type"); } } - if self.tcx.features().min_generic_const_args() - && !self.tcx.features().opaque_generic_const_args() - { - diag.help("add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items"); - } + if self.tcx.features().min_generic_const_args() { + if !self.tcx.features().opaque_generic_const_args() { + diag.help("add `#![feature(opaque_generic_const_args)]` to allow generic expressions as the RHS of const items"); + } else { + diag.help("consider factoring the expression into a `type const` item and use it as the const argument instead"); + } + }; diag.emit() } } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index ad667df47123f..675cb3e0f352d 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1001,12 +1001,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ResolutionError::ParamInTyOfConstParam { name } => { self.dcx().create_err(errs::ParamInTyOfConstParam { span, name }) } - ResolutionError::ParamInNonTrivialAnonConst { name, param_kind: is_type } => { + ResolutionError::ParamInNonTrivialAnonConst { is_ogca, name, param_kind: is_type } => { self.dcx().create_err(errs::ParamInNonTrivialAnonConst { span, name, param_kind: is_type, help: self.tcx.sess.is_nightly_build(), + is_ogca, + help_ogca: is_ogca, }) } ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => self diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 1ca5c17856262..62e2c9deaf4f4 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -405,7 +405,12 @@ pub(crate) struct SelfInConstGenericTy { } #[derive(Diagnostic)] -#[diag("generic parameters may not be used in const operations")] +#[diag( + "{$is_ogca -> + [true] generic parameters in const blocks are only allowed as the direct value of a `type const` + *[false] generic parameters may not be used in const operations +}" +)] pub(crate) struct ParamInNonTrivialAnonConst { #[primary_span] #[label("cannot perform const operation using `{$name}`")] @@ -415,6 +420,11 @@ pub(crate) struct ParamInNonTrivialAnonConst { pub(crate) param_kind: ParamKindInNonTrivialAnonConst, #[help("add `#![feature(generic_const_exprs)]` to allow generic const expressions")] pub(crate) help: bool, + pub(crate) is_ogca: bool, + #[help( + "consider factoring the expression into a `type const` item and use it as the const argument instead" + )] + pub(crate) help_ogca: bool, } #[derive(Debug)] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 59a5c0728a753..1591456108277 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1554,6 +1554,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } NoConstantGenericsReason::NonTrivialConstArg => { ResolutionError::ParamInNonTrivialAnonConst { + is_ogca: self + .tcx + .features() + .opaque_generic_const_args(), name: rib_ident.name, param_kind: ParamKindInNonTrivialAnonConst::Type, } @@ -1645,6 +1649,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } NoConstantGenericsReason::NonTrivialConstArg => { ResolutionError::ParamInNonTrivialAnonConst { + is_ogca: self + .tcx + .features() + .opaque_generic_const_args(), name: rib_ident.name, param_kind: ParamKindInNonTrivialAnonConst::Const { name: rib_ident.name, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index b1d6e3526d9cd..f6bb20b7edb67 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3726,6 +3726,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { name: lifetime_ref.ident.name, param_kind: errors::ParamKindInNonTrivialAnonConst::Lifetime, help: self.r.tcx.sess.is_nightly_build(), + is_ogca: self.r.tcx.features().opaque_generic_const_args(), + help_ogca: self.r.tcx.features().opaque_generic_const_args(), }) .emit() } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 1368e5deb6487..45cbc0b3c828d 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -309,7 +309,11 @@ enum ResolutionError<'ra> { /// generic parameters must not be used inside const evaluations. /// /// This error is only emitted when using `min_const_generics`. - ParamInNonTrivialAnonConst { name: Symbol, param_kind: ParamKindInNonTrivialAnonConst }, + ParamInNonTrivialAnonConst { + is_ogca: bool, + name: Symbol, + param_kind: ParamKindInNonTrivialAnonConst, + }, /// generic parameters must not be used inside enum discriminants. /// /// This error is emitted even with `generic_const_exprs`. diff --git a/tests/ui/const-generics/ogca/generic-param-rhs.rs b/tests/ui/const-generics/ogca/generic-param-rhs.rs new file mode 100644 index 0000000000000..a62b509190bd6 --- /dev/null +++ b/tests/ui/const-generics/ogca/generic-param-rhs.rs @@ -0,0 +1,9 @@ +#![feature(min_generic_const_args, opaque_generic_const_args)] +#![expect(incomplete_features)] + +fn foo() {} +fn bar() { + foo::(); + //~^ ERROR: generic parameters in const blocks are only allowed as the direct value of a `type const` +} +fn main(){} diff --git a/tests/ui/const-generics/ogca/generic-param-rhs.stderr b/tests/ui/const-generics/ogca/generic-param-rhs.stderr new file mode 100644 index 0000000000000..acf3a5b21a855 --- /dev/null +++ b/tests/ui/const-generics/ogca/generic-param-rhs.stderr @@ -0,0 +1,10 @@ +error: generic parameters in const blocks are only allowed as the direct value of a `type const` + --> $DIR/generic-param-rhs.rs:6:19 + | +LL | foo::(); + | ^ + | + = 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/ogca/rhs-but-not-root.rs b/tests/ui/const-generics/ogca/rhs-but-not-root.rs index 2897b16d493f7..bb6c6b667e1d0 100644 --- a/tests/ui/const-generics/ogca/rhs-but-not-root.rs +++ b/tests/ui/const-generics/ogca/rhs-but-not-root.rs @@ -5,8 +5,7 @@ // Anon consts must be the root of the RHS to be OGCA. type const FOO: usize = ID::; -//~^ ERROR generic parameters may not be used in const operations - +//~^ ERROR generic parameters in const blocks are only allowed as the direct value of a `type const` type const ID: usize = N; fn main() {} diff --git a/tests/ui/const-generics/ogca/rhs-but-not-root.stderr b/tests/ui/const-generics/ogca/rhs-but-not-root.stderr index c720b58b9bde9..6481407eedc42 100644 --- a/tests/ui/const-generics/ogca/rhs-but-not-root.stderr +++ b/tests/ui/const-generics/ogca/rhs-but-not-root.stderr @@ -1,8 +1,10 @@ -error: generic parameters may not be used in const operations +error: generic parameters in const blocks are only allowed as the direct value of a `type const` --> $DIR/rhs-but-not-root.rs:7:54 | LL | type const FOO: usize = ID::; | ^ + | + = 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