Added UserAssertTy statement.
This commit is contained in:
parent
c0fdb29362
commit
17b285d203
19 changed files with 79 additions and 6 deletions
|
@ -277,6 +277,10 @@ for mir::StatementKind<'gcx> {
|
||||||
op.hash_stable(hcx, hasher);
|
op.hash_stable(hcx, hasher);
|
||||||
places.hash_stable(hcx, hasher);
|
places.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
|
mir::StatementKind::UserAssertTy(ref ty, ref local) => {
|
||||||
|
ty.hash_stable(hcx, hasher);
|
||||||
|
local.hash_stable(hcx, hasher);
|
||||||
|
}
|
||||||
mir::StatementKind::Nop => {}
|
mir::StatementKind::Nop => {}
|
||||||
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
|
mir::StatementKind::InlineAsm { ref asm, ref outputs, ref inputs } => {
|
||||||
asm.hash_stable(hcx, hasher);
|
asm.hash_stable(hcx, hasher);
|
||||||
|
|
|
@ -1253,6 +1253,15 @@ pub enum StatementKind<'tcx> {
|
||||||
/// (The starting point(s) arise implicitly from borrows.)
|
/// (The starting point(s) arise implicitly from borrows.)
|
||||||
EndRegion(region::Scope),
|
EndRegion(region::Scope),
|
||||||
|
|
||||||
|
/// Encodes a user's type assertion. These need to be preserved intact so that NLL can respect
|
||||||
|
/// them. For example:
|
||||||
|
///
|
||||||
|
/// let (a, b): (T, U) = y;
|
||||||
|
///
|
||||||
|
/// Here we would insert a `UserAssertTy<(T, U)>(y)` instruction to check that the type of `y`
|
||||||
|
/// is the right thing.
|
||||||
|
UserAssertTy(Ty<'tcx>, Local),
|
||||||
|
|
||||||
/// No-op. Useful for deleting instructions without affecting statement indices.
|
/// No-op. Useful for deleting instructions without affecting statement indices.
|
||||||
Nop,
|
Nop,
|
||||||
}
|
}
|
||||||
|
@ -1324,6 +1333,7 @@ impl<'tcx> Debug for Statement<'tcx> {
|
||||||
InlineAsm { ref asm, ref outputs, ref inputs } => {
|
InlineAsm { ref asm, ref outputs, ref inputs } => {
|
||||||
write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
|
write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
|
||||||
},
|
},
|
||||||
|
UserAssertTy(ref ty, ref local) => write!(fmt, "UserAssertTy({:?}, {:?})", ty, local),
|
||||||
Nop => write!(fmt, "nop"),
|
Nop => write!(fmt, "nop"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2184,6 +2194,7 @@ EnumTypeFoldableImpl! {
|
||||||
(StatementKind::InlineAsm) { asm, outputs, inputs },
|
(StatementKind::InlineAsm) { asm, outputs, inputs },
|
||||||
(StatementKind::Validate)(a, b),
|
(StatementKind::Validate)(a, b),
|
||||||
(StatementKind::EndRegion)(a),
|
(StatementKind::EndRegion)(a),
|
||||||
|
(StatementKind::UserAssertTy)(a, b),
|
||||||
(StatementKind::Nop),
|
(StatementKind::Nop),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,6 +144,13 @@ macro_rules! make_mir_visitor {
|
||||||
self.super_operand(operand, location);
|
self.super_operand(operand, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_user_assert_ty(&mut self,
|
||||||
|
ty: & $($mutability)* Ty<'tcx>,
|
||||||
|
local: & $($mutability)* Local,
|
||||||
|
location: Location) {
|
||||||
|
self.super_user_assert_ty(ty, local, location);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_place(&mut self,
|
fn visit_place(&mut self,
|
||||||
place: & $($mutability)* Place<'tcx>,
|
place: & $($mutability)* Place<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
|
@ -376,6 +383,10 @@ macro_rules! make_mir_visitor {
|
||||||
self.visit_operand(input, location);
|
self.visit_operand(input, location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
StatementKind::UserAssertTy(ref $($mutability)* ty,
|
||||||
|
ref $($mutability)* local) => {
|
||||||
|
self.visit_user_assert_ty(ty, local, location);
|
||||||
|
}
|
||||||
StatementKind::Nop => {}
|
StatementKind::Nop => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -619,6 +630,14 @@ macro_rules! make_mir_visitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn super_user_assert_ty(&mut self,
|
||||||
|
ty: & $($mutability)* Ty<'tcx>,
|
||||||
|
local: & $($mutability)* Local,
|
||||||
|
location: Location) {
|
||||||
|
self.visit_ty(ty, TyContext::Location(location));
|
||||||
|
self.visit_local(local, PlaceContext::Validate, location);
|
||||||
|
}
|
||||||
|
|
||||||
fn super_place(&mut self,
|
fn super_place(&mut self,
|
||||||
place: & $($mutability)* Place<'tcx>,
|
place: & $($mutability)* Place<'tcx>,
|
||||||
context: PlaceContext<'tcx>,
|
context: PlaceContext<'tcx>,
|
||||||
|
|
|
@ -392,11 +392,13 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||||
// ignored when consuming results (update to
|
// ignored when consuming results (update to
|
||||||
// flow_state already handled).
|
// flow_state already handled).
|
||||||
}
|
}
|
||||||
StatementKind::Nop | StatementKind::Validate(..) | StatementKind::StorageLive(..) => {
|
StatementKind::Nop |
|
||||||
// `Nop`, `Validate`, and `StorageLive` are irrelevant
|
StatementKind::UserAssertTy(..) |
|
||||||
|
StatementKind::Validate(..) |
|
||||||
|
StatementKind::StorageLive(..) => {
|
||||||
|
// `Nop`, `UserAssertTy`, `Validate`, and `StorageLive` are irrelevant
|
||||||
// to borrow check.
|
// to borrow check.
|
||||||
}
|
}
|
||||||
|
|
||||||
StatementKind::StorageDead(local) => {
|
StatementKind::StorageDead(local) => {
|
||||||
self.access_place(
|
self.access_place(
|
||||||
ContextKind::StorageDead.new(location),
|
ContextKind::StorageDead.new(location),
|
||||||
|
|
|
@ -766,6 +766,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||||
| StatementKind::InlineAsm { .. }
|
| StatementKind::InlineAsm { .. }
|
||||||
| StatementKind::EndRegion(_)
|
| StatementKind::EndRegion(_)
|
||||||
| StatementKind::Validate(..)
|
| StatementKind::Validate(..)
|
||||||
|
| StatementKind::UserAssertTy(..)
|
||||||
| StatementKind::Nop => {}
|
| StatementKind::Nop => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,6 +102,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
remainder_scope,
|
remainder_scope,
|
||||||
init_scope,
|
init_scope,
|
||||||
pattern,
|
pattern,
|
||||||
|
ty,
|
||||||
initializer,
|
initializer,
|
||||||
lint_level
|
lint_level
|
||||||
} => {
|
} => {
|
||||||
|
@ -120,12 +121,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
opt_destruction_scope.map(|de|(de, source_info)), block, |this| {
|
opt_destruction_scope.map(|de|(de, source_info)), block, |this| {
|
||||||
let scope = (init_scope, source_info);
|
let scope = (init_scope, source_info);
|
||||||
this.in_scope(scope, lint_level, block, |this| {
|
this.in_scope(scope, lint_level, block, |this| {
|
||||||
this.expr_into_pattern(block, pattern, init)
|
this.expr_into_pattern(block, ty, pattern, init)
|
||||||
})
|
})
|
||||||
}));
|
}));
|
||||||
} else {
|
} else {
|
||||||
this.visit_bindings(&pattern, &mut |this, _, _, node, span, _| {
|
this.visit_bindings(&pattern, &mut |this, _, _, node, span, _| {
|
||||||
this.storage_live_binding(block, node, span);
|
this.storage_live_binding(block, node, span);
|
||||||
|
if let Some(ty) = ty {
|
||||||
|
this.user_assert_ty(block, ty, node, span);
|
||||||
|
}
|
||||||
this.schedule_drop_for_binding(node, span);
|
this.schedule_drop_for_binding(node, span);
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,8 +145,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
end_block.unit()
|
end_block.unit()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn user_assert_ty(&mut self, block: BasicBlock, ty: Ty<'tcx>, var: NodeId, span: Span) {
|
||||||
|
let local_id = self.var_indices[&var];
|
||||||
|
let source_info = self.source_info(span);
|
||||||
|
self.cfg.push(block, Statement {
|
||||||
|
source_info,
|
||||||
|
kind: StatementKind::UserAssertTy(ty, local_id),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
pub fn expr_into_pattern(&mut self,
|
pub fn expr_into_pattern(&mut self,
|
||||||
mut block: BasicBlock,
|
mut block: BasicBlock,
|
||||||
|
ty: Option<Ty<'tcx>>,
|
||||||
irrefutable_pat: Pattern<'tcx>,
|
irrefutable_pat: Pattern<'tcx>,
|
||||||
initializer: ExprRef<'tcx>)
|
initializer: ExprRef<'tcx>)
|
||||||
-> BlockAnd<()> {
|
-> BlockAnd<()> {
|
||||||
|
@ -156,6 +166,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||||
var,
|
var,
|
||||||
subpattern: None, .. } => {
|
subpattern: None, .. } => {
|
||||||
let place = self.storage_live_binding(block, var, irrefutable_pat.span);
|
let place = self.storage_live_binding(block, var, irrefutable_pat.span);
|
||||||
|
|
||||||
|
if let Some(ty) = ty {
|
||||||
|
self.user_assert_ty(block, ty, var, irrefutable_pat.span);
|
||||||
|
}
|
||||||
|
|
||||||
unpack!(block = self.into(&place, block, initializer));
|
unpack!(block = self.into(&place, block, initializer));
|
||||||
self.schedule_drop_for_binding(var, irrefutable_pat.span);
|
self.schedule_drop_for_binding(var, irrefutable_pat.span);
|
||||||
block.unit()
|
block.unit()
|
||||||
|
|
|
@ -678,6 +678,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
|
||||||
mir::StatementKind::SetDiscriminant { .. } |
|
mir::StatementKind::SetDiscriminant { .. } |
|
||||||
mir::StatementKind::StorageLive(..) |
|
mir::StatementKind::StorageLive(..) |
|
||||||
mir::StatementKind::Validate(..) |
|
mir::StatementKind::Validate(..) |
|
||||||
|
mir::StatementKind::UserAssertTy(..) |
|
||||||
mir::StatementKind::Nop => {}
|
mir::StatementKind::Nop => {}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -298,6 +298,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||||
}
|
}
|
||||||
StatementKind::EndRegion(_) |
|
StatementKind::EndRegion(_) |
|
||||||
StatementKind::Validate(..) |
|
StatementKind::Validate(..) |
|
||||||
|
StatementKind::UserAssertTy(..) |
|
||||||
StatementKind::Nop => {}
|
StatementKind::Nop => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,12 +76,14 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
|
||||||
first_statement_index: region::FirstStatementIndex::new(index),
|
first_statement_index: region::FirstStatementIndex::new(index),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let ty = local.ty.clone().map(|ty| cx.tables().node_id_to_type(ty.hir_id));
|
||||||
let pattern = cx.pattern_from_hir(&local.pat);
|
let pattern = cx.pattern_from_hir(&local.pat);
|
||||||
result.push(StmtRef::Mirror(Box::new(Stmt {
|
result.push(StmtRef::Mirror(Box::new(Stmt {
|
||||||
kind: StmtKind::Let {
|
kind: StmtKind::Let {
|
||||||
remainder_scope: remainder_scope,
|
remainder_scope: remainder_scope,
|
||||||
init_scope: region::Scope::Node(hir_id.local_id),
|
init_scope: region::Scope::Node(hir_id.local_id),
|
||||||
pattern,
|
pattern,
|
||||||
|
ty,
|
||||||
initializer: local.init.to_ref(),
|
initializer: local.init.to_ref(),
|
||||||
lint_level: cx.lint_level_of(local.id),
|
lint_level: cx.lint_level_of(local.id),
|
||||||
},
|
},
|
||||||
|
|
|
@ -93,10 +93,13 @@ pub enum StmtKind<'tcx> {
|
||||||
/// lifetime of temporaries
|
/// lifetime of temporaries
|
||||||
init_scope: region::Scope,
|
init_scope: region::Scope,
|
||||||
|
|
||||||
/// let <PAT> = ...
|
/// let <PAT>: ty = ...
|
||||||
pattern: Pattern<'tcx>,
|
pattern: Pattern<'tcx>,
|
||||||
|
|
||||||
/// let pat = <INIT> ...
|
/// let pat: <TY> = init ...
|
||||||
|
ty: Option<Ty<'tcx>>,
|
||||||
|
|
||||||
|
/// let pat: ty = <INIT> ...
|
||||||
initializer: Option<ExprRef<'tcx>>,
|
initializer: Option<ExprRef<'tcx>>,
|
||||||
|
|
||||||
/// the lint level for this let-statement
|
/// the lint level for this let-statement
|
||||||
|
|
|
@ -89,6 +89,8 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
|
||||||
M::end_region(self, Some(ce))?;
|
M::end_region(self, Some(ce))?;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
UserAssertTy(..) => {}
|
||||||
|
|
||||||
// Defined to do nothing. These are added by optimization passes, to avoid changing the
|
// Defined to do nothing. These are added by optimization passes, to avoid changing the
|
||||||
// size of MIR constantly.
|
// size of MIR constantly.
|
||||||
Nop => {}
|
Nop => {}
|
||||||
|
|
|
@ -105,6 +105,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
||||||
StatementKind::StorageDead(..) |
|
StatementKind::StorageDead(..) |
|
||||||
StatementKind::EndRegion(..) |
|
StatementKind::EndRegion(..) |
|
||||||
StatementKind::Validate(..) |
|
StatementKind::Validate(..) |
|
||||||
|
StatementKind::UserAssertTy(..) |
|
||||||
StatementKind::Nop => {
|
StatementKind::Nop => {
|
||||||
// safe (at least as emitted during MIR construction)
|
// safe (at least as emitted during MIR construction)
|
||||||
}
|
}
|
||||||
|
|
|
@ -234,6 +234,8 @@ fn optimized_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx
|
||||||
simplify_branches::SimplifyBranches::new("initial"),
|
simplify_branches::SimplifyBranches::new("initial"),
|
||||||
remove_noop_landing_pads::RemoveNoopLandingPads,
|
remove_noop_landing_pads::RemoveNoopLandingPads,
|
||||||
simplify::SimplifyCfg::new("early-opt"),
|
simplify::SimplifyCfg::new("early-opt"),
|
||||||
|
// Remove all `UserAssertTy` statements.
|
||||||
|
cleanup_post_borrowck::CleanUserAssertTy,
|
||||||
|
|
||||||
// These next passes must be executed together
|
// These next passes must be executed together
|
||||||
add_call_guards::CriticalCallEdges,
|
add_call_guards::CriticalCallEdges,
|
||||||
|
|
|
@ -1099,6 +1099,7 @@ This does not pose a problem by itself because they can't be accessed directly."
|
||||||
StatementKind::InlineAsm {..} |
|
StatementKind::InlineAsm {..} |
|
||||||
StatementKind::EndRegion(_) |
|
StatementKind::EndRegion(_) |
|
||||||
StatementKind::Validate(..) |
|
StatementKind::Validate(..) |
|
||||||
|
StatementKind::UserAssertTy(..) |
|
||||||
StatementKind::Nop => {}
|
StatementKind::Nop => {}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -50,6 +50,7 @@ impl RemoveNoopLandingPads {
|
||||||
StatementKind::StorageLive(_) |
|
StatementKind::StorageLive(_) |
|
||||||
StatementKind::StorageDead(_) |
|
StatementKind::StorageDead(_) |
|
||||||
StatementKind::EndRegion(_) |
|
StatementKind::EndRegion(_) |
|
||||||
|
StatementKind::UserAssertTy(..) |
|
||||||
StatementKind::Nop => {
|
StatementKind::Nop => {
|
||||||
// These are all nops in a landing pad (there's some
|
// These are all nops in a landing pad (there's some
|
||||||
// borrowck interaction between EndRegion and storage
|
// borrowck interaction between EndRegion and storage
|
||||||
|
|
|
@ -163,6 +163,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
|
||||||
mir::StatementKind::InlineAsm { .. } |
|
mir::StatementKind::InlineAsm { .. } |
|
||||||
mir::StatementKind::EndRegion(_) |
|
mir::StatementKind::EndRegion(_) |
|
||||||
mir::StatementKind::Validate(..) |
|
mir::StatementKind::Validate(..) |
|
||||||
|
mir::StatementKind::UserAssertTy(..) |
|
||||||
mir::StatementKind::Nop => continue,
|
mir::StatementKind::Nop => continue,
|
||||||
mir::StatementKind::SetDiscriminant{ .. } =>
|
mir::StatementKind::SetDiscriminant{ .. } =>
|
||||||
span_bug!(stmt.source_info.span,
|
span_bug!(stmt.source_info.span,
|
||||||
|
|
|
@ -90,6 +90,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> {
|
||||||
StatementKind::StorageLive(..) => "StatementKind::StorageLive",
|
StatementKind::StorageLive(..) => "StatementKind::StorageLive",
|
||||||
StatementKind::StorageDead(..) => "StatementKind::StorageDead",
|
StatementKind::StorageDead(..) => "StatementKind::StorageDead",
|
||||||
StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm",
|
StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm",
|
||||||
|
StatementKind::UserAssertTy(..) => "StatementKind::UserAssertTy",
|
||||||
StatementKind::Nop => "StatementKind::Nop",
|
StatementKind::Nop => "StatementKind::Nop",
|
||||||
}, &statement.kind);
|
}, &statement.kind);
|
||||||
self.super_statement(block, statement, location);
|
self.super_statement(block, statement, location);
|
||||||
|
|
|
@ -84,6 +84,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
mir::StatementKind::EndRegion(_) |
|
mir::StatementKind::EndRegion(_) |
|
||||||
mir::StatementKind::Validate(..) |
|
mir::StatementKind::Validate(..) |
|
||||||
|
mir::StatementKind::UserAssertTy(..) |
|
||||||
mir::StatementKind::Nop => bx,
|
mir::StatementKind::Nop => bx,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue