Skip to content

Commit

Permalink
Merge pull request #222 from oli-obk/const_eval_checks
Browse files Browse the repository at this point in the history
Address comments to previous PR
  • Loading branch information
oli-obk authored Jun 28, 2017
2 parents a589ccb + c8079c6 commit 695f972
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 19 deletions.
26 changes: 17 additions & 9 deletions src/eval_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,20 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
&self.stack
}

/// Returns true if the current frame or any parent frame is part of a ctfe.
///
/// Used to disable features in const eval, which do not have a rfc enabling
/// them or which can't be written in a way that they produce the same output
/// that evaluating the code at runtime would produce.
pub fn const_env(&self) -> bool {
for frame in self.stack.iter().rev() {
if let StackPopCleanup::MarkStatic(_) = frame.return_to_block {
return true;
}
}
false
}

pub(crate) fn str_to_value(&mut self, s: &str) -> EvalResult<'tcx, Value> {
let ptr = self.memory.allocate_cached(s.as_bytes())?;
Ok(Value::ByValPair(PrimVal::Ptr(ptr), PrimVal::from_u128(s.len() as u128)))
Expand Down Expand Up @@ -655,7 +669,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}

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

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

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

impl<'tcx> Frame<'tcx> {
pub fn const_env(&self) -> bool {
match self.return_to_block {
StackPopCleanup::MarkStatic(_) => true,
_ => false,
}
}
pub fn get_local(&self, local: mir::Local) -> EvalResult<'tcx, Value> {
// Subtract 1 because we don't store a value for the ReturnPointer, the local with index 0.
self.locals[local.index() - 1].ok_or(EvalError::DeadLocal)
Expand Down
8 changes: 2 additions & 6 deletions src/operator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,8 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let usize = PrimValKind::from_uint_size(self.memory.pointer_size());
let isize = PrimValKind::from_int_size(self.memory.pointer_size());
if !left_kind.is_float() && !right_kind.is_float() {
if (!left.is_bytes() && !right.is_bytes()) && self.frame().const_env() {
if left.is_ptr() && right.is_ptr() {
return Err(EvalError::NotConst("Comparing pointers".to_string()));
} else {
return Err(EvalError::NeedsRfc("Comparing Pointers integers with pointers".to_string()));
}
if (!left.is_bytes() && !right.is_bytes()) && self.const_env() {
return Err(EvalError::NeedsRfc("Pointer arithmetic or comparison".to_string()));
}
match bin_op {
Offset if left_kind == Ptr && right_kind == usize => {
Expand Down
8 changes: 4 additions & 4 deletions src/terminator/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
Goto { target } => self.goto_block(target),

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

Drop { ref location, target, .. } => {
trace!("TerminatorKind::drop: {:?}, {:?}", location, self.substs());
if self.frame().const_env() {
if self.const_env() {
return Err(EvalError::NeedsRfc("invoking `Drop::drop`".to_string()));
}
let lval = self.eval_lvalue(location)?;
Expand Down Expand Up @@ -430,7 +430,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
let mir = match self.load_mir(instance.def) {
Ok(mir) => mir,
Err(EvalError::NoMirFor(path)) => {
if self.frame().const_env() {
if self.const_env() {
return Err(EvalError::NeedsRfc(format!("calling extern function `{}`", path)));
}
self.call_missing_fn(instance, destination, arg_operands, sig, path)?;
Expand All @@ -439,7 +439,7 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
Err(other) => return Err(other),
};

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

Expand Down

0 comments on commit 695f972

Please sign in to comment.