Exhaustively match in variant count instrinsic

This commit is contained in:
Ngo Iok Ui 2020-11-20 21:49:49 +08:00
parent 172acf8f61
commit 459c83f980
No known key found for this signature in database
GPG Key ID: ECDEF001BA5D2F54
4 changed files with 64 additions and 7 deletions

View File

@ -75,13 +75,16 @@ fn numeric_intrinsic<'tcx, Tag>(
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),
})
}

View File

@ -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::<()>());
}

View File

@ -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<()>>());
}

View File

@ -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