From 459c83f98026551bb0d3d86ede21e6d7424d375e Mon Sep 17 00:00:00 2001 From: Ngo Iok Ui Date: Fri, 20 Nov 2020 21:49:49 +0800 Subject: [PATCH 1/3] Exhaustively match in variant count instrinsic --- .../rustc_mir/src/interpret/intrinsics.rs | 17 ++++++++------- src/test/ui/consts/issue-79137-monomorphic.rs | 19 +++++++++++++++++ src/test/ui/consts/issue-79137-toogeneric.rs | 21 +++++++++++++++++++ .../ui/consts/issue-79137-toogeneric.stderr | 14 +++++++++++++ 4 files changed, 64 insertions(+), 7 deletions(-) create mode 100644 src/test/ui/consts/issue-79137-monomorphic.rs create mode 100644 src/test/ui/consts/issue-79137-toogeneric.rs create mode 100644 src/test/ui/consts/issue-79137-toogeneric.stderr diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index d3b6d706337ed..d4857e00d3aa5 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 0000000000000..58e0c387ffb9c --- /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`. + +#![feature(variant_count)] + +pub struct GetVariantCount(T); + +impl GetVariantCount { + pub const VALUE: usize = std::mem::variant_count::(); +} + +const fn check_variant_count() -> bool { + matches!(GetVariantCount::>::VALUE, GetVariantCount::>::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 0000000000000..b2c62099de562 --- /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); + +impl GetVariantCount { + pub const VALUE: usize = std::mem::variant_count::(); +} + +const fn check_variant_count() -> bool { + matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) + //~^ ERROR constant pattern depends on a generic parameter + //~| ERROR constant pattern depends on a generic parameter +} + +fn main() { + assert!(check_variant_count::>()); +} 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 0000000000000..945bfa452c70c --- /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::::VALUE, GetVariantCount::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: constant pattern depends on a generic parameter + --> $DIR/issue-79137-toogeneric.rs:14:43 + | +LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + From ef34e067817448d8ffbb9ac70e97699bf8b7566e Mon Sep 17 00:00:00 2001 From: Ngo Iok Ui Date: Sat, 21 Nov 2020 13:45:59 +0800 Subject: [PATCH 2/3] List all variants of TyKind --- .../rustc_mir/src/interpret/intrinsics.rs | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index d4857e00d3aa5..f666a89ca56de 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -83,7 +83,26 @@ crate fn eval_nullary_intrinsic<'tcx>( | ty::Bound(_, _) | ty::Placeholder(_) | ty::Infer(_) => throw_inval!(TooGeneric), - _ => ConstValue::from_machine_usize(0u64, &tcx), + ty::Bool + | ty::Char + | ty::Int(_) + | ty::Uint(_) + | ty::Float(_) + | ty::Foreign(_) + | ty::Str + | ty::Array(_, _) + | ty::Slice(_) + | ty::RawPtr(_) + | ty::Ref(_, _, _) + | ty::FnDef(_, _) + | ty::FnPtr(_) + | ty::Dynamic(_, _) + | ty::Closure(_, _) + | ty::Generator(_, _, _) + | ty::GeneratorWitness(_) + | ty::Never + | ty::Tuple(_) + | ty::Error(_) => ConstValue::from_machine_usize(0u64, &tcx), }, other => bug!("`{}` is not a zero arg intrinsic", other), }) From bc43380297c38f8cc888ce3e92fe20de9afbe50e Mon Sep 17 00:00:00 2001 From: Ngo Iok Ui Date: Sat, 21 Nov 2020 13:47:09 +0800 Subject: [PATCH 3/3] Fix comments of toogeneris test --- src/test/ui/consts/issue-79137-toogeneric.rs | 4 +--- src/test/ui/consts/issue-79137-toogeneric.stderr | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/test/ui/consts/issue-79137-toogeneric.rs b/src/test/ui/consts/issue-79137-toogeneric.rs index b2c62099de562..456035458cfc5 100644 --- a/src/test/ui/consts/issue-79137-toogeneric.rs +++ b/src/test/ui/consts/issue-79137-toogeneric.rs @@ -1,6 +1,4 @@ -// 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. +// Test that `variant_count` only gets evaluated once the type is concrete enough. #![feature(variant_count)] diff --git a/src/test/ui/consts/issue-79137-toogeneric.stderr b/src/test/ui/consts/issue-79137-toogeneric.stderr index 945bfa452c70c..579e6aa09bdbd 100644 --- a/src/test/ui/consts/issue-79137-toogeneric.stderr +++ b/src/test/ui/consts/issue-79137-toogeneric.stderr @@ -1,11 +1,11 @@ error: constant pattern depends on a generic parameter - --> $DIR/issue-79137-toogeneric.rs:14:43 + --> $DIR/issue-79137-toogeneric.rs:12:43 | LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: constant pattern depends on a generic parameter - --> $DIR/issue-79137-toogeneric.rs:14:43 + --> $DIR/issue-79137-toogeneric.rs:12:43 | LL | matches!(GetVariantCount::::VALUE, GetVariantCount::::VALUE) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^