From 894b42c8616f352eacf54bc830c01e33b406fb8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Fri, 4 Jun 2021 00:00:00 +0000 Subject: [PATCH 1/2] Disallow non-monomorphic calls to `needs_drop` in interpreter otherwise evaluation could change after further substitutions. --- .../rustc_mir/src/interpret/intrinsics.rs | 5 ++++- .../ui/consts/const-needs_drop-monomorphic.rs | 17 ++++++++++++++++ .../const-needs_drop-monomorphic.stderr | 20 +++++++++++++++++++ 3 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 src/test/ui/consts/const-needs_drop-monomorphic.rs create mode 100644 src/test/ui/consts/const-needs_drop-monomorphic.stderr diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index 99622fb310a..cdd1edbf286 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -56,7 +56,10 @@ crate fn eval_nullary_intrinsic<'tcx>( let alloc = type_name::alloc_type_name(tcx, tp_ty); ConstValue::Slice { data: alloc, start: 0, end: alloc.len() } } - sym::needs_drop => ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env)), + sym::needs_drop => { + ensure_monomorphic_enough(tcx, tp_ty)?; + ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env)) + } sym::min_align_of | sym::pref_align_of => { let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?; let n = match name { diff --git a/src/test/ui/consts/const-needs_drop-monomorphic.rs b/src/test/ui/consts/const-needs_drop-monomorphic.rs new file mode 100644 index 00000000000..9f66e3cfa23 --- /dev/null +++ b/src/test/ui/consts/const-needs_drop-monomorphic.rs @@ -0,0 +1,17 @@ +// Check that evaluation of needs_drop fails when T is not monomorphic. +#![feature(const_generics)] +#![allow(const_evaluatable_unchecked)] +#![allow(incomplete_features)] + +struct Bool {} +impl Bool { + fn assert() {} +} +fn f() { + Bool::<{ std::mem::needs_drop::() }>::assert(); + //~^ ERROR no function or associated item named `assert` found + //~| ERROR constant expression depends on a generic parameter +} +fn main() { + f::(); +} diff --git a/src/test/ui/consts/const-needs_drop-monomorphic.stderr b/src/test/ui/consts/const-needs_drop-monomorphic.stderr new file mode 100644 index 00000000000..0770d06e15b --- /dev/null +++ b/src/test/ui/consts/const-needs_drop-monomorphic.stderr @@ -0,0 +1,20 @@ +error[E0599]: no function or associated item named `assert` found for struct `Bool<{ std::mem::needs_drop::() }>` in the current scope + --> $DIR/const-needs_drop-monomorphic.rs:11:46 + | +LL | struct Bool {} + | -------------------------- function or associated item `assert` not found for this +... +LL | Bool::<{ std::mem::needs_drop::() }>::assert(); + | ^^^^^^ function or associated item cannot be called on `Bool<{ std::mem::needs_drop::() }>` due to unsatisfied trait bounds + +error: constant expression depends on a generic parameter + --> $DIR/const-needs_drop-monomorphic.rs:11:5 + | +LL | Bool::<{ std::mem::needs_drop::() }>::assert(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. From 07a03b0a58438778336f525f5e567e44500704c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Mi=C4=85sko?= Date: Sat, 5 Jun 2021 00:00:00 +0000 Subject: [PATCH 2/2] Explain that `ensure_monomorphic_enough` omission is intentional --- compiler/rustc_mir/src/interpret/intrinsics.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_mir/src/interpret/intrinsics.rs b/compiler/rustc_mir/src/interpret/intrinsics.rs index cdd1edbf286..4e4166dad50 100644 --- a/compiler/rustc_mir/src/interpret/intrinsics.rs +++ b/compiler/rustc_mir/src/interpret/intrinsics.rs @@ -61,6 +61,7 @@ crate fn eval_nullary_intrinsic<'tcx>( ConstValue::from_bool(tp_ty.needs_drop(tcx, param_env)) } sym::min_align_of | sym::pref_align_of => { + // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough. let layout = tcx.layout_of(param_env.and(tp_ty)).map_err(|e| err_inval!(Layout(e)))?; let n = match name { sym::pref_align_of => layout.align.pref.bytes(), @@ -74,6 +75,7 @@ crate fn eval_nullary_intrinsic<'tcx>( ConstValue::from_u64(tcx.type_id_hash(tp_ty)) } sym::variant_count => match tp_ty.kind() { + // Correctly handles non-monomorphic calls, so there is no need for ensure_monomorphic_enough. ty::Adt(ref adt, _) => ConstValue::from_machine_usize(adt.variants.len() as u64, &tcx), ty::Projection(_) | ty::Opaque(_, _)