mir::StatementKind::StorageDead(ref lvalue) => {
lvalue.hash_stable(hcx, hasher);
}
- mir::StatementKind::EndRegion(ref extents) => {
- extents.hash_stable(hcx, hasher);
+ mir::StatementKind::EndRegion(ref extent) => {
+ extent.hash_stable(hcx, hasher);
+ }
+ mir::StatementKind::Validate(ref op, ref lvalues) => {
+ op.hash_stable(hcx, hasher);
+ lvalues.hash_stable(hcx, hasher);
}
mir::StatementKind::Nop => {}
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
}
}
+impl_stable_hash_for!(enum mir::ValidationOp { Acquire, Release, Suspend(extent) });
+
impl<'a, 'gcx, 'tcx> HashStable<StableHashingContext<'a, 'gcx, 'tcx>> for mir::Lvalue<'tcx> {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'a, 'gcx, 'tcx>,
/// End the current live range for the storage of the local.
StorageDead(Lvalue<'tcx>),
+ /// Execute a piece of inline Assembly.
InlineAsm {
asm: Box<InlineAsm>,
outputs: Vec<Lvalue<'tcx>>,
inputs: Vec<Operand<'tcx>>
},
+ /// Assert the given lvalues to be valid inhabitants of their type.
+ Validate(ValidationOp, Vec<(Ty<'tcx>, Lvalue<'tcx>)>),
+
/// Mark one terminating point of an extent (i.e. static region).
/// (The starting point(s) arise implicitly from borrows.)
EndRegion(CodeExtent),
Nop,
}
+#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, PartialEq, Eq)]
+pub enum ValidationOp {
+ Acquire,
+ Release,
+ Suspend(CodeExtent),
+}
+
impl<'tcx> Debug for Statement<'tcx> {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
use self::StatementKind::*;
Assign(ref lv, ref rv) => write!(fmt, "{:?} = {:?}", lv, rv),
// (reuse lifetime rendering policy from ppaux.)
EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)),
+ Validate(ref op, ref lvalues) => write!(fmt, "Validate({:?}, {:?})", op, lvalues),
StorageLive(ref lv) => write!(fmt, "StorageLive({:?})", lv),
StorageDead(ref lv) => write!(fmt, "StorageDead({:?})", lv),
SetDiscriminant{lvalue: ref lv, variant_index: index} => {
// trait with a `fn fold_extent`.
EndRegion(ref extent) => EndRegion(extent.clone()),
+ Validate(ref op, ref lvals) =>
+ Validate(op.clone(),
+ lvals.iter().map(|ty_and_lval| ty_and_lval.fold_with(folder)).collect()),
+
Nop => Nop,
};
Statement {
// trait with a `fn visit_extent`.
EndRegion(ref _extent) => false,
+ Validate(ref _op, ref lvalues) => lvalues.iter().any(|ty_and_lvalue| ty_and_lvalue.visit_with(visitor)),
+
Nop => false,
}
}
self.visit_assign(block, lvalue, rvalue, location);
}
StatementKind::EndRegion(_) => {}
+ StatementKind::Validate(_, ref $($mutability)* lvalues) => {
+ for & $($mutability)* (ref $($mutability)* ty, ref $($mutability)* lvalue) in lvalues {
+ self.visit_ty(ty, Lookup::Loc(location));
+ self.visit_lvalue(lvalue, LvalueContext::Validate, location);
+ }
+ }
StatementKind::SetDiscriminant{ ref $($mutability)* lvalue, .. } => {
self.visit_lvalue(lvalue, LvalueContext::Store, location);
}
// Starting and ending a storage live range
StorageLive,
StorageDead,
+
+ // Validation command
+ Validate,
}
impl<'tcx> LvalueContext<'tcx> {
LvalueContext::Borrow { kind: BorrowKind::Shared, .. } |
LvalueContext::Borrow { kind: BorrowKind::Unique, .. } |
LvalueContext::Projection(Mutability::Not) | LvalueContext::Consume |
- LvalueContext::StorageLive | LvalueContext::StorageDead => false,
+ LvalueContext::StorageLive | LvalueContext::StorageDead |
+ LvalueContext::Validate => false,
}
}
LvalueContext::Projection(Mutability::Not) | LvalueContext::Consume => true,
LvalueContext::Borrow { kind: BorrowKind::Mut, .. } | LvalueContext::Store |
LvalueContext::Call | LvalueContext::Projection(Mutability::Mut) |
- LvalueContext::Drop | LvalueContext::StorageLive | LvalueContext::StorageDead => false,
+ LvalueContext::Drop | LvalueContext::StorageLive | LvalueContext::StorageDead |
+ LvalueContext::Validate => false,
}
}
mir::StatementKind::StorageDead(_) |
mir::StatementKind::InlineAsm { .. } |
mir::StatementKind::EndRegion(_) |
+ mir::StatementKind::Validate(..) |
mir::StatementKind::Nop => {}
},
None => {
mir::StatementKind::StorageDead(_) |
mir::StatementKind::InlineAsm { .. } |
mir::StatementKind::EndRegion(_) |
+ mir::StatementKind::Validate(..) |
mir::StatementKind::Nop => {}
}
}
}
StatementKind::InlineAsm { .. } |
StatementKind::EndRegion(_) |
+ StatementKind::Validate(..) |
StatementKind::Nop => {}
}
}
StatementKind::StorageDead(_) |
StatementKind::InlineAsm {..} |
StatementKind::EndRegion(_) |
+ StatementKind::Validate(..) |
StatementKind::Nop => {}
}
});
mir::StatementKind::StorageDead(_) |
mir::StatementKind::InlineAsm { .. } |
mir::StatementKind::EndRegion(_) |
+ mir::StatementKind::Validate(..) |
mir::StatementKind::Nop => continue,
mir::StatementKind::SetDiscriminant{ .. } =>
span_bug!(stmt.source_info.span,
}
StatementKind::InlineAsm { .. } |
StatementKind::EndRegion(_) |
+ StatementKind::Validate(..) |
StatementKind::Nop => {}
}
}
self.record(match statement.kind {
StatementKind::Assign(..) => "StatementKind::Assign",
StatementKind::EndRegion(..) => "StatementKind::EndRegion",
+ StatementKind::Validate(..) => "StatementKind::Validate",
StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant",
StatementKind::StorageLive(..) => "StatementKind::StorageLive",
StatementKind::StorageDead(..) => "StatementKind::StorageDead",
LvalueContext::StorageLive |
LvalueContext::StorageDead |
+ LvalueContext::Validate |
LvalueContext::Inspect |
LvalueContext::Consume => {}
}
mir::StatementKind::StorageLive(_) |
mir::StatementKind::StorageDead(_) |
+ mir::StatementKind::Validate(..) |
mir::StatementKind::EndRegion(_) |
mir::StatementKind::Nop => {}
mir::StatementKind::InlineAsm { .. } |
bcx
}
mir::StatementKind::EndRegion(_) |
+ mir::StatementKind::Validate(..) |
mir::StatementKind::Nop => bcx,
}
}