Skip to content

Commit

Permalink
Added UserAssertTy statement.
Browse files Browse the repository at this point in the history
  • Loading branch information
davidtwco committed Mar 22, 2018
1 parent c0fdb29 commit 17b285d
Show file tree
Hide file tree
Showing 19 changed files with 79 additions and 6 deletions.
4 changes: 4 additions & 0 deletions src/librustc/ich/impls_mir.rs
Expand Up @@ -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);
Expand Down
11 changes: 11 additions & 0 deletions src/librustc/mir/mod.rs
Expand Up @@ -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,
}
Expand Down Expand Up @@ -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"),
}
}
Expand Down Expand Up @@ -2184,6 +2194,7 @@ EnumTypeFoldableImpl! {
(StatementKind::InlineAsm) { asm, outputs, inputs },
(StatementKind::Validate)(a, b),
(StatementKind::EndRegion)(a),
(StatementKind::UserAssertTy)(a, b),
(StatementKind::Nop),
}
}
Expand Down
19 changes: 19 additions & 0 deletions src/librustc/mir/visit.rs
Expand Up @@ -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>,
Expand Down Expand Up @@ -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 => {}
}
}
Expand Down Expand Up @@ -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>,
Expand Down
8 changes: 5 additions & 3 deletions src/librustc_mir/borrow_check/mod.rs
Expand Up @@ -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),
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/borrow_check/nll/type_check/mod.rs
Expand Up @@ -766,6 +766,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
| StatementKind::InlineAsm { .. }
| StatementKind::EndRegion(_)
| StatementKind::Validate(..)
| StatementKind::UserAssertTy(..)
| StatementKind::Nop => {}
}
}
Expand Down
6 changes: 5 additions & 1 deletion src/librustc_mir/build/block.rs
Expand Up @@ -102,6 +102,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
remainder_scope,
init_scope,
pattern,
ty,
initializer,
lint_level
} => {
Expand All @@ -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);
})
}
Expand Down
15 changes: 15 additions & 0 deletions src/librustc_mir/build/matches/mod.rs
Expand Up @@ -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<()> {
Expand All @@ -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()
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/dataflow/impls/borrows.rs
Expand Up @@ -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 => {}

}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/dataflow/move_paths/builder.rs
Expand Up @@ -298,6 +298,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
}
StatementKind::EndRegion(_) |
StatementKind::Validate(..) |
StatementKind::UserAssertTy(..) |
StatementKind::Nop => {}
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_mir/hair/cx/block.rs
Expand Up @@ -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),
},
Expand Down
7 changes: 5 additions & 2 deletions src/librustc_mir/hair/mod.rs
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_mir/interpret/step.rs
Expand Up @@ -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 => {}
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/transform/check_unsafety.rs
Expand Up @@ -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)
}
Expand Down
2 changes: 2 additions & 0 deletions src/librustc_mir/transform/mod.rs
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/transform/qualify_consts.rs
Expand Up @@ -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 => {}
}
});
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/transform/remove_noop_landing_pads.rs
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions src/librustc_mir/transform/rustc_peek.rs
Expand Up @@ -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,
Expand Down
1 change: 1 addition & 0 deletions src/librustc_passes/mir_stats.rs
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/librustc_trans/mir/statement.rs
Expand Up @@ -84,6 +84,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> {
}
mir::StatementKind::EndRegion(_) |
mir::StatementKind::Validate(..) |
mir::StatementKind::UserAssertTy(..) |
mir::StatementKind::Nop => bx,
}
}
Expand Down

0 comments on commit 17b285d

Please sign in to comment.