diff --git a/src/error.rs b/src/error.rs index e9312a1ef3e6..5624734e888a 100644 --- a/src/error.rs +++ b/src/error.rs @@ -43,6 +43,7 @@ pub enum EvalError<'tcx> { CalledClosureAsFunction, VtableForArgumentlessMethod, ModifiedConstantMemory, + AssumptionNotHeld, } pub type EvalResult<'tcx, T> = Result>; @@ -97,6 +98,8 @@ impl<'tcx> Error for EvalError<'tcx> { "tried to call a vtable function without arguments", EvalError::ModifiedConstantMemory => "tried to modify constant memory", + EvalError::AssumptionNotHeld => + "`assume` argument was false" } } diff --git a/src/interpreter/terminator.rs b/src/interpreter/terminator.rs index 9984e1f14eaf..23396e0694e1 100644 --- a/src/interpreter/terminator.rs +++ b/src/interpreter/terminator.rs @@ -284,8 +284,11 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> { "sub_with_overflow" => self.intrinsic_with_overflow(mir::BinOp::Sub, &args[0], &args[1], dest, dest_layout)?, "mul_with_overflow" => self.intrinsic_with_overflow(mir::BinOp::Mul, &args[0], &args[1], dest, dest_layout)?, - // FIXME: turn into an assertion to catch wrong `assume` that would cause UB in llvm - "assume" => {} + "assume" => { + if !self.memory.read_bool(args_ptrs[0])? { + return Err(EvalError::AssumptionNotHeld); + } + } "copy_nonoverlapping" => { let elem_ty = substs.type_at(0); diff --git a/tests/compile-fail/assume.rs b/tests/compile-fail/assume.rs new file mode 100644 index 000000000000..69758a5d7fe8 --- /dev/null +++ b/tests/compile-fail/assume.rs @@ -0,0 +1,10 @@ +#![feature(core_intrinsics)] + +fn main() { + let x = 5; + unsafe { + std::intrinsics::assume(x < 10); + std::intrinsics::assume(x > 1); + std::intrinsics::assume(x > 42); //~ ERROR: `assume` argument was false + } +}