From 7216012878f32a343b82fc243c7b692b41104691 Mon Sep 17 00:00:00 2001 From: Remy Rakic Date: Wed, 12 Sep 2018 15:09:28 +0200 Subject: [PATCH 1/9] Inject fake read in binding pattern --- src/librustc_mir/build/matches/mod.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 49c4ed874bb..6a84658a7a9 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -264,6 +264,19 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let place = self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard); unpack!(block = self.into(&place, block, initializer)); + + // Inject a fake read of the newly created binding + // to test the fallout of fixing issue #53695 where NLL + // allows to create variables that are immediately unusable. + let source_info = self.source_info(irrefutable_pat.span); + self.cfg.push( + block, + Statement { + source_info, + kind: StatementKind::ReadForMatch(place.clone()), + }, + ); + self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } From c3c7a5bafe26d566242e000bb6136e3e9ee8d611 Mon Sep 17 00:00:00 2001 From: Remy Rakic Date: Thu, 13 Sep 2018 17:06:41 +0200 Subject: [PATCH 2/9] inject fake read in binding pattern with ascription --- src/librustc_mir/build/matches/mod.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 6a84658a7a9..91d439d430c 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -267,7 +267,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Inject a fake read of the newly created binding // to test the fallout of fixing issue #53695 where NLL - // allows to create variables that are immediately unusable. + // allows creating unused variables that are effectively unusable. let source_info = self.source_info(irrefutable_pat.span); self.cfg.push( block, @@ -318,6 +318,17 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }, ); + // Inject a fake read of the newly created binding + // to test the fallout of fixing issue #53695 where NLL + // allows creating unused variables that are effectively unusable. + self.cfg.push( + block, + Statement { + source_info, + kind: StatementKind::ReadForMatch(place.clone()), + }, + ); + self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } From 52b53629901f2f797bf0191afdaba380234f81ad Mon Sep 17 00:00:00 2001 From: Remy Rakic Date: Fri, 14 Sep 2018 18:07:17 +0200 Subject: [PATCH 3/9] Explain the fake read injection better --- src/librustc_mir/build/matches/mod.rs | 23 +++++++++++++++++------ 1 file changed, 17 insertions(+), 6 deletions(-) diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 91d439d430c..5c72679800c 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -265,9 +265,20 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { self.storage_live_binding(block, var, irrefutable_pat.span, OutsideGuard); unpack!(block = self.into(&place, block, initializer)); - // Inject a fake read of the newly created binding - // to test the fallout of fixing issue #53695 where NLL - // allows creating unused variables that are effectively unusable. + + // Officially, the semantics of + // + // `let pattern = ;` + // + // is that `` is evaluated into a temporary and then this temporary is + // into the pattern. + // + // However, if we see the simple pattern `let var = `, we optimize this to + // evaluate `` directly into the variable `var`. This is mostly unobservable, + // but in some cases it can affect the borrow checker, as in #53695. + // Therefore, we insert a "fake read" here to ensure that we get + // appropriate errors. + // let source_info = self.source_info(irrefutable_pat.span); self.cfg.push( block, @@ -318,9 +329,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }, ); - // Inject a fake read of the newly created binding - // to test the fallout of fixing issue #53695 where NLL - // allows creating unused variables that are effectively unusable. + // Similarly to the `let var = ` case, we insert a "fake read" here to + // ensure that we get appropriate errors when this usually unobservable + // optimization affects the borrow checker. self.cfg.push( block, Statement { From f5e310530a96ee1dc443e08c62e5a60e14234306 Mon Sep 17 00:00:00 2001 From: Remy Rakic Date: Fri, 14 Sep 2018 21:05:31 +0200 Subject: [PATCH 4/9] Refactor 'ReadForMatch' into 'FakeRead' and add the cause of the fake read --- src/librustc/ich/impls_mir.rs | 5 ++++- src/librustc/mir/mod.rs | 18 ++++++++++++++---- src/librustc/mir/visit.rs | 2 +- src/librustc/session/config.rs | 2 +- src/librustc/ty/context.rs | 2 +- src/librustc_codegen_llvm/mir/statement.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 6 +++--- .../borrow_check/nll/invalidation.rs | 4 ++-- .../borrow_check/nll/type_check/mod.rs | 2 +- src/librustc_mir/build/matches/mod.rs | 6 +++--- src/librustc_mir/dataflow/impls/borrows.rs | 2 +- .../dataflow/move_paths/builder.rs | 2 +- src/librustc_mir/interpret/step.rs | 4 ++-- src/librustc_mir/transform/check_unsafety.rs | 2 +- src/librustc_mir/transform/qualify_consts.rs | 2 +- .../transform/qualify_min_const_fn.rs | 2 +- .../transform/remove_noop_landing_pads.rs | 2 +- src/librustc_mir/transform/rustc_peek.rs | 2 +- src/librustc_passes/mir_stats.rs | 2 +- 19 files changed, 41 insertions(+), 28 deletions(-) diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index 5f35c9fea0a..313ef054829 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -238,7 +238,8 @@ for mir::StatementKind<'gcx> { place.hash_stable(hcx, hasher); rvalue.hash_stable(hcx, hasher); } - mir::StatementKind::ReadForMatch(ref place) => { + mir::StatementKind::FakeRead(ref cause, ref place) => { + cause.hash_stable(hcx, hasher); place.hash_stable(hcx, hasher); } mir::StatementKind::SetDiscriminant { ref place, variant_index } => { @@ -271,6 +272,8 @@ for mir::StatementKind<'gcx> { } } +impl_stable_hash_for!(enum mir::FakeReadCause { ForMatch, ForLet }); + impl<'a, 'gcx, T> HashStable> for mir::ValidationOperand<'gcx, T> where T: HashStable> diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 3450eec8082..8e9c1ad23c8 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1613,8 +1613,10 @@ pub enum StatementKind<'tcx> { 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>), + /// (e.g. inspecting constants and discriminant values), and the + /// kind of pattern it comes from. This is in order to adapt potential + /// error messages to these specific patterns. + FakeRead(FakeReadCause, Place<'tcx>), /// Write the discriminant for a variant to the enum Place. SetDiscriminant { @@ -1662,6 +1664,13 @@ pub enum StatementKind<'tcx> { Nop, } +/// The `FakeReadCause` describes the type of pattern why a `FakeRead` statement exists. +#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)] +pub enum FakeReadCause { + ForMatch, + ForLet, +} + /// The `ValidationOp` describes what happens with each of the operands of a /// `Validate` statement. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq)] @@ -1718,7 +1727,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), + FakeRead(ref cause, ref place) => write!(fmt, "FakeRead({:?}, {:?})", cause, 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), @@ -2585,6 +2594,7 @@ CloneTypeFoldableAndLiftImpls! { Mutability, SourceInfo, UpvarDecl, + FakeReadCause, ValidationOp, SourceScope, SourceScopeData, @@ -2651,7 +2661,7 @@ BraceStructTypeFoldableImpl! { EnumTypeFoldableImpl! { impl<'tcx> TypeFoldable<'tcx> for StatementKind<'tcx> { (StatementKind::Assign)(a, b), - (StatementKind::ReadForMatch)(place), + (StatementKind::FakeRead)(cause, 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 0beb5ac0a3c..91c83ecb2e2 100644 --- a/src/librustc/mir/visit.rs +++ b/src/librustc/mir/visit.rs @@ -354,7 +354,7 @@ macro_rules! make_mir_visitor { ref $($mutability)* rvalue) => { self.visit_assign(block, place, rvalue, location); } - StatementKind::ReadForMatch(ref $($mutability)* place) => { + StatementKind::FakeRead(_, ref $($mutability)* place) => { self.visit_place(place, PlaceContext::Inspect, location); diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index e4d633c3f2c..1fdbf687be8 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1330,7 +1330,7 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, disable_nll_user_type_assert: bool = (false, parse_bool, [UNTRACKED], "disable user provided type assertion in NLL"), nll_dont_emit_read_for_match: bool = (false, parse_bool, [UNTRACKED], - "in match codegen, do not include ReadForMatch statements (used by mir-borrowck)"), + "in match codegen, do not include FakeRead statements (used by mir-borrowck)"), dont_buffer_diagnostics: bool = (false, parse_bool, [UNTRACKED], "emit diagnostics rather than buffering (breaks NLL error downgrading, sorting)."), polonius: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 03c0b680acf..aaa0b9fe513 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1478,7 +1478,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.emit_read_for_match() } - /// If true, make MIR codegen for `match` emit ReadForMatch + /// If true, make MIR codegen for `match` emit FakeRead /// statements (which simulate the maximal effect of executing the /// patterns in a match arm). pub fn emit_read_for_match(&self) -> bool { diff --git a/src/librustc_codegen_llvm/mir/statement.rs b/src/librustc_codegen_llvm/mir/statement.rs index 0cb8f99efc3..b4eb7615f98 100644 --- a/src/librustc_codegen_llvm/mir/statement.rs +++ b/src/librustc_codegen_llvm/mir/statement.rs @@ -89,7 +89,7 @@ impl FunctionCx<'a, 'll, 'tcx> { asm::codegen_inline_asm(&bx, asm, outputs, input_vals); bx } - mir::StatementKind::ReadForMatch(_) | + mir::StatementKind::FakeRead(..) | mir::StatementKind::EndRegion(_) | mir::StatementKind::Validate(..) | mir::StatementKind::AscribeUserType(..) | diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 521e7ade00e..478a2326be3 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -478,9 +478,9 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx flow_state, ); } - StatementKind::ReadForMatch(ref place) => { + StatementKind::FakeRead(_, ref place) => { self.access_place( - ContextKind::ReadForMatch.new(location), + ContextKind::FakeRead.new(location), (place, span), (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))), LocalMutationIsAllowed::No, @@ -2206,7 +2206,7 @@ enum ContextKind { CallDest, Assert, Yield, - ReadForMatch, + FakeRead, StorageDead, } diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 71345f22e44..0b7fededa97 100644 --- a/src/librustc_mir/borrow_check/nll/invalidation.rs +++ b/src/librustc_mir/borrow_check/nll/invalidation.rs @@ -93,9 +93,9 @@ impl<'cg, 'cx, 'tcx, 'gcx> Visitor<'tcx> for InvalidationGenerator<'cg, 'cx, 'tc JustWrite ); } - StatementKind::ReadForMatch(ref place) => { + StatementKind::FakeRead(_, ref place) => { self.access_place( - ContextKind::ReadForMatch.new(location), + ContextKind::FakeRead.new(location), place, (Deep, Read(ReadKind::Borrow(BorrowKind::Shared))), LocalMutationIsAllowed::No, 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 de96539ec30..1f12e9c747f 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -995,7 +995,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); } } - StatementKind::ReadForMatch(_) + StatementKind::FakeRead(..) | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::InlineAsm { .. } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 5c72679800c..49c1308329f 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -157,7 +157,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { *pre_binding_block, Statement { source_info: pattern_source_info, - kind: StatementKind::ReadForMatch(borrow_temp.clone()), + kind: StatementKind::FakeRead(FakeReadCause::ForMatch, borrow_temp.clone()), }, ); } @@ -284,7 +284,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block, Statement { source_info, - kind: StatementKind::ReadForMatch(place.clone()), + kind: StatementKind::FakeRead(FakeReadCause::ForLet, place.clone()), }, ); @@ -336,7 +336,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { block, Statement { source_info, - kind: StatementKind::ReadForMatch(place.clone()), + kind: StatementKind::FakeRead(FakeReadCause::ForLet, place.clone()), }, ); diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 010ffafc4bd..ed2f780baf1 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -336,7 +336,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { } } - mir::StatementKind::ReadForMatch(..) | + mir::StatementKind::FakeRead(..) | 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 5451d27082d..63adcb5132a 100644 --- a/src/librustc_mir/dataflow/move_paths/builder.rs +++ b/src/librustc_mir/dataflow/move_paths/builder.rs @@ -281,7 +281,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> { } self.gather_rvalue(rval); } - StatementKind::ReadForMatch(ref place) => { + StatementKind::FakeRead(_, ref place) => { self.create_move_path(place); } StatementKind::InlineAsm { ref outputs, ref inputs, ref asm } => { diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs index 5bdaf6ba729..5db7e0b5eb5 100644 --- a/src/librustc_mir/interpret/step.rs +++ b/src/librustc_mir/interpret/step.rs @@ -150,9 +150,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> { self.deallocate_local(old_val)?; } - // No dynamic semantics attached to `ReadForMatch`; MIR + // No dynamic semantics attached to `FakeRead`; MIR // interpreter is solely intended for borrowck'ed code. - ReadForMatch(..) => {} + FakeRead(..) => {} // Validity checks. Validate(op, ref places) => { diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs index 6fbc2f85c08..286de52bec5 100644 --- a/src/librustc_mir/transform/check_unsafety.rs +++ b/src/librustc_mir/transform/check_unsafety.rs @@ -108,7 +108,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> { self.source_info = statement.source_info; match statement.kind { StatementKind::Assign(..) | - StatementKind::ReadForMatch(..) | + StatementKind::FakeRead(..) | 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 bc9cc7274d5..a997bd37c50 100644 --- a/src/librustc_mir/transform/qualify_consts.rs +++ b/src/librustc_mir/transform/qualify_consts.rs @@ -1090,7 +1090,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> { StatementKind::Assign(ref place, ref rvalue) => { this.visit_assign(bb, place, rvalue, location); } - StatementKind::ReadForMatch(..) | + StatementKind::FakeRead(..) | StatementKind::SetDiscriminant { .. } | StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | diff --git a/src/librustc_mir/transform/qualify_min_const_fn.rs b/src/librustc_mir/transform/qualify_min_const_fn.rs index f7e44dde186..541b3c0607d 100644 --- a/src/librustc_mir/transform/qualify_min_const_fn.rs +++ b/src/librustc_mir/transform/qualify_min_const_fn.rs @@ -216,7 +216,7 @@ fn check_statement( check_rvalue(tcx, mir, rval, span) } - StatementKind::ReadForMatch(_) => Err((span, "match in const fn is unstable".into())), + StatementKind::FakeRead(..) => Err((span, "match in const fn is unstable".into())), // just an assignment StatementKind::SetDiscriminant { .. } => Ok(()), diff --git a/src/librustc_mir/transform/remove_noop_landing_pads.rs b/src/librustc_mir/transform/remove_noop_landing_pads.rs index 9cdd94a7be7..298e38228d3 100644 --- a/src/librustc_mir/transform/remove_noop_landing_pads.rs +++ b/src/librustc_mir/transform/remove_noop_landing_pads.rs @@ -49,7 +49,7 @@ impl RemoveNoopLandingPads { ) -> bool { for stmt in &mir[bb].statements { match stmt.kind { - StatementKind::ReadForMatch(_) | + StatementKind::FakeRead(..) | 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 3c898eedebc..487a18f6620 100644 --- a/src/librustc_mir/transform/rustc_peek.rs +++ b/src/librustc_mir/transform/rustc_peek.rs @@ -157,7 +157,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::FakeRead(..) | 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 0120b5bc532..0b9b20d3c45 100644 --- a/src/librustc_passes/mir_stats.rs +++ b/src/librustc_passes/mir_stats.rs @@ -82,7 +82,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::FakeRead(..) => "StatementKind::FakeRead", StatementKind::EndRegion(..) => "StatementKind::EndRegion", StatementKind::Validate(..) => "StatementKind::Validate", StatementKind::SetDiscriminant { .. } => "StatementKind::SetDiscriminant", From ab236dfc86269e3f862c4a1ba6411ae34ee2fb64 Mon Sep 17 00:00:00 2001 From: Remy Rakic Date: Thu, 13 Sep 2018 17:07:34 +0200 Subject: [PATCH 5/9] Update NLL 3-point error message for fake reads in optimized let patterns --- .../borrow_check/nll/explain_borrow/mod.rs | 28 +++++++++++++++++-- src/test/ui/generator/borrowing.nll.stderr | 5 ++-- .../regions/regions-steal-closure.nll.stderr | 5 ++-- src/test/ui/span/range-2.nll.stderr | 12 ++++---- ...d-is-not-static-ensures-scoping.nll.stderr | 12 ++++---- .../send-is-not-static-std-sync-2.nll.stderr | 12 ++++---- .../wf-method-late-bound-regions.nll.stderr | 6 ++-- .../unboxed-closure-region.nll.stderr | 5 ++-- 8 files changed, 56 insertions(+), 29 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index 414cb1d6f05..a62e608a875 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -11,7 +11,7 @@ use borrow_check::borrow_set::BorrowData; use borrow_check::nll::region_infer::Cause; use borrow_check::{Context, MirBorrowckCtxt, WriteKind}; -use rustc::mir::{Local, Location, Place, TerminatorKind}; +use rustc::mir::{FakeReadCause, Local, Location, Place, StatementKind, TerminatorKind}; use rustc_errors::DiagnosticBuilder; use rustc::ty::Region; @@ -142,7 +142,31 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { if spans.for_closure() { "borrow later captured here by closure" } else { - "borrow later used here" + // Check if the location represents a `FakeRead`, and adapt the error + // message to the `FakeReadCause` it is from: in particular, + // the ones inserted in optimized `let var = ` patterns. + let is_fake_read_for_let = match self.mir.basic_blocks()[location.block] + .statements + .get(location.statement_index) + { + None => false, + Some(stmt) => { + if let StatementKind::FakeRead(ref cause, _) = stmt.kind { + match cause { + FakeReadCause::ForLet => true, + _ => false, + } + } else { + false + } + } + }; + + if is_fake_read_for_let { + "borrow later stored here" + } else { + "borrow later used here" + } } }; err.span_label(spans.var_or_use(), message); diff --git a/src/test/ui/generator/borrowing.nll.stderr b/src/test/ui/generator/borrowing.nll.stderr index e03d72a02f0..2488df7772b 100644 --- a/src/test/ui/generator/borrowing.nll.stderr +++ b/src/test/ui/generator/borrowing.nll.stderr @@ -10,6 +10,9 @@ LL | }; error[E0597]: `a` does not live long enough --> $DIR/borrowing.rs:24:9 | +LL | let _b = { + | -- borrow later stored here +LL | let a = 3; LL | / || { LL | | yield &a LL | | //~^ ERROR: `a` does not live long enough @@ -17,8 +20,6 @@ LL | | } | |_________^ borrowed value does not live long enough LL | }; | - `a` dropped here while still borrowed -LL | } - | - borrow later used here, when `_b` is dropped error: aborting due to 2 previous errors diff --git a/src/test/ui/regions/regions-steal-closure.nll.stderr b/src/test/ui/regions/regions-steal-closure.nll.stderr index ed70e38362d..538903c5918 100644 --- a/src/test/ui/regions/regions-steal-closure.nll.stderr +++ b/src/test/ui/regions/regions-steal-closure.nll.stderr @@ -1,14 +1,15 @@ error[E0597]: `i` does not live long enough --> $DIR/regions-steal-closure.rs:24:28 | +LL | let mut cl_box = { + | ---------- borrow later stored here +LL | let mut i = 3; LL | box_it(Box::new(|| i += 1)) //~ ERROR `i` does not live long enough | -- ^ borrowed value does not live long enough | | | value captured here LL | }; | - `i` dropped here while still borrowed -LL | cl_box.cl.call_mut(()); - | --------- borrow later used here error: aborting due to previous error diff --git a/src/test/ui/span/range-2.nll.stderr b/src/test/ui/span/range-2.nll.stderr index 2a82e1b8ada..fe2fa2887ed 100644 --- a/src/test/ui/span/range-2.nll.stderr +++ b/src/test/ui/span/range-2.nll.stderr @@ -1,24 +1,24 @@ error[E0597]: `a` does not live long enough --> $DIR/range-2.rs:17:9 | +LL | let r = { + | - borrow later stored here +... LL | &a..&b | ^^ borrowed value does not live long enough LL | }; | - `a` dropped here while still borrowed -... -LL | r.use_ref(); - | - borrow later used here error[E0597]: `b` does not live long enough --> $DIR/range-2.rs:17:13 | +LL | let r = { + | - borrow later stored here +... LL | &a..&b | ^^ borrowed value does not live long enough LL | }; | - `b` dropped here while still borrowed -... -LL | r.use_ref(); - | - borrow later used here error: aborting due to 2 previous errors diff --git a/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr index c14cb709893..80e2266896f 100644 --- a/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr +++ b/src/test/ui/span/send-is-not-static-ensures-scoping.nll.stderr @@ -1,18 +1,21 @@ error[E0597]: `x` does not live long enough --> $DIR/send-is-not-static-ensures-scoping.rs:26:17 | +LL | let bad = { + | --- borrow later stored here +LL | let x = 1; LL | let y = &x; | ^^ borrowed value does not live long enough ... LL | }; | - `x` dropped here while still borrowed -LL | -LL | bad.join(); - | --- borrow later used here error[E0597]: `y` does not live long enough --> $DIR/send-is-not-static-ensures-scoping.rs:30:22 | +LL | let bad = { + | --- borrow later stored here +... LL | scoped(|| { | -- value captured here LL | let _z = y; @@ -20,9 +23,6 @@ LL | let _z = y; ... LL | }; | - `y` dropped here while still borrowed -LL | -LL | bad.join(); - | --- borrow later used here error: aborting due to 2 previous errors diff --git a/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr b/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr index 58dad753ac4..5b79b71dda0 100644 --- a/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr +++ b/src/test/ui/span/send-is-not-static-std-sync-2.nll.stderr @@ -1,24 +1,24 @@ error[E0597]: `x` does not live long enough --> $DIR/send-is-not-static-std-sync-2.rs:21:20 | +LL | let lock = { + | ---- borrow later stored here +LL | let x = 1; LL | Mutex::new(&x) | ^^ borrowed value does not live long enough LL | }; | - `x` dropped here while still borrowed -... -LL | let _dangling = *lock.lock().unwrap(); - | ---- borrow later used here error[E0597]: `x` does not live long enough --> $DIR/send-is-not-static-std-sync-2.rs:31:21 | +LL | let lock = { + | ---- borrow later stored here +LL | let x = 1; LL | RwLock::new(&x) | ^^ borrowed value does not live long enough LL | }; | - `x` dropped here while still borrowed -LL | //~^^ ERROR `x` does not live long enough -LL | let _dangling = *lock.read().unwrap(); - | ---- borrow later used here error[E0597]: `x` does not live long enough --> $DIR/send-is-not-static-std-sync-2.rs:41:25 diff --git a/src/test/ui/span/wf-method-late-bound-regions.nll.stderr b/src/test/ui/span/wf-method-late-bound-regions.nll.stderr index cc32eaaa979..85eb348257b 100644 --- a/src/test/ui/span/wf-method-late-bound-regions.nll.stderr +++ b/src/test/ui/span/wf-method-late-bound-regions.nll.stderr @@ -1,13 +1,13 @@ error[E0597]: `pointer` does not live long enough --> $DIR/wf-method-late-bound-regions.rs:30:18 | +LL | let dangling = { + | -------- borrow later stored here +LL | let pointer = Box::new(42); LL | f2.xmute(&pointer) | ^^^^^^^^ borrowed value does not live long enough LL | }; | - `pointer` dropped here while still borrowed -LL | //~^^ ERROR `pointer` does not live long enough -LL | println!("{}", dangling); - | -------- borrow later used here error: aborting due to previous error diff --git a/src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr b/src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr index 6ad57a15465..7ba06b6ffb2 100644 --- a/src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr +++ b/src/test/ui/unboxed-closures/unboxed-closure-region.nll.stderr @@ -1,14 +1,15 @@ error[E0597]: `x` does not live long enough --> $DIR/unboxed-closure-region.rs:18:12 | +LL | let _f = { + | -- borrow later stored here +LL | let x = 0; LL | || x //~ ERROR `x` does not live long enough | -- ^ borrowed value does not live long enough | | | value captured here LL | }; | - `x` dropped here while still borrowed -LL | _f; - | -- borrow later used here error: aborting due to previous error From ae6479c13bd3fdb17ed055b88f4ca166dabb4e9f Mon Sep 17 00:00:00 2001 From: Remy Rakic Date: Fri, 14 Sep 2018 21:54:45 +0200 Subject: [PATCH 6/9] Move comments for fake reads where the causes are defined --- src/librustc/mir/mod.rs | 18 ++++++++++++++++ src/librustc_mir/build/matches/mod.rs | 31 ++++++--------------------- 2 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 8e9c1ad23c8..57aa2186927 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1667,7 +1667,25 @@ pub enum StatementKind<'tcx> { /// The `FakeReadCause` describes the type of pattern why a `FakeRead` statement exists. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)] pub enum FakeReadCause { + /// Inject a fake read of the borrowed input at the start of each arm's + /// pattern testing code. + /// + /// This should ensure that you cannot change the variant for an enum + /// while you are in the midst of matching on it. ForMatch, + + /// Officially, the semantics of + /// + /// `let pattern = ;` + /// + /// is that `` is evaluated into a temporary and then this temporary is + /// into the pattern. + /// + /// However, if we see the simple pattern `let var = `, we optimize this to + /// evaluate `` directly into the variable `var`. This is mostly unobservable, + /// but in some cases it can affect the borrow checker, as in #53695. + /// Therefore, we insert a "fake read" here to ensure that we get + /// appropriate errors. ForLet, } diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index 49c1308329f..c30dcdafdb4 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -145,19 +145,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if let (true, Some(borrow_temp)) = (tcx.emit_read_for_match(), borrowed_input_temp.clone()) { - // inject a fake read of the borrowed input at - // the start of each arm's pattern testing - // code. - // - // This should ensure that you cannot change - // the variant for an enum while you are in - // the midst of matching on it. + // Inject a fake read, see comments on `FakeReadCause::ForMatch`. let pattern_source_info = self.source_info(pattern.span); self.cfg.push( *pre_binding_block, Statement { source_info: pattern_source_info, - kind: StatementKind::FakeRead(FakeReadCause::ForMatch, borrow_temp.clone()), + kind: StatementKind::FakeRead( + FakeReadCause::ForMatch, + borrow_temp.clone(), + ), }, ); } @@ -266,19 +263,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { unpack!(block = self.into(&place, block, initializer)); - // Officially, the semantics of - // - // `let pattern = ;` - // - // is that `` is evaluated into a temporary and then this temporary is - // into the pattern. - // - // However, if we see the simple pattern `let var = `, we optimize this to - // evaluate `` directly into the variable `var`. This is mostly unobservable, - // but in some cases it can affect the borrow checker, as in #53695. - // Therefore, we insert a "fake read" here to ensure that we get - // appropriate errors. - // + // Inject a fake read, see comments on `FakeReadCause::ForLet`. let source_info = self.source_info(irrefutable_pat.span); self.cfg.push( block, @@ -329,9 +314,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }, ); - // Similarly to the `let var = ` case, we insert a "fake read" here to - // ensure that we get appropriate errors when this usually unobservable - // optimization affects the borrow checker. + // Inject a fake read, see comments on `FakeReadCause::ForLet`. self.cfg.push( block, Statement { From 75b94e24bf21304a3d2a4f5aac39f893b4ac4245 Mon Sep 17 00:00:00 2001 From: Remy Rakic Date: Fri, 14 Sep 2018 22:22:02 +0200 Subject: [PATCH 7/9] Create a helper function to retrieve the FakeReadClause at a location --- .../borrow_check/error_reporting.rs | 17 +++++++++++- .../borrow_check/nll/explain_borrow/mod.rs | 26 +++---------------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 4671332f282..de2c2164a1f 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -12,7 +12,7 @@ use borrow_check::WriteKind; use rustc::middle::region::ScopeTree; use rustc::mir::VarBindingForm; use rustc::mir::{BindingForm, BorrowKind, ClearCrossCrate, Field, Local}; -use rustc::mir::{LocalDecl, LocalKind, Location, Operand, Place}; +use rustc::mir::{FakeReadCause, LocalDecl, LocalKind, Location, Operand, Place}; use rustc::mir::{ProjectionElem, Rvalue, Statement, StatementKind}; use rustc::ty; use rustc_data_structures::fx::FxHashSet; @@ -989,6 +989,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { false } } + + /// Returns the `FakeReadCause` at this location if it is a `FakeRead` statement. + pub(super) fn retrieve_fake_read_cause_for_location( + &self, + location: &Location, + ) -> Option { + let stmt = self.mir.basic_blocks()[location.block] + .statements + .get(location.statement_index)?; + if let StatementKind::FakeRead(cause, _) = stmt.kind { + Some(cause) + } else { + None + } + } } // The span(s) associated to a use of a place. diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index a62e608a875..c094350757e 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -11,7 +11,7 @@ use borrow_check::borrow_set::BorrowData; use borrow_check::nll::region_infer::Cause; use borrow_check::{Context, MirBorrowckCtxt, WriteKind}; -use rustc::mir::{FakeReadCause, Local, Location, Place, StatementKind, TerminatorKind}; +use rustc::mir::{FakeReadCause, Local, Location, Place, TerminatorKind}; use rustc_errors::DiagnosticBuilder; use rustc::ty::Region; @@ -145,27 +145,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Check if the location represents a `FakeRead`, and adapt the error // message to the `FakeReadCause` it is from: in particular, // the ones inserted in optimized `let var = ` patterns. - let is_fake_read_for_let = match self.mir.basic_blocks()[location.block] - .statements - .get(location.statement_index) - { - None => false, - Some(stmt) => { - if let StatementKind::FakeRead(ref cause, _) = stmt.kind { - match cause { - FakeReadCause::ForLet => true, - _ => false, - } - } else { - false - } - } - }; - - if is_fake_read_for_let { - "borrow later stored here" - } else { - "borrow later used here" + match self.retrieve_fake_read_cause_for_location(&location) { + Some(FakeReadCause::ForLet) => "borrow later stored here", + _ => "borrow later used here" } } }; From e90c9424770ec98400aa4d30d2f0c99a8cde43d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Re=CC=81my=20Rakic?= Date: Sat, 15 Sep 2018 01:05:29 +0200 Subject: [PATCH 8/9] Update mir-opt test suite --- src/test/mir-opt/basic_assignment.rs | 2 ++ src/test/mir-opt/box_expr.rs | 1 + src/test/mir-opt/end_region_1.rs | 2 ++ src/test/mir-opt/end_region_2.rs | 3 +++ src/test/mir-opt/end_region_3.rs | 2 ++ src/test/mir-opt/end_region_4.rs | 4 ++++ src/test/mir-opt/end_region_5.rs | 1 + src/test/mir-opt/end_region_6.rs | 2 ++ src/test/mir-opt/end_region_7.rs | 2 ++ src/test/mir-opt/end_region_8.rs | 2 ++ src/test/mir-opt/end_region_9.rs | 2 ++ src/test/mir-opt/end_region_cyclic.rs | 1 + .../mir-opt/inline-closure-borrows-arg.rs | 1 + src/test/mir-opt/issue-38669.rs | 1 + src/test/mir-opt/issue-49232.rs | 1 + src/test/mir-opt/loop_test.rs | 1 + src/test/mir-opt/match_false_edges.rs | 20 +++++++++---------- .../mir-opt/nll/region-subtyping-basic.rs | 6 +++--- src/test/mir-opt/storage_ranges.rs | 3 +++ src/test/mir-opt/validate_1.rs | 1 + src/test/mir-opt/validate_2.rs | 1 + src/test/mir-opt/validate_3.rs | 2 ++ 22 files changed, 48 insertions(+), 13 deletions(-) diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs index f04d4328929..b474e1a0d6c 100644 --- a/src/test/mir-opt/basic_assignment.rs +++ b/src/test/mir-opt/basic_assignment.rs @@ -47,6 +47,7 @@ fn main() { // bb0: { // StorageLive(_1); // _1 = const false; +// FakeRead(ForLet, _1); // StorageLive(_2); // StorageLive(_3); // _3 = _1; @@ -55,6 +56,7 @@ fn main() { // StorageLive(_4); // _4 = std::option::Option>::None; // AscribeUserType(_4, o, Canonical { variables: [], value: std::option::Option> }); +// FakeRead(ForLet, _4); // StorageLive(_5); // StorageLive(_6); // _6 = move _4; diff --git a/src/test/mir-opt/box_expr.rs b/src/test/mir-opt/box_expr.rs index 8390a0d19ae..f6877d979e0 100644 --- a/src/test/mir-opt/box_expr.rs +++ b/src/test/mir-opt/box_expr.rs @@ -63,6 +63,7 @@ impl Drop for S { // // bb4: { // StorageDead(_2); +// FakeRead(ForLet, _1); // StorageLive(_4); // _4 = move _1; // _3 = const std::mem::drop(move _4) -> [return: bb5, unwind: bb7]; diff --git a/src/test/mir-opt/end_region_1.rs b/src/test/mir-opt/end_region_1.rs index 184459aa90e..23c00c3bce1 100644 --- a/src/test/mir-opt/end_region_1.rs +++ b/src/test/mir-opt/end_region_1.rs @@ -29,8 +29,10 @@ fn main() { // bb0: { // StorageLive(_1); // _1 = const 3i32; +// FakeRead(ForLet, _1); // StorageLive(_2); // _2 = &'10_1rs _1; +// FakeRead(ForLet, _2); // _0 = (); // EndRegion('10_1rs); // StorageDead(_2); diff --git a/src/test/mir-opt/end_region_2.rs b/src/test/mir-opt/end_region_2.rs index c40ab5253a0..08de5320a2b 100644 --- a/src/test/mir-opt/end_region_2.rs +++ b/src/test/mir-opt/end_region_2.rs @@ -45,8 +45,10 @@ fn main() { // bb2: { // StorageLive(_2); // _2 = const true; +// FakeRead(ForLet, _2); // StorageLive(_3); // _3 = &'23_1rs _2; +// FakeRead(ForLet, _3); // StorageLive(_5); // _5 = _2; // switchInt(move _5) -> [false: bb5, otherwise: bb4]; @@ -67,6 +69,7 @@ fn main() { // StorageDead(_5); // StorageLive(_7); // _7 = &'23_3rs _2; +// FakeRead(ForLet, _7); // _1 = (); // EndRegion('23_3rs); // StorageDead(_7); diff --git a/src/test/mir-opt/end_region_3.rs b/src/test/mir-opt/end_region_3.rs index 086d80d15ea..189154332b8 100644 --- a/src/test/mir-opt/end_region_3.rs +++ b/src/test/mir-opt/end_region_3.rs @@ -49,6 +49,7 @@ fn main() { // _1 = const true; // StorageLive(_3); // _3 = &'26_1rs _1; +// FakeRead(ForLet, _3); // StorageLive(_5); // _5 = _1; // switchInt(move _5) -> [false: bb5, otherwise: bb4]; @@ -69,6 +70,7 @@ fn main() { // StorageDead(_5); // StorageLive(_7); // _7 = &'26_3rs _1; +// FakeRead(ForLet, _7); // _2 = (); // EndRegion('26_3rs); // StorageDead(_7); diff --git a/src/test/mir-opt/end_region_4.rs b/src/test/mir-opt/end_region_4.rs index fc58e0824e8..d5701669d2b 100644 --- a/src/test/mir-opt/end_region_4.rs +++ b/src/test/mir-opt/end_region_4.rs @@ -45,10 +45,13 @@ fn foo(i: i32) { // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); +// FakeRead(ForLet, _1); // StorageLive(_2); // _2 = const 0i32; +// FakeRead(ForLet, _2); // StorageLive(_3); // _3 = &'26_2rs _2; +// FakeRead(ForLet, _3); // StorageLive(_5); // _5 = (*_3); // _4 = const foo(move _5) -> [return: bb2, unwind: bb3]; @@ -60,6 +63,7 @@ fn foo(i: i32) { // StorageDead(_5); // StorageLive(_6); // _6 = &'26_4rs _2; +// FakeRead(ForLet, _6); // _0 = (); // EndRegion('26_4rs); // StorageDead(_6); diff --git a/src/test/mir-opt/end_region_5.rs b/src/test/mir-opt/end_region_5.rs index 9496fd9e6c1..7a5d71ee21b 100644 --- a/src/test/mir-opt/end_region_5.rs +++ b/src/test/mir-opt/end_region_5.rs @@ -38,6 +38,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); +// FakeRead(ForLet, _1); // StorageLive(_3); // StorageLive(_4); // _4 = &'14s _1; diff --git a/src/test/mir-opt/end_region_6.rs b/src/test/mir-opt/end_region_6.rs index 910362f65c8..b9162f85fa7 100644 --- a/src/test/mir-opt/end_region_6.rs +++ b/src/test/mir-opt/end_region_6.rs @@ -38,6 +38,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); +// FakeRead(ForLet, _1); // StorageLive(_3); // StorageLive(_4); // _4 = &'19s _1; @@ -73,6 +74,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // bb0: { // StorageLive(_2); // _2 = &'16_0rs (*(_1.0: &'19s D)); +// FakeRead(ForLet, _2); // _0 = ((*_2).0: i32); // EndRegion('16_0rs); // StorageDead(_2); diff --git a/src/test/mir-opt/end_region_7.rs b/src/test/mir-opt/end_region_7.rs index 59261ec9687..4deea75e56b 100644 --- a/src/test/mir-opt/end_region_7.rs +++ b/src/test/mir-opt/end_region_7.rs @@ -37,6 +37,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); +// FakeRead(ForLet, _1); // StorageLive(_3); // _3 = [closure@NodeId(22)] { d: move _1 }; // _2 = const foo(move _3) -> [return: bb2, unwind: bb4]; @@ -74,6 +75,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // bb0: { // StorageLive(_2); // _2 = &'16_0rs (_1.0: D); +// FakeRead(ForLet, _2); // _0 = ((*_2).0: i32); // EndRegion('16_0rs); // StorageDead(_2); diff --git a/src/test/mir-opt/end_region_8.rs b/src/test/mir-opt/end_region_8.rs index a49913a62d9..6f899a0db15 100644 --- a/src/test/mir-opt/end_region_8.rs +++ b/src/test/mir-opt/end_region_8.rs @@ -40,8 +40,10 @@ fn foo(f: F) where F: FnOnce() -> i32 { // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); +// FakeRead(ForLet, _1); // StorageLive(_2); // _2 = &'21_1rs _1; +// FakeRead(ForLet, _2); // StorageLive(_4); // _4 = [closure@NodeId(22)] { r: _2 }; // _3 = const foo(move _4) -> [return: bb2, unwind: bb3]; diff --git a/src/test/mir-opt/end_region_9.rs b/src/test/mir-opt/end_region_9.rs index 15c31e17875..b43f25e6f54 100644 --- a/src/test/mir-opt/end_region_9.rs +++ b/src/test/mir-opt/end_region_9.rs @@ -55,8 +55,10 @@ fn main() { // bb0: { // StorageLive(_1); // _1 = const false; +// FakeRead(ForLet, _1); // StorageLive(_2); // _2 = const 3i32; +// FakeRead(ForLet, _2); // falseUnwind -> [real: bb2, cleanup: bb1]; // } // bb1: { diff --git a/src/test/mir-opt/end_region_cyclic.rs b/src/test/mir-opt/end_region_cyclic.rs index 2d6962c5a5c..75cfb5c2f62 100644 --- a/src/test/mir-opt/end_region_cyclic.rs +++ b/src/test/mir-opt/end_region_cyclic.rs @@ -83,6 +83,7 @@ fn query() -> bool { true } // StorageDead(_4); // _2 = S<'36_0rs> { r: move _3 }; // StorageDead(_3); +// FakeRead(ForLet, _2); // StorageLive(_6); // _6 = &'17s (_2.0: std::cell::Cell>>); // StorageLive(_7); diff --git a/src/test/mir-opt/inline-closure-borrows-arg.rs b/src/test/mir-opt/inline-closure-borrows-arg.rs index 6ce51be3ec5..aab432ddc87 100644 --- a/src/test/mir-opt/inline-closure-borrows-arg.rs +++ b/src/test/mir-opt/inline-closure-borrows-arg.rs @@ -40,6 +40,7 @@ fn foo(_t: T, q: &i32) -> i32 { // _5 = (move _6, move _7); // _8 = move (_5.0: &i32); // _9 = move (_5.1: &i32); +// ... // _0 = (*_8); // ... // return; diff --git a/src/test/mir-opt/issue-38669.rs b/src/test/mir-opt/issue-38669.rs index a9eea26f466..78820d7a6f5 100644 --- a/src/test/mir-opt/issue-38669.rs +++ b/src/test/mir-opt/issue-38669.rs @@ -25,6 +25,7 @@ fn main() { // bb0: { // StorageLive(_1); // _1 = const false; +// FakeRead(ForLet, _1); // goto -> bb2; // } // bb1: { diff --git a/src/test/mir-opt/issue-49232.rs b/src/test/mir-opt/issue-49232.rs index 8e5a94abeed..3bc735bc6c5 100644 --- a/src/test/mir-opt/issue-49232.rs +++ b/src/test/mir-opt/issue-49232.rs @@ -87,6 +87,7 @@ fn main() { // goto -> bb6; // } // bb14: { +// FakeRead(ForLet, _2); // StorageDead(_3); // StorageLive(_7); // _7 = &_2; diff --git a/src/test/mir-opt/loop_test.rs b/src/test/mir-opt/loop_test.rs index d36d8908094..2e526a221cc 100644 --- a/src/test/mir-opt/loop_test.rs +++ b/src/test/mir-opt/loop_test.rs @@ -42,6 +42,7 @@ fn main() { // bb5: { // The loop body (body_block) // StorageLive(_5); // _5 = const 1i32; +// FakeRead(ForLet, _5); // StorageDead(_5); // goto -> bb4; // } diff --git a/src/test/mir-opt/match_false_edges.rs b/src/test/mir-opt/match_false_edges.rs index 43e711ca902..b9f4c239127 100644 --- a/src/test/mir-opt/match_false_edges.rs +++ b/src/test/mir-opt/match_false_edges.rs @@ -66,15 +66,15 @@ fn main() { // goto -> bb13; // } // bb3: { // binding3(empty) and arm3 -// ReadForMatch(_4); +// FakeRead(ForMatch, _4); // falseEdges -> [real: bb8, imaginary: bb4]; //pre_binding1 // } // bb4: { -// ReadForMatch(_4); +// FakeRead(ForMatch, _4); // falseEdges -> [real: bb12, imaginary: bb5]; //pre_binding2 // } // bb5: { -// ReadForMatch(_4); +// FakeRead(ForMatch, _4); // falseEdges -> [real: bb2, imaginary: bb6]; //pre_binding3 // } // bb6: { @@ -136,15 +136,15 @@ fn main() { // goto -> bb13; // } // bb3: { -// ReadForMatch(_4); +// FakeRead(ForMatch, _4); // falseEdges -> [real: bb8, imaginary: bb4]; //pre_binding1 // } // bb4: { -// ReadForMatch(_4); +// FakeRead(ForMatch, _4); // falseEdges -> [real: bb2, imaginary: bb5]; //pre_binding2 // } // bb5: { -// ReadForMatch(_4); +// FakeRead(ForMatch, _4); // falseEdges -> [real: bb12, imaginary: bb6]; //pre_binding3 // } // bb6: { @@ -202,19 +202,19 @@ fn main() { // resume; // } // bb2: { -// ReadForMatch(_4); +// FakeRead(ForMatch, _4); // falseEdges -> [real: bb7, imaginary: bb3]; //pre_binding1 // } // bb3: { -// ReadForMatch(_4); +// FakeRead(ForMatch, _4); // falseEdges -> [real: bb11, imaginary: bb4]; //pre_binding2 // } // bb4: { -// ReadForMatch(_4); +// FakeRead(ForMatch, _4); // falseEdges -> [real: bb12, imaginary: bb5]; //pre_binding3 // } // bb5: { -// ReadForMatch(_4); +// FakeRead(ForMatch, _4); // falseEdges -> [real: bb16, imaginary: bb6]; //pre_binding4 // } // bb6: { diff --git a/src/test/mir-opt/nll/region-subtyping-basic.rs b/src/test/mir-opt/nll/region-subtyping-basic.rs index e554024efef..2b926422b00 100644 --- a/src/test/mir-opt/nll/region-subtyping-basic.rs +++ b/src/test/mir-opt/nll/region-subtyping-basic.rs @@ -32,9 +32,9 @@ fn main() { // END RUST SOURCE // START rustc.main.nll.0.mir -// | '_#2r | U0 | {bb2[0..=3], bb3[0..=1]} -// | '_#3r | U0 | {bb2[1..=3], bb3[0..=1]} -// | '_#4r | U0 | {bb2[3], bb3[0..=1]} +// | '_#2r | U0 | {bb2[0..=5], bb3[0..=1]} +// | '_#3r | U0 | {bb2[1..=5], bb3[0..=1]} +// | '_#4r | U0 | {bb2[4..=5], bb3[0..=1]} // END rustc.main.nll.0.mir // START rustc.main.nll.0.mir // let _6: &'_#4r usize; diff --git a/src/test/mir-opt/storage_ranges.rs b/src/test/mir-opt/storage_ranges.rs index 16e30f84d17..203814ce949 100644 --- a/src/test/mir-opt/storage_ranges.rs +++ b/src/test/mir-opt/storage_ranges.rs @@ -23,6 +23,7 @@ fn main() { // bb0: { // StorageLive(_1); // _1 = const 0i32; +// FakeRead(ForLet, _1); // StorageLive(_3); // StorageLive(_4); // StorageLive(_5); @@ -30,11 +31,13 @@ fn main() { // _4 = std::option::Option::Some(move _5,); // StorageDead(_5); // _3 = &_4; +// FakeRead(ForLet, _3); // _2 = (); // StorageDead(_4); // StorageDead(_3); // StorageLive(_6); // _6 = const 1i32; +// FakeRead(ForLet, _6); // _0 = (); // StorageDead(_6); // StorageDead(_1); diff --git a/src/test/mir-opt/validate_1.rs b/src/test/mir-opt/validate_1.rs index 882579c5710..3ea8e99e953 100644 --- a/src/test/mir-opt/validate_1.rs +++ b/src/test/mir-opt/validate_1.rs @@ -67,6 +67,7 @@ fn main() { // Validate(Suspend(ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 })), [(*_2): i32]); // _3 = &ReErased (*_2); // Validate(Acquire, [(*_3): i32/ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 }) (imm)]); +// FakeRead(ForLet, _3); // _0 = (*_3); // EndRegion(ReScope(Remainder { block: ItemLocalId(25), first_statement_index: 0 })); // StorageDead(_3); diff --git a/src/test/mir-opt/validate_2.rs b/src/test/mir-opt/validate_2.rs index 3776a11b3ab..0cb0b7debfa 100644 --- a/src/test/mir-opt/validate_2.rs +++ b/src/test/mir-opt/validate_2.rs @@ -28,6 +28,7 @@ fn main() { // Validate(Acquire, [_1: std::boxed::Box<[i32]>]); // StorageDead(_2); // StorageDead(_3); +// FakeRead(ForLet, _1); // _0 = (); // Validate(Release, [_1: std::boxed::Box<[i32]>]); // drop(_1) -> [return: bb2, unwind: bb3]; diff --git a/src/test/mir-opt/validate_3.rs b/src/test/mir-opt/validate_3.rs index 07f5b2aa84b..89b67bd34c8 100644 --- a/src/test/mir-opt/validate_3.rs +++ b/src/test/mir-opt/validate_3.rs @@ -47,10 +47,12 @@ fn main() { // bb0: { // StorageLive(_1); // _1 = Test { x: const 0i32 }; +// FakeRead(ForLet, _1); // StorageLive(_2); // Validate(Suspend(ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 })), [_1: Test]); // _2 = &ReErased _1; // Validate(Acquire, [(*_2): Test/ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }) (imm)]); +// FakeRead(ForLet, _2); // StorageLive(_4); // StorageLive(_5); // Validate(Suspend(ReScope(Node(ItemLocalId(18)))), [((*_2).0: i32): i32/ReScope(Remainder { block: ItemLocalId(20), first_statement_index: 3 }) (imm)]); From 3bdba74ed3f8a859331ff658a6c0235855331095 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Re=CC=81my=20Rakic?= Date: Thu, 20 Sep 2018 23:22:42 +0200 Subject: [PATCH 9/9] Disable rustfix temporarily on extern-const.rs `src/test/ui/extern/extern-const.rs` seems to have an inconsistent behaviour across build configurations, possibly non-deterministically. This is tracked in issue 54388. For this PR, disable running rustfix on it because it failed on CI, until that issue is fixed. --- src/test/ui/extern/extern-const.fixed | 25 ------------------------- src/test/ui/extern/extern-const.rs | 2 +- 2 files changed, 1 insertion(+), 26 deletions(-) delete mode 100644 src/test/ui/extern/extern-const.fixed diff --git a/src/test/ui/extern/extern-const.fixed b/src/test/ui/extern/extern-const.fixed deleted file mode 100644 index 6e131ca41aa..00000000000 --- a/src/test/ui/extern/extern-const.fixed +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2017 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -// run-rustfix -// compile-flags: -Z continue-parse-after-error - -extern "C" { - static C: u8; //~ ERROR extern items cannot be `const` -} - -fn main() { - // We suggest turning the (illegal) extern `const` into an extern `static`, - // but this also requires `unsafe` (a deny-by-default lint at comment time, - // future error; Issue #36247) - unsafe { - let _x = C; - } -} diff --git a/src/test/ui/extern/extern-const.rs b/src/test/ui/extern/extern-const.rs index 4a766b9724d..d8a167311d5 100644 --- a/src/test/ui/extern/extern-const.rs +++ b/src/test/ui/extern/extern-const.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// run-rustfix +// FIXME(#54388): re-enable rustfix later, when this test has consistent output across targets // compile-flags: -Z continue-parse-after-error extern "C" {