validate TyClosure, TyTuple, TyNever

This commit is contained in:
Ralf Jung 2017-07-13 17:25:38 -07:00 committed by Oliver Schneider
parent dac51f41ad
commit 1f9153fac3
No known key found for this signature in database
GPG key ID: A69F8D225B3AD7D9
3 changed files with 26 additions and 2 deletions

View file

@ -57,6 +57,7 @@ pub enum EvalError<'tcx> {
access: AccessKind,
lock: LockInfo,
},
ValidationFailure(String),
InvalidMemoryLockRelease {
ptr: MemoryPointer,
len: u64,
@ -110,6 +111,8 @@ impl<'tcx> Error for EvalError<'tcx> {
"invalid use of NULL pointer",
MemoryLockViolation { .. } =>
"memory access conflicts with lock",
ValidationFailure(..) =>
"type validation failed",
DeallocatedLockedMemory =>
"deallocated memory while a lock was held",
InvalidMemoryLockRelease { .. } =>
@ -221,6 +224,9 @@ impl<'tcx> fmt::Display for EvalError<'tcx> {
write!(f, "tried to release memory write lock at {:?}, size {}, which was not acquired by this function",
ptr, len)
}
ValidationFailure(ref err) => {
write!(f, "type validation failed: {}", err)
}
NoMirFor(ref func) => write!(f, "no mir for `{}`", func),
FunctionPointerTyMismatch(sig, got) =>
write!(f, "tried to call a function with sig {} through a function pointer of type {}", sig, got),

View file

@ -539,6 +539,9 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
// TODO: Check if these are valid bool/float/UTF-8, respectively (and in particular, not undef).
Ok(())
}
TyNever => {
Err(EvalError::ValidationFailure(format!("The empty type is never valid.")))
}
TyRef(region, ty::TypeAndMut { ty: pointee_ty, mutbl }) => {
let val = self.read_lvalue(lvalue)?;
// Sharing restricts our context
@ -617,6 +620,21 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}
}
}
TyTuple(ref types, _) => {
for (idx, field_ty) in types.iter().enumerate() {
let field_lvalue = self.lvalue_field(lvalue, idx, ty, field_ty)?;
self.validate(field_lvalue, field_ty, vctx)?;
}
Ok(())
}
TyClosure(def_id, ref closure_substs) => {
for (idx, field_ty) in closure_substs.upvar_tys(def_id, self.tcx).enumerate() {
let field_lvalue = self.lvalue_field(lvalue, idx, ty, field_ty)?;
self.validate(field_lvalue, field_ty, vctx)?;
}
Ok(())
}
TyParam(_) | TyInfer(_) => bug!("I got an incomplete type for validation"),
_ => unimplemented!("Unimplemented type encountered when checking validity.")
}
}

View file

@ -132,13 +132,13 @@ impl<'a, 'tcx> EvalContext<'a, 'tcx> {
}
// Validity checks.
Validate(ref op, ref lvalues) => {
Validate(op, ref lvalues) => {
for operand in lvalues {
// We need to monomorphize ty *without* erasing lifetimes
let ty = operand.ty.subst(self.tcx, self.substs());
// TODO: do we have to self.tcx.normalize_associated_type(&{ty}) ? That however seems to erase lifetimes.
let lvalue = self.eval_lvalue(&operand.lval)?;
self.validate(lvalue, ty, ValidationCtx::new(*op))?;
self.validate(lvalue, ty, ValidationCtx::new(op))?;
}
}
EndRegion(ce) => {