about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_mir/src/interpret/intrinsics.rs17
-rw-r--r--src/test/ui/consts/issue-79137-monomorphic.rs19
-rw-r--r--src/test/ui/consts/issue-79137-toogeneric.rs21
-rw-r--r--src/test/ui/consts/issue-79137-toogeneric.stderr14
4 files changed, 64 insertions, 7 deletions
diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs
index d3b6d706337..d4857e00d3a 100644
--- a/compiler/rustc_mir/src/interpret/intrinsics.rs
+++ b/compiler/rustc_mir/src/interpret/intrinsics.rs
@@ -75,13 +75,16 @@ crate fn eval_nullary_intrinsic<'tcx>(
             ensure_monomorphic_enough(tcx, tp_ty)?;
             ConstValue::from_u64(tcx.type_id_hash(tp_ty))
         }
-        sym::variant_count => {
-            if let ty::Adt(ref adt, _) = tp_ty.kind() {
-                ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx)
-            } else {
-                ConstValue::from_machine_usize(0u64, &tcx)
-            }
-        }
+        sym::variant_count => match tp_ty.kind() {
+            ty::Adt(ref adt, _) => ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx),
+            ty::Projection(_)
+            | ty::Opaque(_, _)
+            | ty::Param(_)
+            | ty::Bound(_, _)
+            | ty::Placeholder(_)
+            | ty::Infer(_) => throw_inval!(TooGeneric),
+            _ => ConstValue::from_machine_usize(0u64, &tcx),
+        },
         other => bug!("`{}` is not a zero arg intrinsic", other),
     })
 }
diff --git a/src/test/ui/consts/issue-79137-monomorphic.rs b/src/test/ui/consts/issue-79137-monomorphic.rs
new file mode 100644
index 00000000000..58e0c387ffb
--- /dev/null
+++ b/src/test/ui/consts/issue-79137-monomorphic.rs
@@ -0,0 +1,19 @@
+// check-pass
+
+// Verify that variant count intrinsic can still evaluate for types like `Option<T>`.
+
+#![feature(variant_count)]
+
+pub struct GetVariantCount<T>(T);
+
+impl<T> GetVariantCount<T> {
+    pub const VALUE: usize = std::mem::variant_count::<T>();
+}
+
+const fn check_variant_count<T>() -> bool {
+    matches!(GetVariantCount::<Option<T>>::VALUE, GetVariantCount::<Option<()>>::VALUE)
+}
+
+fn main() {
+    assert!(check_variant_count::<()>());
+}
diff --git a/src/test/ui/consts/issue-79137-toogeneric.rs b/src/test/ui/consts/issue-79137-toogeneric.rs
new file mode 100644
index 00000000000..b2c62099de5
--- /dev/null
+++ b/src/test/ui/consts/issue-79137-toogeneric.rs
@@ -0,0 +1,21 @@
+// The instrinsic call for variant count should exhaustively match on `tp_ty` and forbid
+// `ty::Projection`, `ty::Opaque`, `ty::Param`, `ty::Bound`, `ty::Placeholder` and `ty::Infer`
+// variant. This test checks that it will fail if it's too generic.
+
+#![feature(variant_count)]
+
+pub struct GetVariantCount<T>(T);
+
+impl<T> GetVariantCount<T> {
+    pub const VALUE: usize = std::mem::variant_count::<T>();
+}
+
+const fn check_variant_count<T>() -> bool {
+    matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
+    //~^ ERROR constant pattern depends on a generic parameter
+    //~| ERROR constant pattern depends on a generic parameter
+}
+
+fn main() {
+    assert!(check_variant_count::<Option<()>>());
+}
diff --git a/src/test/ui/consts/issue-79137-toogeneric.stderr b/src/test/ui/consts/issue-79137-toogeneric.stderr
new file mode 100644
index 00000000000..945bfa452c7
--- /dev/null
+++ b/src/test/ui/consts/issue-79137-toogeneric.stderr
@@ -0,0 +1,14 @@
+error: constant pattern depends on a generic parameter
+  --> $DIR/issue-79137-toogeneric.rs:14:43
+   |
+LL |     matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: constant pattern depends on a generic parameter
+  --> $DIR/issue-79137-toogeneric.rs:14:43
+   |
+LL |     matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
+   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+