From 24abe6f363cd47d444e4cff1123da93817b980f8 Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Fri, 4 May 2018 12:04:33 +0200 Subject: [PATCH] rust-lang/rust#27282: Add `StatementKind::ReadForMatch` to MIR. (This is just the data structure changes and some boilerplate match code that followed from it; the actual emission of these statements comes in a follow-up commit.) --- src/librustc/ich/impls_mir.rs | 3 +++ src/librustc/mir/mod.rs | 6 ++++++ src/librustc/mir/visit.rs | 5 +++++ src/librustc_codegen_llvm/mir/statement.rs | 1 + src/librustc_mir/borrow_check/mod.rs | 9 +++++++++ src/librustc_mir/borrow_check/nll/invalidation.rs | 8 ++++++++ src/librustc_mir/borrow_check/nll/type_check/mod.rs | 3 ++- src/librustc_mir/dataflow/impls/borrows.rs | 1 + src/librustc_mir/dataflow/move_paths/builder.rs | 3 +++ src/librustc_mir/interpret/step.rs | 5 +++++ src/librustc_mir/transform/check_unsafety.rs | 1 + src/librustc_mir/transform/qualify_consts.rs | 1 + src/librustc_mir/transform/remove_noop_landing_pads.rs | 1 + src/librustc_mir/transform/rustc_peek.rs | 1 + src/librustc_passes/mir_stats.rs | 1 + 15 files changed, 48 insertions(+), 1 deletion(-) diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index c71b10ce142c5..e77d38de58264 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -241,6 +241,9 @@ for mir::StatementKind<'gcx> { place.hash_stable(hcx, hasher); rvalue.hash_stable(hcx, hasher); } + mir::StatementKind::ReadForMatch(ref place) => { + place.hash_stable(hcx, hasher); + } mir::StatementKind::SetDiscriminant { ref place, variant_index } => { place.hash_stable(hcx, hasher); variant_index.hash_stable(hcx, hasher); diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index d35884ec78a82..a94e5e793b470 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1225,6 +1225,10 @@ pub enum StatementKind<'tcx> { /// Write the RHS Rvalue to the LHS Place. Assign(Place<'tcx>, Rvalue<'tcx>), + /// This represents all the reading that a pattern match may do + /// (e.g. inspecting constants and discriminant values). + ReadForMatch(Place<'tcx>), + /// Write the discriminant for a variant to the enum Place. SetDiscriminant { place: Place<'tcx>, variant_index: usize }, @@ -1327,6 +1331,7 @@ impl<'tcx> Debug for Statement<'tcx> { use self::StatementKind::*; match self.kind { Assign(ref place, ref rv) => write!(fmt, "{:?} = {:?}", place, rv), + ReadForMatch(ref place) => write!(fmt, "ReadForMatch({:?})", place), // (reuse lifetime rendering policy from ppaux.) EndRegion(ref ce) => write!(fmt, "EndRegion({})", ty::ReScope(*ce)), Validate(ref op, ref places) => write!(fmt, "Validate({:?}, {:?})", op, places), @@ -2212,6 +2217,7 @@ BraceStructTypeFoldableImpl! { EnumTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for StatementKind<'tcx> { (StatementKind::Assign)(a, b), + (StatementKind::ReadForMatch)(place), (StatementKind::SetDiscriminant) { place, variant_index }, (StatementKind::StorageLive)(a), (StatementKind::StorageDead)(a), diff --git a/src/librustc/mir/visit.rs b/src/librustc/mir/visit.rs index b647ba553dd6c..9dd1432167a90 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -355,6 +355,11 @@ macro_rules! make_mir_visitor { ref $($mutability)* rvalue) => { self.visit_assign(block, place, rvalue, location); } + StatementKind::ReadForMatch(ref $($mutability)* place) => { + self.visit_place(place, + PlaceContext::Inspect, + location); + } StatementKind::EndRegion(_) => {} StatementKind::Validate(_, ref $($mutability)* places) => { for operand in places { diff --git a/src/librustc_codegen_llvm/mir/statement.rs b/src/librustc_codegen_llvm/mir/statement.rs index 578481df157e8..c0cce297ef6a9 100644 --- a/src/librustc_codegen_llvm/mir/statement.rs +++ b/src/librustc_codegen_llvm/mir/statement.rs @@ -82,6 +82,7 @@ impl<'a, 'tcx> FunctionCx<'a, 'tcx> { asm::codegen_inline_asm(&bx, asm, outputs, input_vals); bx } + mir::StatementKind::ReadForMatch(_) | mir::StatementKind::EndRegion(_) | mir::StatementKind::Validate(..) | mir::StatementKind::UserAssertTy(..) | diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 9bfba219ccd71..233974435f3f8 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -423,6 +423,14 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx flow_state, ); } + StatementKind::ReadForMatch(ref place) => { + self.access_place(ContextKind::ReadForMatch.new(location), + (place, span), + (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))), + LocalMutationIsAllowed::No, + flow_state, + ); + } StatementKind::SetDiscriminant { ref place, variant_index: _, @@ -2090,6 +2098,7 @@ enum ContextKind { CallDest, Assert, Yield, + ReadForMatch, StorageDead, } diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 50aa1550fb768..46026cdc94121 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -93,6 +93,14 @@ impl<'cg, 'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cg, 'cx, 'tc JustWrite ); } + StatementKind::ReadForMatch(ref place) => { + self.access_place( + ContextKind::ReadForMatch.new(location), + place, + (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))), + LocalMutationIsAllowed::No, + ); + } StatementKind::SetDiscriminant { ref place, variant_index: _, diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 456aa1aa66f11..04f5024b76946 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -836,7 +836,8 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); } } - StatementKind::StorageLive(_) + StatementKind::ReadForMatch(_) + | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::InlineAsm { .. } | StatementKind::EndRegion(_) diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 04c62854c5cbd..78886baf51476 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -227,6 +227,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { } } + mir::StatementKind::ReadForMatch(..) | mir::StatementKind::SetDiscriminant { .. } | mir::StatementKind::StorageLive(..) | mir::StatementKind::Validate(..) | diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs index cbf4c822769c6..2ff22842141d9 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -278,6 +278,9 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { } self.gather_rvalue(rval); } + StatementKind::ReadForMatch(ref place) => { + self.create_move_path(place); + } StatementKind::InlineAsm { ref outputs, ref inputs, ref asm } => { for (output, kind) in outputs.iter().zip(&asm.outputs) { if !kind.is_indirect { diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 554d87a04e2f8..b9edd2c07f381 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -79,6 +79,11 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { self.deallocate_local(old_val)?; } + // FIXME: is there some dynamic semantics we should attach to + // these? Or am I correct in thinking that the inerpreter + // is solely intended for borrowck'ed code? + ReadForMatch(..) => {} + // Validity checks. Validate(op, ref places) => { for operand in places { diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index fc3764e4f49a5..4081f827d4b3d 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -100,6 +100,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.source_info = statement.source_info; match statement.kind { StatementKind::Assign(..) | + StatementKind::ReadForMatch(..) | StatementKind::SetDiscriminant { .. } | StatementKind::StorageLive(..) | StatementKind::StorageDead(..) | diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs index c249dc312f2f7..719630129440a 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1135,6 +1135,7 @@ This does not pose a problem by itself because they can't be accessed directly." StatementKind::Assign(ref place, ref rvalue) => { this.visit_assign(bb, place, rvalue, location); } + StatementKind::ReadForMatch(..) | StatementKind::SetDiscriminant { .. } | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index bcc8fef18f013..680b60b972841 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -47,6 +47,7 @@ impl RemoveNoopLandingPads { { for stmt in &mir[bb].statements { match stmt.kind { + StatementKind::ReadForMatch(_) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::EndRegion(_) | diff --git a/src/librustc_mir/transform/rustc_peek.rs b/src/librustc_mir/transform/rustc_peek.rs index 8f67b9e7c3d9d..b23f056801210 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -158,6 +158,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir::StatementKind::Assign(ref place, ref rvalue) => { (place, rvalue) } + mir::StatementKind::ReadForMatch(_) | mir::StatementKind::StorageLive(_) | mir::StatementKind::StorageDead(_) | mir::StatementKind::InlineAsm { .. } | diff --git a/src/librustc_passes/mir_stats.rs b/src/librustc_passes/mir_stats.rs index 45c6e89321d04..f7c8f8f43f178 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -85,6 +85,7 @@ impl<'a, 'tcx> mir_visit::Visitor<'tcx> for StatCollector<'a, 'tcx> { self.record("Statement", statement); self.record(match statement.kind { StatementKind::Assign(..) => "StatementKind::Assign", + StatementKind::ReadForMatch(..) => "StatementKind::ReadForMatch", StatementKind::EndRegion(..) => "StatementKind::EndRegion", StatementKind::Validate(..) => "StatementKind::Validate", StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant",