Skip to content

Commit 695f972

Browse files
authored
Merge pull request rust-lang#222 from oli-obk/const_eval_checks
Address comments to previous PR
2 parents a589ccb + c8079c6 commit 695f972

File tree

3 files changed

+23
-19
lines changed

3 files changed

+23
-19
lines changed

src/eval_context.rs

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,20 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
169169
&self.stack
170170
}
171171

172+
/// Returns true if the current frame or any parent frame is part of a ctfe.
173+
///
174+
/// Used to disable features in const eval, which do not have a rfc enabling
175+
/// them or which can't be written in a way that they produce the same output
176+
/// that evaluating the code at runtime would produce.
177+
pub fn const_env(&self) -> bool {
178+
for frame in self.stack.iter().rev() {
179+
if let StackPopCleanup::MarkStatic(_) = frame.return_to_block {
180+
return true;
181+
}
182+
}
183+
false
184+
}
185+
172186
pub(crate) fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
173187
let ptr = self.memory.allocate_cached(s.as_bytes())?;
174188
Ok(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::from_u128(s.len() as u128)))
@@ -655,7 +669,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
655669
}
656670

657671
Len(ref lvalue) => {
658-
if self.frame().const_env() {
672+
if self.const_env() {
659673
return Err(EvalError::NeedsRfc("computing the length of arrays".to_string()));
660674
}
661675
let src = self.eval_lvalue(lvalue)?;
@@ -704,7 +718,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
704718
}
705719

706720
NullaryOp(mir::NullOp::Box, ty) => {
707-
if self.frame().const_env() {
721+
if self.const_env() {
708722
return Err(EvalError::NeedsRfc("\"heap\" allocations".to_string()));
709723
}
710724
// FIXME: call the `exchange_malloc` lang item if available
@@ -718,7 +732,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
718732
}
719733

720734
NullaryOp(mir::NullOp::SizeOf, ty) => {
721-
if self.frame().const_env() {
735+
if self.const_env() {
722736
return Err(EvalError::NeedsRfc("computing the size of types (size_of)".to_string()));
723737
}
724738
let size = self.type_size(ty)?.expect("SizeOf nullary MIR operator called for unsized type");
@@ -1592,12 +1606,6 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
15921606
}
15931607

15941608
impl<'tcx> Frame<'tcx> {
1595-
pub fn const_env(&self) -> bool {
1596-
match self.return_to_block {
1597-
StackPopCleanup::MarkStatic(_) => true,
1598-
_ => false,
1599-
}
1600-
}
16011609
pub fn get_local(&self, local: mir::Local) -> EvalResult<'tcx, Value> {
16021610
// Subtract 1 because we don't store a value for the ReturnPointer, the local with index 0.
16031611
self.locals[local.index() - 1].ok_or(EvalError::DeadLocal)

src/operator.rs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,12 +151,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
151151
let usize = PrimValKind::from_uint_size(self.memory.pointer_size());
152152
let isize = PrimValKind::from_int_size(self.memory.pointer_size());
153153
if !left_kind.is_float() && !right_kind.is_float() {
154-
if (!left.is_bytes() && !right.is_bytes()) && self.frame().const_env() {
155-
if left.is_ptr() && right.is_ptr() {
156-
return Err(EvalError::NotConst("Comparing pointers".to_string()));
157-
} else {
158-
return Err(EvalError::NeedsRfc("Comparing Pointers integers with pointers".to_string()));
159-
}
154+
if (!left.is_bytes() && !right.is_bytes()) && self.const_env() {
155+
return Err(EvalError::NeedsRfc("Pointer arithmetic or comparison".to_string()));
160156
}
161157
match bin_op {
162158
Offset if left_kind == Ptr && right_kind == usize => {

src/terminator/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
3737
Goto { target } => self.goto_block(target),
3838

3939
SwitchInt { ref discr, ref values, ref targets, .. } => {
40-
if self.frame().const_env() {
40+
if self.const_env() {
4141
return Err(EvalError::NeedsRfc("branching (if, match, loop, ...)".to_string()));
4242
}
4343
let discr_val = self.eval_operand(discr)?;
@@ -95,7 +95,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
9595

9696
Drop { ref location, target, .. } => {
9797
trace!("TerminatorKind::drop: {:?}, {:?}", location, self.substs());
98-
if self.frame().const_env() {
98+
if self.const_env() {
9999
return Err(EvalError::NeedsRfc("invoking `Drop::drop`".to_string()));
100100
}
101101
let lval = self.eval_lvalue(location)?;
@@ -430,7 +430,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
430430
let mir = match self.load_mir(instance.def) {
431431
Ok(mir) => mir,
432432
Err(EvalError::NoMirFor(path)) => {
433-
if self.frame().const_env() {
433+
if self.const_env() {
434434
return Err(EvalError::NeedsRfc(format!("calling extern function `{}`", path)));
435435
}
436436
self.call_missing_fn(instance, destination, arg_operands, sig, path)?;
@@ -439,7 +439,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
439439
Err(other) => return Err(other),
440440
};
441441

442-
if self.frame().const_env() && !self.tcx.is_const_fn(instance.def_id()) {
442+
if self.const_env() && !self.tcx.is_const_fn(instance.def_id()) {
443443
return Err(EvalError::NotConst(format!("calling non-const fn `{}`", instance)));
444444
}
445445

0 commit comments

Comments
 (0)