mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-04 19:29:07 +00:00
Added UserAssertTy statement.
This commit is contained in:
parent
c0fdb29362
commit
17b285d203
@ -277,6 +277,10 @@ for mir::StatementKind<'gcx> {
|
||||
op.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::InlineAsm { ref asm, ref outputs, ref inputs } => {
|
||||
asm.hash_stable(hcx, hasher);
|
||||
|
@ -1253,6 +1253,15 @@ pub enum StatementKind<'tcx> {
|
||||
/// (The starting point(s) arise implicitly from borrows.)
|
||||
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.
|
||||
Nop,
|
||||
}
|
||||
@ -1324,6 +1333,7 @@ impl<'tcx> Debug for Statement<'tcx> {
|
||||
InlineAsm { ref asm, ref outputs, ref inputs } => {
|
||||
write!(fmt, "asm!({:?} : {:?} : {:?})", asm, outputs, inputs)
|
||||
},
|
||||
UserAssertTy(ref ty, ref local) => write!(fmt, "UserAssertTy({:?}, {:?})", ty, local),
|
||||
Nop => write!(fmt, "nop"),
|
||||
}
|
||||
}
|
||||
@ -2184,6 +2194,7 @@ EnumTypeFoldableImpl! {
|
||||
(StatementKind::InlineAsm) { asm, outputs, inputs },
|
||||
(StatementKind::Validate)(a, b),
|
||||
(StatementKind::EndRegion)(a),
|
||||
(StatementKind::UserAssertTy)(a, b),
|
||||
(StatementKind::Nop),
|
||||
}
|
||||
}
|
||||
|
@ -144,6 +144,13 @@ macro_rules! make_mir_visitor {
|
||||
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,
|
||||
place: & $($mutability)* Place<'tcx>,
|
||||
context: PlaceContext<'tcx>,
|
||||
@ -376,6 +383,10 @@ macro_rules! make_mir_visitor {
|
||||
self.visit_operand(input, location);
|
||||
}
|
||||
}
|
||||
StatementKind::UserAssertTy(ref $($mutability)* ty,
|
||||
ref $($mutability)* local) => {
|
||||
self.visit_user_assert_ty(ty, local, location);
|
||||
}
|
||||
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,
|
||||
place: & $($mutability)* Place<'tcx>,
|
||||
context: PlaceContext<'tcx>,
|
||||
|
@ -392,11 +392,13 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx
|
||||
// ignored when consuming results (update to
|
||||
// flow_state already handled).
|
||||
}
|
||||
StatementKind::Nop | StatementKind::Validate(..) | StatementKind::StorageLive(..) => {
|
||||
// `Nop`, `Validate`, and `StorageLive` are irrelevant
|
||||
StatementKind::Nop |
|
||||
StatementKind::UserAssertTy(..) |
|
||||
StatementKind::Validate(..) |
|
||||
StatementKind::StorageLive(..) => {
|
||||
// `Nop`, `UserAssertTy`, `Validate`, and `StorageLive` are irrelevant
|
||||
// to borrow check.
|
||||
}
|
||||
|
||||
StatementKind::StorageDead(local) => {
|
||||
self.access_place(
|
||||
ContextKind::StorageDead.new(location),
|
||||
|
@ -766,6 +766,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
|
||||
| StatementKind::InlineAsm { .. }
|
||||
| StatementKind::EndRegion(_)
|
||||
| StatementKind::Validate(..)
|
||||
| StatementKind::UserAssertTy(..)
|
||||
| StatementKind::Nop => {}
|
||||
}
|
||||
}
|
||||
|
@ -102,6 +102,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
remainder_scope,
|
||||
init_scope,
|
||||
pattern,
|
||||
ty,
|
||||
initializer,
|
||||
lint_level
|
||||
} => {
|
||||
@ -120,12 +121,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
opt_destruction_scope.map(|de|(de, source_info)), block, |this| {
|
||||
let scope = (init_scope, source_info);
|
||||
this.in_scope(scope, lint_level, block, |this| {
|
||||
this.expr_into_pattern(block, pattern, init)
|
||||
this.expr_into_pattern(block, ty, pattern, init)
|
||||
})
|
||||
}));
|
||||
} else {
|
||||
this.visit_bindings(&pattern, &mut |this, _, _, 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);
|
||||
})
|
||||
}
|
||||
|
@ -145,8 +145,18 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
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,
|
||||
mut block: BasicBlock,
|
||||
ty: Option<Ty<'tcx>>,
|
||||
irrefutable_pat: Pattern<'tcx>,
|
||||
initializer: ExprRef<'tcx>)
|
||||
-> BlockAnd<()> {
|
||||
@ -156,6 +166,11 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
|
||||
var,
|
||||
subpattern: None, .. } => {
|
||||
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));
|
||||
self.schedule_drop_for_binding(var, irrefutable_pat.span);
|
||||
block.unit()
|
||||
|
@ -678,6 +678,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> {
|
||||
mir::StatementKind::SetDiscriminant { .. } |
|
||||
mir::StatementKind::StorageLive(..) |
|
||||
mir::StatementKind::Validate(..) |
|
||||
mir::StatementKind::UserAssertTy(..) |
|
||||
mir::StatementKind::Nop => {}
|
||||
|
||||
}
|
||||
|
@ -298,6 +298,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
|
||||
}
|
||||
StatementKind::EndRegion(_) |
|
||||
StatementKind::Validate(..) |
|
||||
StatementKind::UserAssertTy(..) |
|
||||
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),
|
||||
});
|
||||
|
||||
let ty = local.ty.clone().map(|ty| cx.tables().node_id_to_type(ty.hir_id));
|
||||
let pattern = cx.pattern_from_hir(&local.pat);
|
||||
result.push(StmtRef::Mirror(Box::new(Stmt {
|
||||
kind: StmtKind::Let {
|
||||
remainder_scope: remainder_scope,
|
||||
init_scope: region::Scope::Node(hir_id.local_id),
|
||||
pattern,
|
||||
ty,
|
||||
initializer: local.init.to_ref(),
|
||||
lint_level: cx.lint_level_of(local.id),
|
||||
},
|
||||
|
@ -93,10 +93,13 @@ pub enum StmtKind<'tcx> {
|
||||
/// lifetime of temporaries
|
||||
init_scope: region::Scope,
|
||||
|
||||
/// let <PAT> = ...
|
||||
/// let <PAT>: ty = ...
|
||||
pattern: Pattern<'tcx>,
|
||||
|
||||
/// let pat = <INIT> ...
|
||||
/// let pat: <TY> = init ...
|
||||
ty: Option<Ty<'tcx>>,
|
||||
|
||||
/// let pat: ty = <INIT> ...
|
||||
initializer: Option<ExprRef<'tcx>>,
|
||||
|
||||
/// 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))?;
|
||||
}
|
||||
|
||||
UserAssertTy(..) => {}
|
||||
|
||||
// Defined to do nothing. These are added by optimization passes, to avoid changing the
|
||||
// size of MIR constantly.
|
||||
Nop => {}
|
||||
|
@ -105,6 +105,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
|
||||
StatementKind::StorageDead(..) |
|
||||
StatementKind::EndRegion(..) |
|
||||
StatementKind::Validate(..) |
|
||||
StatementKind::UserAssertTy(..) |
|
||||
StatementKind::Nop => {
|
||||
// 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"),
|
||||
remove_noop_landing_pads::RemoveNoopLandingPads,
|
||||
simplify::SimplifyCfg::new("early-opt"),
|
||||
// Remove all `UserAssertTy` statements.
|
||||
cleanup_post_borrowck::CleanUserAssertTy,
|
||||
|
||||
// These next passes must be executed together
|
||||
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::EndRegion(_) |
|
||||
StatementKind::Validate(..) |
|
||||
StatementKind::UserAssertTy(..) |
|
||||
StatementKind::Nop => {}
|
||||
}
|
||||
});
|
||||
|
@ -50,6 +50,7 @@ impl RemoveNoopLandingPads {
|
||||
StatementKind::StorageLive(_) |
|
||||
StatementKind::StorageDead(_) |
|
||||
StatementKind::EndRegion(_) |
|
||||
StatementKind::UserAssertTy(..) |
|
||||
StatementKind::Nop => {
|
||||
// These are all nops in a landing pad (there's some
|
||||
// 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::EndRegion(_) |
|
||||
mir::StatementKind::Validate(..) |
|
||||
mir::StatementKind::UserAssertTy(..) |
|
||||
mir::StatementKind::Nop => continue,
|
||||
mir::StatementKind::SetDiscriminant{ .. } =>
|
||||
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::StorageDead(..) => "StatementKind::StorageDead",
|
||||
StatementKind::InlineAsm { .. } => "StatementKind::InlineAsm",
|
||||
StatementKind::UserAssertTy(..) => "StatementKind::UserAssertTy",
|
||||
StatementKind::Nop => "StatementKind::Nop",
|
||||
}, &statement.kind);
|
||||
self.super_statement(block, statement, location);
|
||||
|
@ -84,6 +84,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
|
||||
}
|
||||
mir::StatementKind::EndRegion(_) |
|
||||
mir::StatementKind::Validate(..) |
|
||||
mir::StatementKind::UserAssertTy(..) |
|
||||
mir::StatementKind::Nop => bx,
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user