diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index 5f35c9fea0a33..313ef054829c5 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 3450eec8082f3..57aa2186927a9 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,31 @@ 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 { + /// 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, +} + /// The `ValidationOp` describes what happens with each of the operands of a /// `Validate` statement. #[derive(Copy, Clone, RustcEncodable, RustcDecodable, PartialEq, Eq)] @@ -1718,7 +1745,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 +2612,7 @@ CloneTypeFoldableAndLiftImpls! { Mutability, SourceInfo, UpvarDecl, + FakeReadCause, ValidationOp, SourceScope, SourceScopeData, @@ -2651,7 +2679,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 0beb5ac0a3cb5..91c83ecb2e23c 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 e4d633c3f2cf2..1fdbf687be8f8 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 b7b0fdca2e634..37ef408c6bdee 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1505,7 +1505,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 0cb8f99efc33f..b4eb7615f98b4 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/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 9187cb97e69e5..44bfc0cf06de7 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; @@ -1020,6 +1020,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/mod.rs b/src/librustc_mir/borrow_check/mod.rs index c7e53714e3e84..aea0bb748b2e8 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -501,9 +501,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, @@ -2229,7 +2229,7 @@ enum ContextKind { CallDest, Assert, Yield, - ReadForMatch, + FakeRead, StorageDead, } 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 414cb1d6f05c2..c094350757e2f 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, TerminatorKind}; use rustc_errors::DiagnosticBuilder; use rustc::ty::Region; @@ -142,7 +142,13 @@ 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. + match self.retrieve_fake_read_cause_for_location(&location) { + Some(FakeReadCause::ForLet) => "borrow later stored here", + _ => "borrow later used here" + } } }; err.span_label(spans.var_or_use(), message); diff --git a/src/librustc_mir/borrow_check/nll/invalidation.rs b/src/librustc_mir/borrow_check/nll/invalidation.rs index 71345f22e443b..0b7fededa9732 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 de96539ec30f1..1f12e9c747f45 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 49c4ed874bbe9..c30dcdafdb402 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::ReadForMatch(borrow_temp.clone()), + kind: StatementKind::FakeRead( + FakeReadCause::ForMatch, + borrow_temp.clone(), + ), }, ); } @@ -264,6 +261,18 @@ 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, see comments on `FakeReadCause::ForLet`. + let source_info = self.source_info(irrefutable_pat.span); + self.cfg.push( + block, + Statement { + source_info, + kind: StatementKind::FakeRead(FakeReadCause::ForLet, place.clone()), + }, + ); + self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } @@ -305,6 +314,15 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { }, ); + // Inject a fake read, see comments on `FakeReadCause::ForLet`. + self.cfg.push( + block, + Statement { + source_info, + kind: StatementKind::FakeRead(FakeReadCause::ForLet, place.clone()), + }, + ); + self.schedule_drop_for_binding(var, irrefutable_pat.span, OutsideGuard); block.unit() } diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 010ffafc4bd60..ed2f780baf1c2 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 5451d27082db7..63adcb5132a71 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 5bdaf6ba72963..5db7e0b5eb531 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 6fbc2f85c08da..286de52bec5ca 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 bc9cc7274d5e7..a997bd37c50a3 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 f7e44dde186fe..541b3c0607de3 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 9cdd94a7be7f1..298e38228d357 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 3c898eedebcc4..487a18f6620b2 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 0120b5bc5322f..0b9b20d3c4539 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", diff --git a/src/test/mir-opt/basic_assignment.rs b/src/test/mir-opt/basic_assignment.rs index f04d432892968..b474e1a0d6cae 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 8390a0d19ae7b..f6877d979e073 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 184459aa90eb8..23c00c3bce1d8 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 c40ab5253a075..08de5320a2b32 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 086d80d15eacd..189154332b85a 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 fc58e0824e8bd..d5701669d2bdd 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 9496fd9e6c173..7a5d71ee21b93 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 910362f65c8d9..b9162f85fa71e 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 59261ec968740..4deea75e56b04 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 a49913a62d9d0..6f899a0db15d9 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 15c31e178759d..b43f25e6f548c 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 2d6962c5a5c1f..75cfb5c2f6239 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 6ce51be3ec5db..aab432ddc8700 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 a9eea26f46643..78820d7a6f5f8 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 8e5a94abeed78..3bc735bc6c5ed 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 d36d890809497..2e526a221cc72 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 43e711ca902f8..b9f4c23912737 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 e554024efef43..2b926422b0012 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 16e30f84d1756..203814ce949ff 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 882579c571086..3ea8e99e953b4 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 3776a11b3ab82..0cb0b7debfaa3 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 07f5b2aa84b7d..89b67bd34c83d 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)]); diff --git a/src/test/ui/extern/extern-const.fixed b/src/test/ui/extern/extern-const.fixed deleted file mode 100644 index 6e131ca41aa97..0000000000000 --- 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 4a766b9724dc2..d8a167311d55c 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" { diff --git a/src/test/ui/generator/borrowing.nll.stderr b/src/test/ui/generator/borrowing.nll.stderr index e03d72a02f0aa..2488df7772b3f 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 ed70e38362dac..538903c591868 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 2a82e1b8ada8c..fe2fa2887ed48 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 c14cb7098933f..80e2266896fab 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 58dad753ac4a1..5b79b71dda0d6 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 cc32eaaa97991..85eb348257bbf 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 6ad57a15465d3..7ba06b6ffb2d7 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