From 7fe440879ea356529798f3a2dc762906c631b059 Mon Sep 17 00:00:00 2001 From: JayanAXHF Date: Sun, 12 Apr 2026 18:48:27 +0530 Subject: [PATCH] fix(mgca): Allow specifying generic args (of enum) on enum itself in unit & tuple variant constructions in (direct) const args --- .../src/hir_ty_lowering/mod.rs | 50 +++++++++++++++---- ...eric-args-on-enum-variant-segments-fail.rs | 19 +++++++ ...-args-on-enum-variant-segments-fail.stderr | 41 +++++++++++++++ .../generic-args-on-enum-variant-segments.rs | 16 ++++++ 4 files changed, 115 insertions(+), 11 deletions(-) create mode 100644 tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs create mode 100644 tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr create mode 100644 tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs 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 5a86e8186a5aa..5aab360f73985 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -2862,33 +2862,61 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let args = self.lower_generic_args_of_path_segment(span, did, segment); ty::Const::new_unevaluated(tcx, ty::UnevaluatedConst::new(did, args)) } - Res::Def(DefKind::Ctor(ctor_of, CtorKind::Const), did) => { + Res::Def(kind @ DefKind::Ctor(ctor_of, CtorKind::Const), did) => { assert_eq!(opt_self_ty, None); - let [leading_segments @ .., segment] = path.segments else { bug!() }; - let _ = self - .prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None); + let generic_segments = + self.probe_generic_path_segments(path.segments, opt_self_ty, kind, did, span); + let indices: FxHashSet<_> = + generic_segments.iter().map(|GenericPathSegment(_, index)| index).collect(); + let _ = self.prohibit_generic_args( + path.segments.iter().enumerate().filter_map(|(index, seg)| { + if !indices.contains(&index) { Some(seg) } else { None } + }), + GenericsArgsErrExtend::DefVariant(&path.segments), + ); let parent_did = tcx.parent(did); let generics_did = match ctor_of { CtorOf::Variant => tcx.parent(parent_did), CtorOf::Struct => parent_did, }; - let args = self.lower_generic_args_of_path_segment(span, generics_did, segment); - + let args = self.lower_generic_args_of_path_segment( + span, + generics_did, + &path.segments[generic_segments[0].1], + ); self.construct_const_ctor_value(did, ctor_of, args) } - Res::Def(DefKind::Ctor(_, CtorKind::Fn), did) => { + Res::Def(DefKind::Ctor(ctor_of, CtorKind::Fn), did) => { assert_eq!(opt_self_ty, None); - let [leading_segments @ .., segment] = path.segments else { bug!() }; - let _ = self - .prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None); + let generic_segments = self.probe_generic_path_segments( + path.segments, + opt_self_ty, + DefKind::Ctor(ctor_of, CtorKind::Const), + did, + span, + ); + let indices: FxHashSet<_> = + generic_segments.iter().map(|GenericPathSegment(_, index)| index).collect(); + let _ = self.prohibit_generic_args( + path.segments.iter().enumerate().filter_map(|(index, seg)| { + if !indices.contains(&index) { Some(seg) } else { None } + }), + GenericsArgsErrExtend::DefVariant(&path.segments), + ); + let parent_did = tcx.parent(did); let generics_did = if let DefKind::Ctor(CtorOf::Variant, _) = tcx.def_kind(did) { tcx.parent(parent_did) } else { parent_did }; - let args = self.lower_generic_args_of_path_segment(span, generics_did, segment); + let args = self.lower_generic_args_of_path_segment( + span, + generics_did, + &path.segments[generic_segments[0].1], + ); + ty::Const::zero_sized(tcx, Ty::new_fn_def(tcx, did, args)) } Res::Def(DefKind::AssocConst { .. }, did) => { diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs new file mode 100644 index 0000000000000..9e4443b1fc1c5 --- /dev/null +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs @@ -0,0 +1,19 @@ +#![feature(min_generic_const_args)] +#![feature(adt_const_params, unsized_const_params)] +#[derive(PartialEq, Eq, std::marker::ConstParamTy)] +pub enum Enum { + Unit, + Tuple(), + Store(T), +} +pub mod module { + pub use super::Enum::Store; +} +fn main() { + type const _: Enum<()> = Enum::<()>::Unit::<()>; + //~^ ERROR: type arguments are not allowed on unit variant `Unit` [E0109] + type const _: Enum<()> = Enum::<()>::Tuple::<()>(); + //~^ ERROR: type arguments are not allowed on tuple variant `Tuple` [E0109] + type const _: Enum<()> = self::::Enum::<()>::Store; + //~^ ERROR: type arguments are not allowed on module `generic_args_on_enum_variant_segments_fail` [E0109] +} diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr new file mode 100644 index 0000000000000..ec129b3e33213 --- /dev/null +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr @@ -0,0 +1,41 @@ +error[E0109]: type arguments are not allowed on unit variant `Unit` + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:13:49 + | +LL | type const _: Enum<()> = Enum::<()>::Unit::<()>; + | ---- ^^ type argument not allowed + | | + | not allowed on unit variant `Unit` + | + = note: generic arguments are not allowed on both an enum and its variant's path segments simultaneously; they are only valid in one place or the other +help: remove the generics arguments from one of the path segments + | +LL - type const _: Enum<()> = Enum::<()>::Unit::<()>; +LL + type const _: Enum<()> = Enum::<()>::Unit; + | + +error[E0109]: type arguments are not allowed on tuple variant `Tuple` + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:15:50 + | +LL | type const _: Enum<()> = Enum::<()>::Tuple::<()>(); + | ----- ^^ type argument not allowed + | | + | not allowed on tuple variant `Tuple` + | + = note: generic arguments are not allowed on both an enum and its variant's path segments simultaneously; they are only valid in one place or the other +help: remove the generics arguments from one of the path segments + | +LL - type const _: Enum<()> = Enum::<()>::Tuple::<()>(); +LL + type const _: Enum<()> = Enum::<()>::Tuple(); + | + +error[E0109]: type arguments are not allowed on module `generic_args_on_enum_variant_segments_fail` + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:17:37 + | +LL | type const _: Enum<()> = self::::Enum::<()>::Store; + | ---- ^^^ type argument not allowed + | | + | not allowed on module `generic_args_on_enum_variant_segments_fail` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0109`. diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs new file mode 100644 index 0000000000000..caac7a3b23a50 --- /dev/null +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs @@ -0,0 +1,16 @@ +//@ check-pass + +#![feature(min_generic_const_args)] +#![feature(adt_const_params, unsized_const_params)] + +#[derive(PartialEq, Eq, std::marker::ConstParamTy)] +enum Enum { + Unit, + Tuple(), + Store(T), +} + +type const _: Enum<()> = Enum::<()>::Unit; +type const _: Enum<()> = Enum::<()>::Tuple(); + +fn main() {}