Skip to content

Commit 459c83f

Browse files
author
Ngo Iok Ui
committed
Exhaustively match in variant count instrinsic
1 parent 172acf8 commit 459c83f

File tree

4 files changed

+64
-7
lines changed

4 files changed

+64
-7
lines changed

compiler/rustc_mir/src/interpret/intrinsics.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -75,13 +75,16 @@ crate fn eval_nullary_intrinsic<'tcx>(
7575
ensure_monomorphic_enough(tcx, tp_ty)?;
7676
ConstValue::from_u64(tcx.type_id_hash(tp_ty))
7777
}
78-
sym::variant_count => {
79-
if let ty::Adt(ref adt, _) = tp_ty.kind() {
80-
ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx)
81-
} else {
82-
ConstValue::from_machine_usize(0u64, &tcx)
83-
}
84-
}
78+
sym::variant_count => match tp_ty.kind() {
79+
ty::Adt(ref adt, _) => ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx),
80+
ty::Projection(_)
81+
| ty::Opaque(_, _)
82+
| ty::Param(_)
83+
| ty::Bound(_, _)
84+
| ty::Placeholder(_)
85+
| ty::Infer(_) => throw_inval!(TooGeneric),
86+
_ => ConstValue::from_machine_usize(0u64, &tcx),
87+
},
8588
other => bug!("`{}` is not a zero arg intrinsic", other),
8689
})
8790
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// check-pass
2+
3+
// Verify that variant count intrinsic can still evaluate for types like `Option<T>`.
4+
5+
#![feature(variant_count)]
6+
7+
pub struct GetVariantCount<T>(T);
8+
9+
impl<T> GetVariantCount<T> {
10+
pub const VALUE: usize = std::mem::variant_count::<T>();
11+
}
12+
13+
const fn check_variant_count<T>() -> bool {
14+
matches!(GetVariantCount::<Option<T>>::VALUE, GetVariantCount::<Option<()>>::VALUE)
15+
}
16+
17+
fn main() {
18+
assert!(check_variant_count::<()>());
19+
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// The instrinsic call for variant count should exhaustively match on `tp_ty` and forbid
2+
// `ty::Projection`, `ty::Opaque`, `ty::Param`, `ty::Bound`, `ty::Placeholder` and `ty::Infer`
3+
// variant. This test checks that it will fail if it's too generic.
4+
5+
#![feature(variant_count)]
6+
7+
pub struct GetVariantCount<T>(T);
8+
9+
impl<T> GetVariantCount<T> {
10+
pub const VALUE: usize = std::mem::variant_count::<T>();
11+
}
12+
13+
const fn check_variant_count<T>() -> bool {
14+
matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
15+
//~^ ERROR constant pattern depends on a generic parameter
16+
//~| ERROR constant pattern depends on a generic parameter
17+
}
18+
19+
fn main() {
20+
assert!(check_variant_count::<Option<()>>());
21+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
error: constant pattern depends on a generic parameter
2+
--> $DIR/issue-79137-toogeneric.rs:14:43
3+
|
4+
LL | matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
6+
7+
error: constant pattern depends on a generic parameter
8+
--> $DIR/issue-79137-toogeneric.rs:14:43
9+
|
10+
LL | matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
11+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
12+
13+
error: aborting due to 2 previous errors
14+

0 commit comments

Comments
 (0)