From 517e7fd2a1bb54da9da5ad121a28f5ea80f72edf Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 6 Apr 2018 11:12:27 -0400 Subject: [PATCH 01/16] remove `assigned_map` (appears to be dead code) --- src/librustc_mir/dataflow/impls/borrows.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index aa991427be093..e6b8cd6abf066 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -58,11 +58,6 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> { /// corresponding `BorrowIndex`. location_map: FxHashMap, - /// Every borrow in MIR is immediately stored into a place via an - /// assignment statement. This maps each such assigned place back - /// to its borrow-indexes. - assigned_map: FxHashMap, FxHashSet>, - /// Locations which activate borrows. activation_map: FxHashMap>, @@ -144,7 +139,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { mir, idx_vec: IndexVec::new(), location_map: FxHashMap(), - assigned_map: FxHashMap(), activation_map: FxHashMap(), region_map: FxHashMap(), local_map: FxHashMap(), @@ -158,7 +152,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { scope_tree, root_scope, location_map: visitor.location_map, - assigned_map: visitor.assigned_map, activation_map: visitor.activation_map, region_map: visitor.region_map, local_map: visitor.local_map, @@ -170,7 +163,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { mir: &'a Mir<'tcx>, idx_vec: IndexVec>, location_map: FxHashMap, - assigned_map: FxHashMap, FxHashSet>, activation_map: FxHashMap>, region_map: FxHashMap, FxHashSet>, local_map: FxHashMap>, @@ -209,7 +201,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { self.location_map.insert(location, idx); insert(&mut self.activation_map, &activate_location, idx); - insert(&mut self.assigned_map, assigned_place, idx); insert(&mut self.region_map, ®ion, idx); if let Some(local) = root_local(borrowed_place) { insert(&mut self.local_map, &local, idx); From 6c528ce784befb01e569d4743a4c7f6557d83c4d Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 6 Apr 2018 11:50:17 -0400 Subject: [PATCH 02/16] gather activation locations for 2-phase borrows in 1 pass --- src/librustc_mir/dataflow/impls/borrows.rs | 237 ++++++++++++--------- 1 file changed, 139 insertions(+), 98 deletions(-) diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index e6b8cd6abf066..b83e78ef1d1b6 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -13,6 +13,7 @@ use rustc::hir; use rustc::hir::def_id::DefId; use rustc::middle::region; use rustc::mir::{self, Location, Place, Mir}; +use rustc::mir::traversal; use rustc::mir::visit::{PlaceContext, Visitor}; use rustc::ty::{self, Region, TyCtxt}; use rustc::ty::RegionKind; @@ -85,6 +86,9 @@ pub struct BorrowData<'tcx> { /// Location where the borrow reservation starts. /// In many cases, this will be equal to the activation location but not always. pub(crate) reserve_location: Location, + /// Location where the borrow is activated. None if this is not a + /// 2-phase borrow. + pub(crate) activation_location: Option, /// What kind of borrow this is pub(crate) kind: mir::BorrowKind, /// The region for which this borrow is live @@ -143,9 +147,26 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { region_map: FxHashMap(), local_map: FxHashMap(), region_span_map: FxHashMap(), - nonlexical_regioncx: nonlexical_regioncx.clone() + nonlexical_regioncx: nonlexical_regioncx.clone(), + pending_activations: FxHashMap(), }; - visitor.visit_mir(mir); + for (block, block_data) in traversal::preorder(mir) { + visitor.visit_basic_block_data(block, block_data); + } + + // Double check: We should have found an activation for every pending + // activation. + assert_eq!( + visitor + .pending_activations + .iter() + .find(|&(_local, &borrow_index)| { + visitor.idx_vec[borrow_index].activation_location.is_none() + }), + None, + "never found an activation for this borrow!", + ); + return Borrows { tcx: tcx, mir: mir, borrows: visitor.idx_vec, @@ -168,6 +189,16 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { local_map: FxHashMap>, region_span_map: FxHashMap, nonlexical_regioncx: Option>>, + + /// When we encounter a 2-phase borrow statement, it will always + /// be assigning into a temporary TEMP: + /// + /// TEMP = &foo + /// + /// We add TEMP into this map with `b`, where `b` is the index of + /// the borrow. When we find a later use of this activation, we + /// remove from the map (and add to the "tombstone" set below). + pending_activations: FxHashMap, } impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { @@ -187,20 +218,25 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue { if is_unsafe_place(self.tcx, self.mir, borrowed_place) { return; } - let activate_location = self.compute_activation_location(location, - &assigned_place, - region, - kind); let borrow = BorrowData { - kind, region, + kind, + region, reserve_location: location, + activation_location: None, borrowed_place: borrowed_place.clone(), assigned_place: assigned_place.clone(), }; let idx = self.idx_vec.push(borrow); self.location_map.insert(location, idx); - insert(&mut self.activation_map, &activate_location, idx); + self.insert_as_pending_if_two_phase( + location, + &assigned_place, + region, + kind, + idx, + ); + insert(&mut self.region_map, ®ion, idx); if let Some(local) = root_local(borrowed_place) { insert(&mut self.local_map, &local, idx); @@ -220,25 +256,69 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { } } + fn visit_place( + &mut self, + place: &mir::Place<'tcx>, + context: PlaceContext<'tcx>, + location: Location, + ) { + self.super_place(place, context, location); + + // We found a use of some temporary TEMP... + if let Place::Local(temp) = place { + // ... check whether we (earlier) saw a 2-phase borrow like + // + // TMP = &mut place + match self.pending_activations.get(temp) { + Some(&borrow_index) => { + let borrow_data = &mut self.idx_vec[borrow_index]; + + // Watch out: the use of TMP in the borrow + // itself doesn't count as an + // activation. =) + if borrow_data.reserve_location == location + && context == PlaceContext::Store + { + return; + } + + if let Some(other_activation) = borrow_data.activation_location { + span_bug!( + self.mir.source_info(location).span, + "found two activations for 2-phase borrow temporary {:?}: \ + {:?} and {:?}", + temp, + location, + other_activation, + ); + } + + // Otherwise, this is the unique later use + // that we expect. + borrow_data.activation_location = Some(location); + self.activation_map + .entry(location) + .or_insert(FxHashSet()) + .insert(borrow_index); + } + + None => {} + } + } + } + fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: mir::Location) { if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue { // double-check that we already registered a BorrowData for this - let mut found_it = false; - for idx in &self.region_map[region] { - let bd = &self.idx_vec[*idx]; - if bd.reserve_location == location && - bd.kind == kind && - bd.region == region && - bd.borrowed_place == *place - { - found_it = true; - break; - } - } - assert!(found_it, "Ref {:?} at {:?} missing BorrowData", rvalue, location); + let borrow_index = self.location_map[&location]; + let borrow_data = &self.idx_vec[borrow_index]; + assert_eq!(borrow_data.reserve_location, location); + assert_eq!(borrow_data.kind, kind); + assert_eq!(borrow_data.region, region); + assert_eq!(borrow_data.borrowed_place, *place); } return self.super_rvalue(rvalue, location); @@ -380,87 +460,48 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { false } - /// Computes the activation location of a borrow. - /// The general idea is to start at the beginning of the region and perform a DFS - /// until we exit the region, either via an explicit EndRegion or because NLL tells - /// us so. If we find more than one valid activation point, we currently panic the - /// compiler since two-phase borrows are only currently supported for compiler- - /// generated code. More precisely, we only allow two-phase borrows for: - /// - Function calls (fn some_func(&mut self, ....)) - /// - *Assign operators (a += b -> fn add_assign(&mut self, other: Self)) - /// See - /// - https://github.com/rust-lang/rust/issues/48431 - /// for detailed design notes. - /// See the FIXME in the body of the function for notes on extending support to more - /// general two-phased borrows. - fn compute_activation_location(&self, - start_location: Location, - assigned_place: &mir::Place<'tcx>, - region: Region<'tcx>, - kind: mir::BorrowKind) -> Location { - debug!("Borrows::compute_activation_location({:?}, {:?}, {:?})", - start_location, - assigned_place, - region); + /// If this is a two-phase borrow, then we will record it + /// as "pending" until we find the activating use. + fn insert_as_pending_if_two_phase( + &mut self, + start_location: Location, + assigned_place: &mir::Place<'tcx>, + region: Region<'tcx>, + kind: mir::BorrowKind, + borrow_index: BorrowIndex, + ) { + debug!( + "Borrows::insert_as_pending_if_two_phase({:?}, {:?}, {:?}, {:?})", + start_location, assigned_place, region, borrow_index, + ); + if !self.allow_two_phase_borrow(kind) { debug!(" -> {:?}", start_location); - return start_location; - } - - // Perform the DFS. - // `stack` is the stack of locations still under consideration - // `visited` is the set of points we have already visited - // `found_use` is an Option that becomes Some when we find a use - let mut stack = vec![start_location]; - let mut visited = FxHashSet(); - let mut found_use = None; - while let Some(curr_loc) = stack.pop() { - let block_data = &self.mir.basic_blocks() - .get(curr_loc.block) - .unwrap_or_else(|| { - panic!("could not find block at location {:?}", curr_loc); - }); - - if self.region_terminated_after(region, curr_loc) { - // No need to process this statement. - // It's either an EndRegion (and thus couldn't use assigned_place) or not - // contained in the NLL region and thus a use would be invalid - continue; - } - - if !visited.insert(curr_loc) { - debug!(" Already visited {:?}", curr_loc); - continue; - } - - if self.location_contains_use(curr_loc, assigned_place) { - // FIXME: Handle this case a little more gracefully. Perhaps collect - // all uses in a vector, and find the point in the CFG that dominates - // all of them? - // Right now this is sufficient though since there should only be exactly - // one borrow-activating use of the borrow. - assert!(found_use.is_none(), "Found secondary use of place"); - found_use = Some(curr_loc); - } - - // Push the points we should consider next. - if curr_loc.statement_index < block_data.statements.len() { - stack.push(curr_loc.successor_within_block()); - } else { - stack.extend(block_data.terminator().successors().iter().map( - |&basic_block| { - Location { - statement_index: 0, - block: basic_block - } - } - )) - } + return; } - let found_use = found_use.expect("Did not find use of two-phase place"); - debug!(" -> {:?}", found_use); - found_use + // When we encounter a 2-phase borrow statement, it will always + // be assigning into a temporary TEMP: + // + // TEMP = &foo + // + // so extract `temp`. + let temp = if let &mir::Place::Local(temp) = assigned_place { + temp + } else { + span_bug!( + self.mir.source_info(start_location).span, + "expected 2-phase borrow to assign to a local, not `{:?}`", + assigned_place, + ); + }; + + // Insert `temp` into the list of pending activations. From + // now on, we'll be on the lookout for a use of it. Note that + // we are guaranteed that this use will come after the + // assignment. + let old_value = self.pending_activations.insert(temp, borrow_index); + assert!(old_value.is_none()); } } } From 70592664b6b071af2fe03afb60ffb9cfab6feaf7 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 6 Apr 2018 15:18:01 -0400 Subject: [PATCH 03/16] relocate `BorrowData` etc into `borrow_check::borrow_set` --- src/librustc_mir/borrow_check/borrow_set.rs | 78 ++++++++++++++ .../borrow_check/error_reporting.rs | 6 +- src/librustc_mir/borrow_check/mod.rs | 4 +- .../borrow_check/nll/explain_borrow/mod.rs | 2 +- src/librustc_mir/dataflow/impls/borrows.rs | 100 +++++------------- src/librustc_mir/dataflow/impls/mod.rs | 1 + src/librustc_mir/dataflow/mod.rs | 2 +- src/librustc_mir/lib.rs | 1 + 8 files changed, 113 insertions(+), 81 deletions(-) create mode 100644 src/librustc_mir/borrow_check/borrow_set.rs diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs new file mode 100644 index 0000000000000..4d541d0ffd229 --- /dev/null +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -0,0 +1,78 @@ +// Copyright 2012-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. + +use dataflow::indexes::BorrowIndex; +use rustc::mir::{self, Location}; +use rustc::ty::{Region, RegionKind}; +use rustc::util::nodemap::{FxHashMap, FxHashSet}; +use rustc_data_structures::indexed_vec::IndexVec; +use std::fmt; +use syntax_pos::Span; + +crate struct BorrowSet<'tcx> { + /// The fundamental map relating bitvector indexes to the borrows + /// in the MIR. + crate borrows: IndexVec>, + + /// Each borrow is also uniquely identified in the MIR by the + /// `Location` of the assignment statement in which it appears on + /// the right hand side; we map each such location to the + /// corresponding `BorrowIndex`. + crate location_map: FxHashMap, + + /// Locations which activate borrows. + /// NOTE: A given location may activate more than one borrow in the future + /// when more general two-phase borrow support is introduced, but for now we + /// only need to store one borrow index + crate activation_map: FxHashMap>, + + /// Every borrow has a region; this maps each such regions back to + /// its borrow-indexes. + crate region_map: FxHashMap, FxHashSet>, + + /// Map from local to all the borrows on that local + crate local_map: FxHashMap>, + + /// Maps regions to their corresponding source spans + /// Only contains ReScope()s as keys + crate region_span_map: FxHashMap, +} + +#[derive(Debug)] +crate struct BorrowData<'tcx> { + /// Location where the borrow reservation starts. + /// In many cases, this will be equal to the activation location but not always. + crate reserve_location: Location, + /// Location where the borrow is activated. None if this is not a + /// 2-phase borrow. + crate activation_location: Option, + /// What kind of borrow this is + crate kind: mir::BorrowKind, + /// The region for which this borrow is live + crate region: Region<'tcx>, + /// Place from which we are borrowing + crate borrowed_place: mir::Place<'tcx>, + /// Place to which the borrow was stored + crate assigned_place: mir::Place<'tcx>, +} + +impl<'tcx> fmt::Display for BorrowData<'tcx> { + fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { + let kind = match self.kind { + mir::BorrowKind::Shared => "", + mir::BorrowKind::Unique => "uniq ", + mir::BorrowKind::Mut { .. } => "mut ", + }; + let region = format!("{}", self.region); + let region = if region.len() > 0 { format!("{} ", region) } else { region }; + write!(w, "&{}{}{:?}", region, kind, self.borrowed_place) + } +} + diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index aaed1dd871bac..8160a3201dac8 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -18,7 +18,9 @@ use rustc_data_structures::sync::Lrc; use super::{Context, MirBorrowckCtxt}; use super::{InitializationRequiringAction, PrefixSet}; -use dataflow::{Borrows, BorrowData, FlowAtLocation, MovingOutStatements}; +use super::borrow_set::BorrowData; + +use dataflow::{Borrows, FlowAtLocation, MovingOutStatements}; use dataflow::move_paths::MovePathIndex; use util::borrowck_errors::{BorrowckErrors, Origin}; @@ -834,7 +836,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { } // Retrieve span of given borrow from the current MIR representation - pub fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span { + crate fn retrieve_borrow_span(&self, borrow: &BorrowData) -> Span { self.mir.source_info(borrow.reserve_location).span } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 62acdf7654624..69044a3c83e75 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -37,7 +37,7 @@ use dataflow::MoveDataParamEnv; use dataflow::{DataflowResultsConsumer}; use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use dataflow::{EverInitializedPlaces, MovingOutStatements}; -use dataflow::{BorrowData, Borrows, ReserveOrActivateIndex}; +use dataflow::{Borrows, ReserveOrActivateIndex}; use dataflow::indexes::BorrowIndex; use dataflow::move_paths::{IllegalMoveOriginKind, MoveError}; use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex}; @@ -46,10 +46,12 @@ use util::collect_writes::FindAssignments; use std::iter; +use self::borrow_set::BorrowData; use self::flows::Flows; use self::prefixes::PrefixSet; use self::MutateMode::{JustWrite, WriteAndRead}; +crate mod borrow_set; mod error_reporting; mod flows; mod prefixes; 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 187bfc2bf90f9..b12beb524e20d 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -10,7 +10,7 @@ use borrow_check::nll::region_infer::{Cause, RegionInferenceContext}; use borrow_check::{Context, MirBorrowckCtxt}; -use dataflow::BorrowData; +use borrow_check::borrow_set::BorrowData; use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor}; use rustc::mir::{Local, Location, Mir}; use rustc_data_structures::fx::FxHashSet; diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index b83e78ef1d1b6..381718234a62f 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use borrow_check::borrow_set::{BorrowSet, BorrowData}; + use rustc; use rustc::hir; use rustc::hir::def_id::DefId; @@ -32,7 +34,6 @@ use borrow_check::nll::ToRegionVid; use syntax_pos::Span; -use std::fmt; use std::hash::Hash; use std::rc::Rc; @@ -49,69 +50,12 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> { scope_tree: Lrc, root_scope: Option, - /// The fundamental map relating bitvector indexes to the borrows - /// in the MIR. - borrows: IndexVec>, - - /// Each borrow is also uniquely identified in the MIR by the - /// `Location` of the assignment statement in which it appears on - /// the right hand side; we map each such location to the - /// corresponding `BorrowIndex`. - location_map: FxHashMap, - - /// Locations which activate borrows. - activation_map: FxHashMap>, - - /// Every borrow has a region; this maps each such regions back to - /// its borrow-indexes. - region_map: FxHashMap, FxHashSet>, - - /// Map from local to all the borrows on that local - local_map: FxHashMap>, - - /// Maps regions to their corresponding source spans - /// Only contains ReScope()s as keys - region_span_map: FxHashMap, + borrow_set: BorrowSet<'tcx>, /// NLL region inference context with which NLL queries should be resolved nonlexical_regioncx: Option>>, } -// temporarily allow some dead fields: `kind` and `region` will be -// needed by borrowck; `borrowed_place` will probably be a MovePathIndex when -// that is extended to include borrowed data paths. -#[allow(dead_code)] -#[derive(Debug)] -pub struct BorrowData<'tcx> { - /// Location where the borrow reservation starts. - /// In many cases, this will be equal to the activation location but not always. - pub(crate) reserve_location: Location, - /// Location where the borrow is activated. None if this is not a - /// 2-phase borrow. - pub(crate) activation_location: Option, - /// What kind of borrow this is - pub(crate) kind: mir::BorrowKind, - /// The region for which this borrow is live - pub(crate) region: Region<'tcx>, - /// Place from which we are borrowing - pub(crate) borrowed_place: mir::Place<'tcx>, - /// Place to which the borrow was stored - pub(crate) assigned_place: mir::Place<'tcx>, -} - -impl<'tcx> fmt::Display for BorrowData<'tcx> { - fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { - let kind = match self.kind { - mir::BorrowKind::Shared => "", - mir::BorrowKind::Unique => "uniq ", - mir::BorrowKind::Mut { .. } => "mut ", - }; - let region = format!("{}", self.region); - let region = if region.len() > 0 { format!("{} ", region) } else { region }; - write!(w, "&{}{}{:?}", region, kind, self.borrowed_place) - } -} - impl ReserveOrActivateIndex { fn reserved(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new(i.index() * 2) } fn active(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new((i.index() * 2) + 1) } @@ -169,14 +113,16 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { return Borrows { tcx: tcx, mir: mir, - borrows: visitor.idx_vec, + borrow_set: BorrowSet { + borrows: visitor.idx_vec, + location_map: visitor.location_map, + activation_map: visitor.activation_map, + region_map: visitor.region_map, + local_map: visitor.local_map, + region_span_map: visitor.region_span_map, + }, scope_tree, root_scope, - location_map: visitor.location_map, - activation_map: visitor.activation_map, - region_map: visitor.region_map, - local_map: visitor.local_map, - region_span_map: visitor.region_span_map, nonlexical_regioncx }; struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> { @@ -514,7 +460,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { match self.nonlexical_regioncx { Some(_) => None, None => { - match self.region_span_map.get(region) { + match self.borrow_set.region_span_map.get(region) { Some(span) => Some(self.tcx.sess.codemap().end_point(*span)), None => Some(self.tcx.sess.codemap().end_point(self.mir.span)) } @@ -522,12 +468,12 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { } } - pub fn borrows(&self) -> &IndexVec> { &self.borrows } + crate fn borrows(&self) -> &IndexVec> { &self.borrow_set.borrows } pub fn scope_tree(&self) -> &Lrc { &self.scope_tree } pub fn location(&self, idx: BorrowIndex) -> &Location { - &self.borrows[idx].reserve_location + &self.borrow_set.borrows[idx].reserve_location } /// Add all borrows to the kill set, if those borrows are out of scope at `location`. @@ -548,7 +494,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { // terminator *does* introduce a new loan of the same // region, then setting that gen-bit will override any // potential kill introduced here. - for (borrow_index, borrow_data) in self.borrows.iter_enumerated() { + for (borrow_index, borrow_data) in self.borrow_set.borrows.iter_enumerated() { let borrow_region = borrow_data.region.to_region_vid(); if !regioncx.region_contains_point(borrow_region, location) { sets.kill(&ReserveOrActivateIndex::reserved(borrow_index)); @@ -562,7 +508,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { sets: &mut BlockSets, local: &rustc::mir::Local) { - if let Some(borrow_indexes) = self.local_map.get(local) { + if let Some(borrow_indexes) = self.borrow_set.local_map.get(local) { sets.kill_all(borrow_indexes.iter() .map(|b| ReserveOrActivateIndex::reserved(*b))); sets.kill_all(borrow_indexes.iter() @@ -575,7 +521,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { sets: &mut BlockSets, location: Location) { // Handle activations - match self.activation_map.get(&location) { + match self.borrow_set.activation_map.get(&location) { Some(activations) => { for activated in activations { debug!("activating borrow {:?}", activated); @@ -591,7 +537,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { type Idx = ReserveOrActivateIndex; fn name() -> &'static str { "borrows" } fn bits_per_block(&self) -> usize { - self.borrows.len() * 2 + self.borrow_set.borrows.len() * 2 } fn start_block_effect(&self, _entry_set: &mut IdxSet) { @@ -623,7 +569,9 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { match stmt.kind { // EndRegion kills any borrows (reservations and active borrows both) mir::StatementKind::EndRegion(region_scope) => { - if let Some(borrow_indexes) = self.region_map.get(&ReScope(region_scope)) { + if let Some(borrow_indexes) = + self.borrow_set.region_map.get(&ReScope(region_scope)) + { assert!(self.nonlexical_regioncx.is_none()); for idx in borrow_indexes { sets.kill(&ReserveOrActivateIndex::reserved(*idx)); @@ -650,7 +598,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { if let mir::Rvalue::Ref(region, _, ref place) = *rhs { if is_unsafe_place(self.tcx, self.mir, place) { return; } - let index = self.location_map.get(&location).unwrap_or_else(|| { + let index = self.borrow_set.location_map.get(&location).unwrap_or_else(|| { panic!("could not find BorrowIndex for location {:?}", location); }); @@ -661,7 +609,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { return } - assert!(self.region_map.get(region).unwrap_or_else(|| { + assert!(self.borrow_set.region_map.get(region).unwrap_or_else(|| { panic!("could not find BorrowIndexs for region {:?}", region); }).contains(&index)); sets.gen(&ReserveOrActivateIndex::reserved(*index)); @@ -739,7 +687,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { // and hence most of these loans will already be dead -- but, in some cases // like unwind paths, we do not always emit `EndRegion` statements, so we // add some kills here as a "backup" and to avoid spurious error messages. - for (borrow_index, borrow_data) in self.borrows.iter_enumerated() { + for (borrow_index, borrow_data) in self.borrow_set.borrows.iter_enumerated() { if let ReScope(scope) = borrow_data.region { // Check that the scope is not actually a scope from a function that is // a parent of our closure. Note that the CallSite scope itself is diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 287640439c0e8..72b6f9d54fd66 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -19,6 +19,7 @@ use rustc_data_structures::indexed_set::{IdxSet}; use rustc_data_structures::indexed_vec::Idx; use super::MoveDataParamEnv; + use util::elaborate_drops::DropFlagState; use super::move_paths::{HasMoveData, MoveData, MoveOutIndex, MovePathIndex, InitIndex}; diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 454b6cbd27df1..557799305f9c2 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -29,7 +29,7 @@ pub use self::impls::{MaybeStorageLive}; pub use self::impls::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; pub use self::impls::{DefinitelyInitializedPlaces, MovingOutStatements}; pub use self::impls::EverInitializedPlaces; -pub use self::impls::borrows::{Borrows, BorrowData}; +pub use self::impls::borrows::Borrows; pub use self::impls::HaveBeenBorrowedLocals; pub(crate) use self::impls::borrows::{ReserveOrActivateIndex}; pub use self::at_location::{FlowAtLocation, FlowsAtLocation}; diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs index a701fe3144266..de3063a575673 100644 --- a/src/librustc_mir/lib.rs +++ b/src/librustc_mir/lib.rs @@ -20,6 +20,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment! #![feature(box_patterns)] #![feature(box_syntax)] #![feature(catch_expr)] +#![feature(crate_visibility_modifier)] #![feature(const_fn)] #![feature(core_intrinsics)] #![feature(decl_macro)] From e1123674b1c719e0a5ced078c15a81a22e16dec0 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 6 Apr 2018 15:53:49 -0400 Subject: [PATCH 04/16] extract code to build borrow-set into `borrow_check::borrow_set` Also: - Extract common helper functions into a helper trait. - Kill a bit of dead code. --- src/librustc_mir/borrow_check/borrow_set.rs | 252 +++++++++++- src/librustc_mir/borrow_check/mod.rs | 1 + src/librustc_mir/borrow_check/place_ext.rs | 60 +++ src/librustc_mir/dataflow/impls/borrows.rs | 416 +------------------- 4 files changed, 322 insertions(+), 407 deletions(-) create mode 100644 src/librustc_mir/borrow_check/place_ext.rs diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index 4d541d0ffd229..a25c3afd63c24 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -8,12 +8,16 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use borrow_check::place_ext::PlaceExt; use dataflow::indexes::BorrowIndex; -use rustc::mir::{self, Location}; -use rustc::ty::{Region, RegionKind}; +use rustc::mir::traversal; +use rustc::mir::visit::{PlaceContext, Visitor}; +use rustc::mir::{self, Location, Mir, Place}; +use rustc::ty::{self, Region, RegionKind, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::IndexVec; use std::fmt; +use std::hash::Hash; use syntax_pos::Span; crate struct BorrowSet<'tcx> { @@ -71,8 +75,250 @@ impl<'tcx> fmt::Display for BorrowData<'tcx> { mir::BorrowKind::Mut { .. } => "mut ", }; let region = format!("{}", self.region); - let region = if region.len() > 0 { format!("{} ", region) } else { region }; + let region = if region.len() > 0 { + format!("{} ", region) + } else { + region + }; write!(w, "&{}{}{:?}", region, kind, self.borrowed_place) } } +impl<'tcx> BorrowSet<'tcx> { + pub fn build(tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> Self { + let mut visitor = GatherBorrows { + tcx, + mir, + idx_vec: IndexVec::new(), + location_map: FxHashMap(), + activation_map: FxHashMap(), + region_map: FxHashMap(), + local_map: FxHashMap(), + region_span_map: FxHashMap(), + pending_activations: FxHashMap(), + }; + + for (block, block_data) in traversal::preorder(mir) { + visitor.visit_basic_block_data(block, block_data); + } + + // Double check: We should have found an activation for every pending + // activation. + assert_eq!( + visitor + .pending_activations + .iter() + .find(|&(_local, &borrow_index)| visitor.idx_vec[borrow_index] + .activation_location + .is_none()), + None, + "never found an activation for this borrow!", + ); + + BorrowSet { + borrows: visitor.idx_vec, + location_map: visitor.location_map, + activation_map: visitor.activation_map, + region_map: visitor.region_map, + local_map: visitor.local_map, + region_span_map: visitor.region_span_map, + } + } +} + +struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> { + tcx: TyCtxt<'a, 'gcx, 'tcx>, + mir: &'a Mir<'tcx>, + idx_vec: IndexVec>, + location_map: FxHashMap, + activation_map: FxHashMap>, + region_map: FxHashMap, FxHashSet>, + local_map: FxHashMap>, + region_span_map: FxHashMap, + + /// When we encounter a 2-phase borrow statement, it will always + /// be assigning into a temporary TEMP: + /// + /// TEMP = &foo + /// + /// We add TEMP into this map with `b`, where `b` is the index of + /// the borrow. When we find a later use of this activation, we + /// remove from the map (and add to the "tombstone" set below). + pending_activations: FxHashMap, +} + +impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { + fn visit_assign( + &mut self, + block: mir::BasicBlock, + assigned_place: &mir::Place<'tcx>, + rvalue: &mir::Rvalue<'tcx>, + location: mir::Location, + ) { + if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue { + if borrowed_place.is_unsafe_place(self.tcx, self.mir) { + return; + } + + let borrow = BorrowData { + kind, + region, + reserve_location: location, + activation_location: None, + borrowed_place: borrowed_place.clone(), + assigned_place: assigned_place.clone(), + }; + let idx = self.idx_vec.push(borrow); + self.location_map.insert(location, idx); + + self.insert_as_pending_if_two_phase(location, &assigned_place, region, kind, idx); + + insert(&mut self.region_map, ®ion, idx); + if let Some(local) = borrowed_place.root_local() { + insert(&mut self.local_map, &local, idx); + } + } + + return self.super_assign(block, assigned_place, rvalue, location); + + fn insert<'a, K, V>(map: &'a mut FxHashMap>, k: &K, v: V) + where + K: Clone + Eq + Hash, + V: Eq + Hash, + { + map.entry(k.clone()).or_insert(FxHashSet()).insert(v); + } + } + + fn visit_place( + &mut self, + place: &mir::Place<'tcx>, + context: PlaceContext<'tcx>, + location: Location, + ) { + self.super_place(place, context, location); + + // We found a use of some temporary TEMP... + if let Place::Local(temp) = place { + // ... check whether we (earlier) saw a 2-phase borrow like + // + // TMP = &mut place + match self.pending_activations.get(temp) { + Some(&borrow_index) => { + let borrow_data = &mut self.idx_vec[borrow_index]; + + // Watch out: the use of TMP in the borrow + // itself doesn't count as an + // activation. =) + if borrow_data.reserve_location == location && context == PlaceContext::Store { + return; + } + + if let Some(other_activation) = borrow_data.activation_location { + span_bug!( + self.mir.source_info(location).span, + "found two activations for 2-phase borrow temporary {:?}: \ + {:?} and {:?}", + temp, + location, + other_activation, + ); + } + + // Otherwise, this is the unique later use + // that we expect. + borrow_data.activation_location = Some(location); + self.activation_map + .entry(location) + .or_insert(FxHashSet()) + .insert(borrow_index); + } + + None => {} + } + } + } + + fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: mir::Location) { + if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue { + // double-check that we already registered a BorrowData for this + + let borrow_index = self.location_map[&location]; + let borrow_data = &self.idx_vec[borrow_index]; + assert_eq!(borrow_data.reserve_location, location); + assert_eq!(borrow_data.kind, kind); + assert_eq!(borrow_data.region, region); + assert_eq!(borrow_data.borrowed_place, *place); + } + + return self.super_rvalue(rvalue, location); + } + + fn visit_statement( + &mut self, + block: mir::BasicBlock, + statement: &mir::Statement<'tcx>, + location: Location, + ) { + if let mir::StatementKind::EndRegion(region_scope) = statement.kind { + self.region_span_map + .insert(ty::ReScope(region_scope), statement.source_info.span); + } + return self.super_statement(block, statement, location); + } +} + +impl<'a, 'gcx, 'tcx> GatherBorrows<'a, 'gcx, 'tcx> { + /// Returns true if the borrow represented by `kind` is + /// allowed to be split into separate Reservation and + /// Activation phases. + fn allow_two_phase_borrow(&self, kind: mir::BorrowKind) -> bool { + self.tcx.two_phase_borrows() + && (kind.allows_two_phase_borrow() + || self.tcx.sess.opts.debugging_opts.two_phase_beyond_autoref) + } + + /// If this is a two-phase borrow, then we will record it + /// as "pending" until we find the activating use. + fn insert_as_pending_if_two_phase( + &mut self, + start_location: Location, + assigned_place: &mir::Place<'tcx>, + region: Region<'tcx>, + kind: mir::BorrowKind, + borrow_index: BorrowIndex, + ) { + debug!( + "Borrows::insert_as_pending_if_two_phase({:?}, {:?}, {:?}, {:?})", + start_location, assigned_place, region, borrow_index, + ); + + if !self.allow_two_phase_borrow(kind) { + debug!(" -> {:?}", start_location); + return; + } + + // When we encounter a 2-phase borrow statement, it will always + // be assigning into a temporary TEMP: + // + // TEMP = &foo + // + // so extract `temp`. + let temp = if let &mir::Place::Local(temp) = assigned_place { + temp + } else { + span_bug!( + self.mir.source_info(start_location).span, + "expected 2-phase borrow to assign to a local, not `{:?}`", + assigned_place, + ); + }; + + // Insert `temp` into the list of pending activations. From + // now on, we'll be on the lookout for a use of it. Note that + // we are guaranteed that this use will come after the + // assignment. + let old_value = self.pending_activations.insert(temp, borrow_index); + assert!(old_value.is_none()); + } +} diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 69044a3c83e75..6efe0c39d07b8 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -54,6 +54,7 @@ use self::MutateMode::{JustWrite, WriteAndRead}; crate mod borrow_set; mod error_reporting; mod flows; +crate mod place_ext; mod prefixes; pub(crate) mod nll; diff --git a/src/librustc_mir/borrow_check/place_ext.rs b/src/librustc_mir/borrow_check/place_ext.rs new file mode 100644 index 0000000000000..f6ffe3c6d2314 --- /dev/null +++ b/src/librustc_mir/borrow_check/place_ext.rs @@ -0,0 +1,60 @@ +// Copyright 2012-2014 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. + +use rustc::hir; +use rustc::mir::ProjectionElem; +use rustc::mir::{Local, Mir, Place}; +use rustc::ty::{self, TyCtxt}; + +/// Extension methods for the `Place` type. +crate trait PlaceExt<'tcx> { + /// True if this is a deref of a raw pointer. + fn is_unsafe_place(&self, tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> bool; + + /// If this is a place like `x.f.g`, returns the local + /// `x`. Returns `None` if this is based in a static. + fn root_local(&self) -> Option; +} + +impl<'tcx> PlaceExt<'tcx> for Place<'tcx> { + fn is_unsafe_place(&self, tcx: TyCtxt<'_, '_, 'tcx>, mir: &Mir<'tcx>) -> bool { + match self { + Place::Local(_) => false, + Place::Static(static_) => { + tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable) + } + Place::Projection(proj) => match proj.elem { + ProjectionElem::Field(..) + | ProjectionElem::Downcast(..) + | ProjectionElem::Subslice { .. } + | ProjectionElem::ConstantIndex { .. } + | ProjectionElem::Index(_) => proj.base.is_unsafe_place(tcx, mir), + ProjectionElem::Deref => { + let ty = proj.base.ty(mir, tcx).to_ty(tcx); + match ty.sty { + ty::TyRawPtr(..) => true, + _ => proj.base.is_unsafe_place(tcx, mir), + } + } + }, + } + } + + fn root_local(&self) -> Option { + let mut p = self; + loop { + match p { + Place::Projection(pi) => p = &pi.base, + Place::Static(_) => return None, + Place::Local(l) => return Some(*l), + } + } + } +} diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 381718234a62f..79f2915e12c0f 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -9,18 +9,16 @@ // except according to those terms. use borrow_check::borrow_set::{BorrowSet, BorrowData}; +use borrow_check::place_ext::PlaceExt; use rustc; use rustc::hir; use rustc::hir::def_id::DefId; use rustc::middle::region; use rustc::mir::{self, Location, Place, Mir}; -use rustc::mir::traversal; -use rustc::mir::visit::{PlaceContext, Visitor}; -use rustc::ty::{self, Region, TyCtxt}; +use rustc::ty::{Region, TyCtxt}; use rustc::ty::RegionKind; use rustc::ty::RegionKind::ReScope; -use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::bitslice::{BitwiseOperator}; use rustc_data_structures::indexed_set::{IdxSet}; @@ -34,7 +32,6 @@ use borrow_check::nll::ToRegionVid; use syntax_pos::Span; -use std::hash::Hash; use std::rc::Rc; /// `Borrows` stores the data used in the analyses that track the flow @@ -82,373 +79,15 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { let root_scope = body_id.map(|body_id| { region::Scope::CallSite(tcx.hir.body(body_id).value.hir_id.local_id) }); - let mut visitor = GatherBorrows { - tcx, - mir, - idx_vec: IndexVec::new(), - location_map: FxHashMap(), - activation_map: FxHashMap(), - region_map: FxHashMap(), - local_map: FxHashMap(), - region_span_map: FxHashMap(), - nonlexical_regioncx: nonlexical_regioncx.clone(), - pending_activations: FxHashMap(), - }; - for (block, block_data) in traversal::preorder(mir) { - visitor.visit_basic_block_data(block, block_data); - } - - // Double check: We should have found an activation for every pending - // activation. - assert_eq!( - visitor - .pending_activations - .iter() - .find(|&(_local, &borrow_index)| { - visitor.idx_vec[borrow_index].activation_location.is_none() - }), - None, - "never found an activation for this borrow!", - ); - - return Borrows { tcx: tcx, - mir: mir, - borrow_set: BorrowSet { - borrows: visitor.idx_vec, - location_map: visitor.location_map, - activation_map: visitor.activation_map, - region_map: visitor.region_map, - local_map: visitor.local_map, - region_span_map: visitor.region_span_map, - }, - scope_tree, - root_scope, - nonlexical_regioncx }; - - struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> { - tcx: TyCtxt<'a, 'gcx, 'tcx>, - mir: &'a Mir<'tcx>, - idx_vec: IndexVec>, - location_map: FxHashMap, - activation_map: FxHashMap>, - region_map: FxHashMap, FxHashSet>, - local_map: FxHashMap>, - region_span_map: FxHashMap, - nonlexical_regioncx: Option>>, - - /// When we encounter a 2-phase borrow statement, it will always - /// be assigning into a temporary TEMP: - /// - /// TEMP = &foo - /// - /// We add TEMP into this map with `b`, where `b` is the index of - /// the borrow. When we find a later use of this activation, we - /// remove from the map (and add to the "tombstone" set below). - pending_activations: FxHashMap, - } - - impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { - fn visit_assign(&mut self, - block: mir::BasicBlock, - assigned_place: &mir::Place<'tcx>, - rvalue: &mir::Rvalue<'tcx>, - location: mir::Location) { - fn root_local(mut p: &mir::Place<'_>) -> Option { - loop { match p { - mir::Place::Projection(pi) => p = &pi.base, - mir::Place::Static(_) => return None, - mir::Place::Local(l) => return Some(*l) - }} - } - - if let mir::Rvalue::Ref(region, kind, ref borrowed_place) = *rvalue { - if is_unsafe_place(self.tcx, self.mir, borrowed_place) { return; } - - let borrow = BorrowData { - kind, - region, - reserve_location: location, - activation_location: None, - borrowed_place: borrowed_place.clone(), - assigned_place: assigned_place.clone(), - }; - let idx = self.idx_vec.push(borrow); - self.location_map.insert(location, idx); - - self.insert_as_pending_if_two_phase( - location, - &assigned_place, - region, - kind, - idx, - ); - - insert(&mut self.region_map, ®ion, idx); - if let Some(local) = root_local(borrowed_place) { - insert(&mut self.local_map, &local, idx); - } - } - - return self.super_assign(block, assigned_place, rvalue, location); - - fn insert<'a, K, V>(map: &'a mut FxHashMap>, - k: &K, - v: V) - where K: Clone+Eq+Hash, V: Eq+Hash - { - map.entry(k.clone()) - .or_insert(FxHashSet()) - .insert(v); - } - } - - fn visit_place( - &mut self, - place: &mir::Place<'tcx>, - context: PlaceContext<'tcx>, - location: Location, - ) { - self.super_place(place, context, location); - - // We found a use of some temporary TEMP... - if let Place::Local(temp) = place { - // ... check whether we (earlier) saw a 2-phase borrow like - // - // TMP = &mut place - match self.pending_activations.get(temp) { - Some(&borrow_index) => { - let borrow_data = &mut self.idx_vec[borrow_index]; - - // Watch out: the use of TMP in the borrow - // itself doesn't count as an - // activation. =) - if borrow_data.reserve_location == location - && context == PlaceContext::Store - { - return; - } - - if let Some(other_activation) = borrow_data.activation_location { - span_bug!( - self.mir.source_info(location).span, - "found two activations for 2-phase borrow temporary {:?}: \ - {:?} and {:?}", - temp, - location, - other_activation, - ); - } - - // Otherwise, this is the unique later use - // that we expect. - borrow_data.activation_location = Some(location); - self.activation_map - .entry(location) - .or_insert(FxHashSet()) - .insert(borrow_index); - } - - None => {} - } - } - } - - fn visit_rvalue(&mut self, - rvalue: &mir::Rvalue<'tcx>, - location: mir::Location) { - if let mir::Rvalue::Ref(region, kind, ref place) = *rvalue { - // double-check that we already registered a BorrowData for this - - let borrow_index = self.location_map[&location]; - let borrow_data = &self.idx_vec[borrow_index]; - assert_eq!(borrow_data.reserve_location, location); - assert_eq!(borrow_data.kind, kind); - assert_eq!(borrow_data.region, region); - assert_eq!(borrow_data.borrowed_place, *place); - } - - return self.super_rvalue(rvalue, location); - } - - fn visit_statement(&mut self, - block: mir::BasicBlock, - statement: &mir::Statement<'tcx>, - location: Location) { - if let mir::StatementKind::EndRegion(region_scope) = statement.kind { - self.region_span_map.insert(ReScope(region_scope), statement.source_info.span); - } - return self.super_statement(block, statement, location); - } - } - - /// A MIR visitor that determines if a specific place is used in a two-phase activating - /// manner in a given chunk of MIR. - struct ContainsUseOfPlace<'b, 'tcx: 'b> { - target: &'b Place<'tcx>, - use_found: bool, - } - - impl<'b, 'tcx: 'b> ContainsUseOfPlace<'b, 'tcx> { - fn new(place: &'b Place<'tcx>) -> Self { - Self { target: place, use_found: false } - } - - /// return whether `context` should be considered a "use" of a - /// place found in that context. "Uses" activate associated - /// borrows (at least when such uses occur while the borrow also - /// has a reservation at the time). - fn is_potential_use(context: PlaceContext) -> bool { - match context { - // storage effects on a place do not activate it - PlaceContext::StorageLive | PlaceContext::StorageDead => false, - - // validation effects do not activate a place - // - // FIXME: Should they? Is it just another read? Or can we - // guarantee it won't dereference the stored address? How - // "deep" does validation go? - PlaceContext::Validate => false, - - // FIXME: This is here to not change behaviour from before - // AsmOutput existed, but it's not necessarily a pure overwrite. - // so it's possible this should activate the place. - PlaceContext::AsmOutput | - // pure overwrites of a place do not activate it. (note - // PlaceContext::Call is solely about dest place) - PlaceContext::Store | PlaceContext::Call => false, - - // reads of a place *do* activate it - PlaceContext::Move | - PlaceContext::Copy | - PlaceContext::Drop | - PlaceContext::Inspect | - PlaceContext::Borrow { .. } | - PlaceContext::Projection(..) => true, - } - } - } - - impl<'b, 'tcx: 'b> Visitor<'tcx> for ContainsUseOfPlace<'b, 'tcx> { - fn visit_place(&mut self, - place: &mir::Place<'tcx>, - context: PlaceContext<'tcx>, - location: Location) { - if Self::is_potential_use(context) && place == self.target { - self.use_found = true; - return; - // There is no need to keep checking the statement, we already found a use - } - - self.super_place(place, context, location); - } - } - - impl<'a, 'gcx, 'tcx> GatherBorrows<'a, 'gcx, 'tcx> { - /// Returns true if the borrow represented by `kind` is - /// allowed to be split into separate Reservation and - /// Activation phases. - fn allow_two_phase_borrow(&self, kind: mir::BorrowKind) -> bool { - self.tcx.two_phase_borrows() && - (kind.allows_two_phase_borrow() || - self.tcx.sess.opts.debugging_opts.two_phase_beyond_autoref) - } - - /// Returns true if the given location contains an NLL-activating use of the given place - fn location_contains_use(&self, location: Location, place: &Place) -> bool { - let mut use_checker = ContainsUseOfPlace::new(place); - let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| { - panic!("could not find block at location {:?}", location); - }); - if location.statement_index != block.statements.len() { - // This is a statement - let stmt = block.statements.get(location.statement_index).unwrap_or_else(|| { - panic!("could not find statement at location {:?}"); - }); - use_checker.visit_statement(location.block, stmt, location); - } else { - // This is a terminator - match block.terminator { - Some(ref term) => { - use_checker.visit_terminator(location.block, term, location); - } - None => { - // There is no way for Place to be used by the terminator if there is no - // terminator - } - } - } - - use_checker.use_found - } - - /// Determines if the provided region is terminated after the provided location. - /// EndRegion statements terminate their enclosed region::Scope. - /// We also consult with the NLL region inference engine, should one be available - fn region_terminated_after(&self, region: Region<'tcx>, location: Location) -> bool { - let block_data = &self.mir[location.block]; - if location.statement_index != block_data.statements.len() { - let stmt = &block_data.statements[location.statement_index]; - if let mir::StatementKind::EndRegion(region_scope) = stmt.kind { - if &ReScope(region_scope) == region { - // We encountered an EndRegion statement that terminates the provided - // region - return true; - } - } - } - if let Some(ref regioncx) = self.nonlexical_regioncx { - if !regioncx.region_contains_point(region, location) { - // NLL says the region has ended already - return true; - } - } - - false - } - - /// If this is a two-phase borrow, then we will record it - /// as "pending" until we find the activating use. - fn insert_as_pending_if_two_phase( - &mut self, - start_location: Location, - assigned_place: &mir::Place<'tcx>, - region: Region<'tcx>, - kind: mir::BorrowKind, - borrow_index: BorrowIndex, - ) { - debug!( - "Borrows::insert_as_pending_if_two_phase({:?}, {:?}, {:?}, {:?})", - start_location, assigned_place, region, borrow_index, - ); - - if !self.allow_two_phase_borrow(kind) { - debug!(" -> {:?}", start_location); - return; - } - - // When we encounter a 2-phase borrow statement, it will always - // be assigning into a temporary TEMP: - // - // TEMP = &foo - // - // so extract `temp`. - let temp = if let &mir::Place::Local(temp) = assigned_place { - temp - } else { - span_bug!( - self.mir.source_info(start_location).span, - "expected 2-phase borrow to assign to a local, not `{:?}`", - assigned_place, - ); - }; - - // Insert `temp` into the list of pending activations. From - // now on, we'll be on the lookout for a use of it. Note that - // we are guaranteed that this use will come after the - // assignment. - let old_value = self.pending_activations.insert(temp, borrow_index); - assert!(old_value.is_none()); - } + let borrow_set = BorrowSet::build(tcx, mir); + + Borrows { + tcx: tcx, + mir: mir, + borrow_set, + scope_tree, + root_scope, + nonlexical_regioncx, } } @@ -597,7 +236,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { // propagate_call_return method. if let mir::Rvalue::Ref(region, _, ref place) = *rhs { - if is_unsafe_place(self.tcx, self.mir, place) { return; } + if place.is_unsafe_place(self.tcx, self.mir) { return; } let index = self.borrow_set.location_map.get(&location).unwrap_or_else(|| { panic!("could not find BorrowIndex for location {:?}", location); }); @@ -744,34 +383,3 @@ impl<'a, 'gcx, 'tcx> InitialFlow for Borrows<'a, 'gcx, 'tcx> { } } -fn is_unsafe_place<'a, 'gcx: 'tcx, 'tcx: 'a>( - tcx: TyCtxt<'a, 'gcx, 'tcx>, - mir: &'a Mir<'tcx>, - place: &mir::Place<'tcx> -) -> bool { - use self::mir::Place::*; - use self::mir::ProjectionElem; - - match *place { - Local(_) => false, - Static(ref static_) => tcx.is_static(static_.def_id) == Some(hir::Mutability::MutMutable), - Projection(ref proj) => { - match proj.elem { - ProjectionElem::Field(..) | - ProjectionElem::Downcast(..) | - ProjectionElem::Subslice { .. } | - ProjectionElem::ConstantIndex { .. } | - ProjectionElem::Index(_) => { - is_unsafe_place(tcx, mir, &proj.base) - } - ProjectionElem::Deref => { - let ty = proj.base.ty(mir, tcx).to_ty(tcx); - match ty.sty { - ty::TyRawPtr(..) => true, - _ => is_unsafe_place(tcx, mir, &proj.base), - } - } - } - } - } -} From 5f7b74f832b33280e685dd8b89ef218c27c746e3 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 6 Apr 2018 15:57:21 -0400 Subject: [PATCH 05/16] construct the `BorrowSet` outside of `borrows` --- src/librustc_mir/borrow_check/mod.rs | 6 ++++-- src/librustc_mir/dataflow/impls/borrows.rs | 15 ++++++++------- src/librustc_mir/dataflow/impls/mod.rs | 1 - 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 6efe0c39d07b8..3cc79d947d6bf 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -46,7 +46,7 @@ use util::collect_writes::FindAssignments; use std::iter; -use self::borrow_set::BorrowData; +use self::borrow_set::{BorrowSet, BorrowData}; use self::flows::Flows; use self::prefixes::PrefixSet; use self::MutateMode::{JustWrite, WriteAndRead}; @@ -192,6 +192,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( |bd, i| DebugFormatted::new(&bd.move_data().inits[i]), )); + let borrow_set = BorrowSet::build(tcx, mir); + // If we are in non-lexical mode, compute the non-lexical lifetimes. let (opt_regioncx, opt_closure_req) = if let Some(free_regions) = free_regions { let (regioncx, opt_closure_req) = nll::compute_regions( @@ -216,7 +218,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( id, &attributes, &dead_unwinds, - Borrows::new(tcx, mir, opt_regioncx.clone(), def_id, body_id), + Borrows::new(tcx, mir, opt_regioncx.clone(), def_id, body_id, borrow_set), |rs, i| { DebugFormatted::new(&(i.kind(), rs.location(i.borrow_index()))) } diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 79f2915e12c0f..25f1278d7fa62 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -69,17 +69,18 @@ impl ReserveOrActivateIndex { } impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { - pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>, - mir: &'a Mir<'tcx>, - nonlexical_regioncx: Option>>, - def_id: DefId, - body_id: Option) - -> Self { + crate fn new( + tcx: TyCtxt<'a, 'gcx, 'tcx>, + mir: &'a Mir<'tcx>, + nonlexical_regioncx: Option>>, + def_id: DefId, + body_id: Option, + borrow_set: BorrowSet<'tcx> + ) -> Self { let scope_tree = tcx.region_scope_tree(def_id); let root_scope = body_id.map(|body_id| { region::Scope::CallSite(tcx.hir.body(body_id).value.hir_id.local_id) }); - let borrow_set = BorrowSet::build(tcx, mir); Borrows { tcx: tcx, diff --git a/src/librustc_mir/dataflow/impls/mod.rs b/src/librustc_mir/dataflow/impls/mod.rs index 72b6f9d54fd66..f64fd64b283ea 100644 --- a/src/librustc_mir/dataflow/impls/mod.rs +++ b/src/librustc_mir/dataflow/impls/mod.rs @@ -38,7 +38,6 @@ mod borrowed_locals; pub use self::borrowed_locals::*; -#[allow(dead_code)] pub(super) mod borrows; /// `MaybeInitializedPlaces` tracks all places that might be From 8e783da2228ec256d15bb6af0f7e1053fc1e040e Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 6 Apr 2018 17:03:14 -0400 Subject: [PATCH 06/16] encapsulate ReserveOrActivateIndex into the borrows dataflow --- src/librustc_mir/borrow_check/mod.rs | 26 +++++++++++++------------- src/librustc_mir/dataflow/mod.rs | 1 - 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 3cc79d947d6bf..e4a4360a8051d 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -37,7 +37,7 @@ use dataflow::MoveDataParamEnv; use dataflow::{DataflowResultsConsumer}; use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use dataflow::{EverInitializedPlaces, MovingOutStatements}; -use dataflow::{Borrows, ReserveOrActivateIndex}; +use dataflow::Borrows; use dataflow::indexes::BorrowIndex; use dataflow::move_paths::{IllegalMoveOriginKind, MoveError}; use dataflow::move_paths::{HasMoveData, LookupResult, MoveData, MovePathIndex}; @@ -66,6 +66,8 @@ pub fn provide(providers: &mut Providers) { }; } +struct IsActive(bool); + fn mir_borrowck<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, @@ -846,22 +848,21 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { context, (sd, place_span.0), flow_state, - |this, index, borrow| match (rw, borrow.kind) { + |this, borrow_index, is_active, borrow| match (rw, borrow.kind) { // Obviously an activation is compatible with its own // reservation (or even prior activating uses of same // borrow); so don't check if they interfere. // // NOTE: *reservations* do conflict with themselves; // thus aren't injecting unsoundenss w/ this check.) - (Activation(_, activating), _) if activating == index.borrow_index() => { + (Activation(_, activating), _) if activating == borrow_index => { debug!( "check_access_for_conflict place_span: {:?} sd: {:?} rw: {:?} \ - skipping {:?} b/c activation of same borrow_index: {:?}", + skipping {:?} b/c activation of same borrow_index", place_span, sd, rw, - (index, borrow), - index.borrow_index() + (borrow_index, borrow), ); Control::Continue } @@ -872,7 +873,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { (Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut { .. }) => { // Reading from mere reservations of mutable-borrows is OK. - if this.allow_two_phase_borrow(borrow.kind) && index.is_reservation() { + if this.allow_two_phase_borrow(borrow.kind) && !is_active.0 { return Control::Continue; } @@ -2216,10 +2217,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { /// "Current borrow" here means a borrow that reaches the point in /// the control-flow where the access occurs. /// - /// The borrow's phase is represented by the ReserveOrActivateIndex - /// passed to the callback: one can call `is_reservation()` and - /// `is_activation()` to determine what phase the borrow is - /// currently in, when such distinction matters. + /// The borrow's phase is represented by the IsActive parameter + /// passed to the callback. fn each_borrow_involving_path( &mut self, _context: Context, @@ -2227,7 +2226,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { flow_state: &Flows<'cx, 'gcx, 'tcx>, mut op: F, ) where - F: FnMut(&mut Self, ReserveOrActivateIndex, &BorrowData<'tcx>) -> Control, + F: FnMut(&mut Self, BorrowIndex, IsActive, &BorrowData<'tcx>) -> Control, { let (access, place) = access_place; @@ -2247,7 +2246,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "each_borrow_involving_path: {:?} @ {:?} vs. {:?}/{:?}", i, borrowed, place, access ); - let ctrl = op(self, i, borrowed); + let is_active = IsActive(i.is_activation()); + let ctrl = op(self, i.borrow_index(), is_active, borrowed); if ctrl == Control::Break { return; } diff --git a/src/librustc_mir/dataflow/mod.rs b/src/librustc_mir/dataflow/mod.rs index 557799305f9c2..85458c7d68488 100644 --- a/src/librustc_mir/dataflow/mod.rs +++ b/src/librustc_mir/dataflow/mod.rs @@ -31,7 +31,6 @@ pub use self::impls::{DefinitelyInitializedPlaces, MovingOutStatements}; pub use self::impls::EverInitializedPlaces; pub use self::impls::borrows::Borrows; pub use self::impls::HaveBeenBorrowedLocals; -pub(crate) use self::impls::borrows::{ReserveOrActivateIndex}; pub use self::at_location::{FlowAtLocation, FlowsAtLocation}; pub(crate) use self::drop_flag_effects::*; From f93d5d30bd0d141f7c5acabb5d612897eaf83303 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 6 Apr 2018 18:03:23 -0400 Subject: [PATCH 07/16] add useful debug --- src/librustc_mir/borrow_check/mod.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index e4a4360a8051d..7c5f0b97f7139 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -843,6 +843,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { rw: ReadOrWrite, flow_state: &Flows<'cx, 'gcx, 'tcx>, ) -> bool { + debug!( + "check_access_for_conflict(context={:?}, place_span={:?}, sd={:?}, rw={:?})", + context, + place_span, + sd, + rw, + ); + let mut error_reported = false; self.each_borrow_involving_path( context, From e1f82aa5908911c6ab5db295d5ea279dfb8fc0e2 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 6 Apr 2018 20:48:13 -0400 Subject: [PATCH 08/16] determine whether a borrow is active based solely on the location --- src/librustc/mir/mod.rs | 2 +- src/librustc_mir/borrow_check/mod.rs | 83 +++++++++++++++++-- .../borrowck/two-phase-across-loop.rs | 34 ++++++++ 3 files changed, 111 insertions(+), 8 deletions(-) create mode 100644 src/test/compile-fail/borrowck/two-phase-across-loop.rs diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 33f52ab09c856..c525c4ed651f2 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1991,7 +1991,7 @@ impl Location { Location { block: self.block, statement_index: self.statement_index + 1 } } - pub fn dominates(&self, other: &Location, dominators: &Dominators) -> bool { + pub fn dominates(&self, other: Location, dominators: &Dominators) -> bool { if self.block == other.block { self.statement_index <= other.statement_index } else { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 7c5f0b97f7139..2e64626e2ea40 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -22,6 +22,7 @@ use rustc::mir::{Mir, Mutability, Operand, Projection, ProjectionElem, Rvalue}; use rustc::mir::{Field, Statement, StatementKind, Terminator, TerminatorKind}; use rustc::mir::ClosureRegionRequirements; +use rustc_data_structures::control_flow_graph::dominators::Dominators; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_set::IdxSetBuf; use rustc_data_structures::indexed_vec::Idx; @@ -66,8 +67,6 @@ pub fn provide(providers: &mut Providers) { }; } -struct IsActive(bool); - fn mir_borrowck<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, @@ -234,6 +233,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( _ => false, }; + let dominators = mir.dominators(); + let mut mbcx = MirBorrowckCtxt { tcx: tcx, mir: mir, @@ -250,6 +251,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( moved_error_reported: FxHashSet(), nonlexical_regioncx: opt_regioncx, nonlexical_cause_info: None, + dominators, }; let mut state = Flows::new( @@ -302,6 +304,7 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> { /// find out which CFG points are contained in each borrow region. nonlexical_regioncx: Option>>, nonlexical_cause_info: Option, + dominators: Dominators, } // Check that: @@ -856,7 +859,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { context, (sd, place_span.0), flow_state, - |this, borrow_index, is_active, borrow| match (rw, borrow.kind) { + |this, borrow_index, borrow| match (rw, borrow.kind) { // Obviously an activation is compatible with its own // reservation (or even prior activating uses of same // borrow); so don't check if they interfere. @@ -881,7 +884,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { (Read(kind), BorrowKind::Unique) | (Read(kind), BorrowKind::Mut { .. }) => { // Reading from mere reservations of mutable-borrows is OK. - if this.allow_two_phase_borrow(borrow.kind) && !is_active.0 { + if !this.is_active(borrow, context.loc) { + assert!(this.allow_two_phase_borrow(borrow.kind)); return Control::Continue; } @@ -2234,7 +2238,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { flow_state: &Flows<'cx, 'gcx, 'tcx>, mut op: F, ) where - F: FnMut(&mut Self, BorrowIndex, IsActive, &BorrowData<'tcx>) -> Control, + F: FnMut(&mut Self, BorrowIndex, &BorrowData<'tcx>) -> Control, { let (access, place) = access_place; @@ -2247,6 +2251,13 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // borrows of P, P.a.b, etc. let mut iter_incoming = flow_state.borrows.iter_incoming(); while let Some(i) = iter_incoming.next() { + // TODO -- for now, just skip activations, since + // everywhere that activation is set, reservation should + // be set + if i.is_activation() { + continue; + } + let borrowed = &data[i.borrow_index()]; if self.places_conflict(&borrowed.borrowed_place, place, access) { @@ -2254,14 +2265,72 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "each_borrow_involving_path: {:?} @ {:?} vs. {:?}/{:?}", i, borrowed, place, access ); - let is_active = IsActive(i.is_activation()); - let ctrl = op(self, i.borrow_index(), is_active, borrowed); + let ctrl = op(self, i.borrow_index(), borrowed); if ctrl == Control::Break { return; } } } } + + fn is_active( + &self, + borrow_data: &BorrowData<'tcx>, + location: Location + ) -> bool { + debug!("is_active(borrow_data={:?}, location={:?})", borrow_data, location); + + // If this is not a 2-phase borrow, it is always active. + let activation_location = match borrow_data.activation_location { + Some(v) => v, + None => return true, + }; + + // Otherwise, it is active for every location *except* in between + // the reservation and the activation: + // + // X + // / + // R <--+ Except for this + // / \ | diamond + // \ / | + // A <------+ + // | + // Z + // + // Note that we assume that: + // - the reservation R dominates the activation A + // - the activation A post-dominates the reservation R (ignoring unwinding edges). + // + // This means that there can't be an edge that leaves A and + // comes back into that diamond unless it passes through R. + // + // Suboptimal: In some cases, this code walks the dominator + // tree twice when it only has to be walked once. I am + // lazy. -nmatsakis + + // If dominated by the activation A, then it is active. The + // activation occurs upon entering the point A, so this is + // also true if location == activation_location. + if activation_location.dominates(location, &self.dominators) { + return true; + } + + // The reservation starts *on exiting* the reservation block, + // so check if the location is dominated by R.successor. If so, + // this point falls in between the reservation and location. + let reserve_location = borrow_data.reserve_location.successor_within_block(); + if reserve_location.dominates(location, &self.dominators) { + false + } else { + // Otherwise, this point is outside the diamond, so + // consider the borrow active. This could happen for + // example if the borrow remains active around a loop (in + // which case it would be active also for the point R, + // which would generate an error). + true + } + } } impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { diff --git a/src/test/compile-fail/borrowck/two-phase-across-loop.rs b/src/test/compile-fail/borrowck/two-phase-across-loop.rs new file mode 100644 index 0000000000000..e03a0355b48d6 --- /dev/null +++ b/src/test/compile-fail/borrowck/two-phase-across-loop.rs @@ -0,0 +1,34 @@ +// Copyright 2016 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. + +// Test that a borrow which starts as a 2-phase borrow and gets +// carried around a loop winds up conflicting with itself. + +#![feature(nll)] + +struct Foo { x: String } + +impl Foo { + fn get_string(&mut self) -> &str { + &self.x + } +} + +fn main() { + let mut foo = Foo { x: format!("Hello, world") }; + let mut strings = vec![]; + + loop { + strings.push(foo.get_string()); //~ ERROR cannot borrow `foo` as mutable + if strings.len() > 2 { break; } + } + + println!("{:?}", strings); +} From d32e5aac3d517ae4c8709a3a865260a88316bed2 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 7 Apr 2018 05:43:36 -0400 Subject: [PATCH 09/16] use the `activations_at_location` map to check activations Not gen bits --- src/librustc_mir/borrow_check/borrow_set.rs | 8 +-- src/librustc_mir/borrow_check/mod.rs | 54 +++++++++------------ src/librustc_mir/dataflow/impls/borrows.rs | 7 +++ 3 files changed, 35 insertions(+), 34 deletions(-) diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index a25c3afd63c24..1fae97566d0a5 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -35,7 +35,7 @@ crate struct BorrowSet<'tcx> { /// NOTE: A given location may activate more than one borrow in the future /// when more general two-phase borrow support is introduced, but for now we /// only need to store one borrow index - crate activation_map: FxHashMap>, + crate activation_map: FxHashMap>, /// Every borrow has a region; this maps each such regions back to /// its borrow-indexes. @@ -131,7 +131,7 @@ struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> { mir: &'a Mir<'tcx>, idx_vec: IndexVec>, location_map: FxHashMap, - activation_map: FxHashMap>, + activation_map: FxHashMap>, region_map: FxHashMap, FxHashSet>, local_map: FxHashMap>, region_span_map: FxHashMap, @@ -230,8 +230,8 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { borrow_data.activation_location = Some(location); self.activation_map .entry(location) - .or_insert(FxHashSet()) - .insert(borrow_index); + .or_insert(Vec::new()) + .push(borrow_index); } None => {} diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 2e64626e2ea40..dd76b883d63d2 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -1267,36 +1267,30 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Two-phase borrow support: For each activation that is newly // generated at this statement, check if it interferes with // another borrow. - let domain = flow_state.borrows.operator(); - let data = domain.borrows(); - flow_state.borrows.each_gen_bit(|gen| { - if gen.is_activation() { - let borrow_index = gen.borrow_index(); - let borrow = &data[borrow_index]; - // currently the flow analysis registers - // activations for both mutable and immutable - // borrows. So make sure we are talking about a - // mutable borrow before we check it. - match borrow.kind { - BorrowKind::Shared => return, - BorrowKind::Unique | BorrowKind::Mut { .. } => {} - } - - self.access_place( - ContextKind::Activation.new(location), - (&borrow.borrowed_place, span), - ( - Deep, - Activation(WriteKind::MutableBorrow(borrow.kind), borrow_index), - ), - LocalMutationIsAllowed::No, - flow_state, - ); - // We do not need to call `check_if_path_or_subpath_is_moved` - // again, as we already called it when we made the - // initial reservation. - } - }); + let borrows = flow_state.borrows.operator(); + for &borrow_index in borrows.activations_at_location(location) { + let borrow = &borrows.borrows()[borrow_index]; + + // only mutable borrows should be 2-phase + assert!(match borrow.kind { + BorrowKind::Shared => false, + BorrowKind::Unique | BorrowKind::Mut { .. } => true, + }); + + self.access_place( + ContextKind::Activation.new(location), + (&borrow.borrowed_place, span), + ( + Deep, + Activation(WriteKind::MutableBorrow(borrow.kind), borrow_index), + ), + LocalMutationIsAllowed::No, + flow_state, + ); + // We do not need to call `check_if_path_or_subpath_is_moved` + // again, as we already called it when we made the + // initial reservation. + } } } diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 25f1278d7fa62..190d08e83de4f 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -156,6 +156,13 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { } } + crate fn activations_at_location(&self, location: Location) -> &[BorrowIndex] { + self.borrow_set.activation_map + .get(&location) + .map(|activations| &activations[..]) + .unwrap_or(&[]) + } + /// Performs the activations for a given location fn perform_activations_at_location(&self, sets: &mut BlockSets, From a849da626d8e47265e6a70e1ff24997b935626bd Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 7 Apr 2018 05:53:44 -0400 Subject: [PATCH 10/16] remove `ReserveOrActivateIndex` --- src/librustc_mir/borrow_check/flows.rs | 7 +- src/librustc_mir/borrow_check/mod.rs | 19 ++--- src/librustc_mir/dataflow/impls/borrows.rs | 79 ++++++--------------- src/librustc_mir/dataflow/move_paths/mod.rs | 3 - 4 files changed, 28 insertions(+), 80 deletions(-) diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs index ceff380c594ed..b5cfdee6a454c 100644 --- a/src/librustc_mir/borrow_check/flows.rs +++ b/src/librustc_mir/borrow_check/flows.rs @@ -88,9 +88,8 @@ impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> { s.push_str(", "); }; saw_one = true; - let borrow_data = &self.borrows.operator().borrows()[borrow.borrow_index()]; - s.push_str(&format!("{}{}", borrow_data, - if borrow.is_activation() { "@active" } else { "" })); + let borrow_data = &self.borrows.operator().borrows()[borrow]; + s.push_str(&format!("{}", borrow_data)); }); s.push_str("] "); @@ -101,7 +100,7 @@ impl<'b, 'gcx, 'tcx> fmt::Display for Flows<'b, 'gcx, 'tcx> { s.push_str(", "); }; saw_one = true; - let borrow_data = &self.borrows.operator().borrows()[borrow.borrow_index()]; + let borrow_data = &self.borrows.operator().borrows()[borrow]; s.push_str(&format!("{}", borrow_data)); }); s.push_str("] "); diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index dd76b883d63d2..962356c64010e 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -220,9 +220,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( &attributes, &dead_unwinds, Borrows::new(tcx, mir, opt_regioncx.clone(), def_id, body_id, borrow_set), - |rs, i| { - DebugFormatted::new(&(i.kind(), rs.location(i.borrow_index()))) - } + |rs, i| DebugFormatted::new(&rs.location(i)), )); let movable_generator = !match tcx.hir.get(id) { @@ -549,7 +547,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx let data = domain.borrows(); flow_state.borrows.with_iter_outgoing(|borrows| { for i in borrows { - let borrow = &data[i.borrow_index()]; + let borrow = &data[i]; self.check_for_local_borrow(borrow, span); } }); @@ -565,7 +563,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx let data = domain.borrows(); flow_state.borrows.with_iter_outgoing(|borrows| { for i in borrows { - let borrow = &data[i.borrow_index()]; + let borrow = &data[i]; let context = ContextKind::StorageDead.new(loc); self.check_for_invalidation_at_exit(context, borrow, span, flow_state); } @@ -2245,21 +2243,14 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // borrows of P, P.a.b, etc. let mut iter_incoming = flow_state.borrows.iter_incoming(); while let Some(i) = iter_incoming.next() { - // TODO -- for now, just skip activations, since - // everywhere that activation is set, reservation should - // be set - if i.is_activation() { - continue; - } - - let borrowed = &data[i.borrow_index()]; + let borrowed = &data[i]; if self.places_conflict(&borrowed.borrowed_place, place, access) { debug!( "each_borrow_involving_path: {:?} @ {:?} vs. {:?}/{:?}", i, borrowed, place, access ); - let ctrl = op(self, i.borrow_index(), borrowed); + let ctrl = op(self, i, borrowed); if ctrl == Control::Break { return; } diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 190d08e83de4f..19f5ad5589e88 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -20,13 +20,13 @@ use rustc::ty::{Region, TyCtxt}; use rustc::ty::RegionKind; use rustc::ty::RegionKind::ReScope; -use rustc_data_structures::bitslice::{BitwiseOperator}; -use rustc_data_structures::indexed_set::{IdxSet}; -use rustc_data_structures::indexed_vec::{Idx, IndexVec}; +use rustc_data_structures::bitslice::BitwiseOperator; +use rustc_data_structures::indexed_set::IdxSet; +use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::sync::Lrc; use dataflow::{BitDenotation, BlockSets, InitialFlow}; -pub use dataflow::indexes::{BorrowIndex, ReserveOrActivateIndex}; +pub use dataflow::indexes::BorrowIndex; use borrow_check::nll::region_infer::RegionInferenceContext; use borrow_check::nll::ToRegionVid; @@ -53,21 +53,6 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> { nonlexical_regioncx: Option>>, } -impl ReserveOrActivateIndex { - fn reserved(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new(i.index() * 2) } - fn active(i: BorrowIndex) -> Self { ReserveOrActivateIndex::new((i.index() * 2) + 1) } - - pub(crate) fn is_reservation(self) -> bool { self.index() % 2 == 0 } - pub(crate) fn is_activation(self) -> bool { self.index() % 2 == 1} - - pub(crate) fn kind(self) -> &'static str { - if self.is_reservation() { "reserved" } else { "active" } - } - pub(crate) fn borrow_index(self) -> BorrowIndex { - BorrowIndex::new(self.index() / 2) - } -} - impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { crate fn new( tcx: TyCtxt<'a, 'gcx, 'tcx>, @@ -120,7 +105,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { /// That means either they went out of either a nonlexical scope, if we care about those /// at the moment, or the location represents a lexical EndRegion fn kill_loans_out_of_scope_at_location(&self, - sets: &mut BlockSets, + sets: &mut BlockSets, location: Location) { if let Some(ref regioncx) = self.nonlexical_regioncx { // NOTE: The state associated with a given `location` @@ -137,22 +122,18 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { for (borrow_index, borrow_data) in self.borrow_set.borrows.iter_enumerated() { let borrow_region = borrow_data.region.to_region_vid(); if !regioncx.region_contains_point(borrow_region, location) { - sets.kill(&ReserveOrActivateIndex::reserved(borrow_index)); - sets.kill(&ReserveOrActivateIndex::active(borrow_index)); + sets.kill(&borrow_index); } } } } fn kill_borrows_on_local(&self, - sets: &mut BlockSets, + sets: &mut BlockSets, local: &rustc::mir::Local) { if let Some(borrow_indexes) = self.borrow_set.local_map.get(local) { - sets.kill_all(borrow_indexes.iter() - .map(|b| ReserveOrActivateIndex::reserved(*b))); - sets.kill_all(borrow_indexes.iter() - .map(|b| ReserveOrActivateIndex::active(*b))); + sets.kill_all(borrow_indexes); } } @@ -162,45 +143,29 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { .map(|activations| &activations[..]) .unwrap_or(&[]) } - - /// Performs the activations for a given location - fn perform_activations_at_location(&self, - sets: &mut BlockSets, - location: Location) { - // Handle activations - match self.borrow_set.activation_map.get(&location) { - Some(activations) => { - for activated in activations { - debug!("activating borrow {:?}", activated); - sets.gen(&ReserveOrActivateIndex::active(*activated)) - } - } - None => {} - } - } } impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { - type Idx = ReserveOrActivateIndex; + type Idx = BorrowIndex; fn name() -> &'static str { "borrows" } fn bits_per_block(&self) -> usize { self.borrow_set.borrows.len() * 2 } - fn start_block_effect(&self, _entry_set: &mut IdxSet) { + fn start_block_effect(&self, _entry_set: &mut IdxSet) { // no borrows of code region_scopes have been taken prior to // function execution, so this method has no effect on // `_sets`. } fn before_statement_effect(&self, - sets: &mut BlockSets, + sets: &mut BlockSets, location: Location) { debug!("Borrows::before_statement_effect sets: {:?} location: {:?}", sets, location); self.kill_loans_out_of_scope_at_location(sets, location); } - fn statement_effect(&self, sets: &mut BlockSets, location: Location) { + fn statement_effect(&self, sets: &mut BlockSets, location: Location) { debug!("Borrows::statement_effect sets: {:?} location: {:?}", sets, location); let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| { @@ -210,7 +175,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { panic!("could not find statement at location {:?}"); }); - self.perform_activations_at_location(sets, location); self.kill_loans_out_of_scope_at_location(sets, location); match stmt.kind { @@ -221,8 +185,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { { assert!(self.nonlexical_regioncx.is_none()); for idx in borrow_indexes { - sets.kill(&ReserveOrActivateIndex::reserved(*idx)); - sets.kill(&ReserveOrActivateIndex::active(*idx)); + sets.kill(idx); } } else { // (if there is no entry, then there are no borrows to be tracked) @@ -252,14 +215,14 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { if let RegionKind::ReEmpty = region { // If the borrowed value dies before the borrow is used, the region for // the borrow can be empty. Don't track the borrow in that case. - sets.kill(&ReserveOrActivateIndex::active(*index)); + sets.kill(&index); return } assert!(self.borrow_set.region_map.get(region).unwrap_or_else(|| { panic!("could not find BorrowIndexs for region {:?}", region); }).contains(&index)); - sets.gen(&ReserveOrActivateIndex::reserved(*index)); + sets.gen(&index); // Issue #46746: Two-phase borrows handles // stmts of form `Tmp = &mut Borrow` ... @@ -270,7 +233,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { // e.g. `box (&mut _)`. Current // conservative solution: force // immediate activation here. - sets.gen(&ReserveOrActivateIndex::active(*index)); + sets.gen(&index); } } } @@ -306,13 +269,13 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { } fn before_terminator_effect(&self, - sets: &mut BlockSets, + sets: &mut BlockSets, location: Location) { debug!("Borrows::before_terminator_effect sets: {:?} location: {:?}", sets, location); self.kill_loans_out_of_scope_at_location(sets, location); } - fn terminator_effect(&self, sets: &mut BlockSets, location: Location) { + fn terminator_effect(&self, sets: &mut BlockSets, location: Location) { debug!("Borrows::terminator_effect sets: {:?} location: {:?}", sets, location); let block = &self.mir.basic_blocks().get(location.block).unwrap_or_else(|| { @@ -320,7 +283,6 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { }); let term = block.terminator(); - self.perform_activations_at_location(sets, location); self.kill_loans_out_of_scope_at_location(sets, location); @@ -343,8 +305,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { if *scope != root_scope && self.scope_tree.is_subscope_of(*scope, root_scope) { - sets.kill(&ReserveOrActivateIndex::reserved(borrow_index)); - sets.kill(&ReserveOrActivateIndex::active(borrow_index)); + sets.kill(&borrow_index); } } } @@ -365,7 +326,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { } fn propagate_call_return(&self, - _in_out: &mut IdxSet, + _in_out: &mut IdxSet, _call_bb: mir::BasicBlock, _dest_bb: mir::BasicBlock, _dest_place: &mir::Place) { diff --git a/src/librustc_mir/dataflow/move_paths/mod.rs b/src/librustc_mir/dataflow/move_paths/mod.rs index 9f6cf8c036e19..3a49e28f04187 100644 --- a/src/librustc_mir/dataflow/move_paths/mod.rs +++ b/src/librustc_mir/dataflow/move_paths/mod.rs @@ -65,9 +65,6 @@ pub(crate) mod indexes { /// Index into Borrows.locations new_index!(BorrowIndex, "bw"); - - /// Index into Reservations/Activations bitvector - new_index!(ReserveOrActivateIndex, "ra"); } pub use self::indexes::MovePathIndex; From d4005a2bc9adeb5a19b04bd4354e22e9e75a7072 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 7 Apr 2018 07:11:01 -0400 Subject: [PATCH 11/16] thread borrow-set around more --- src/librustc_mir/borrow_check/mod.rs | 11 ++++++----- src/librustc_mir/borrow_check/nll/mod.rs | 2 ++ src/librustc_mir/dataflow/impls/borrows.rs | 6 +++--- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 962356c64010e..04f4aaf1332e9 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -193,7 +193,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( |bd, i| DebugFormatted::new(&bd.move_data().inits[i]), )); - let borrow_set = BorrowSet::build(tcx, mir); + let borrow_set = Rc::new(BorrowSet::build(tcx, mir)); // If we are in non-lexical mode, compute the non-lexical lifetimes. let (opt_regioncx, opt_closure_req) = if let Some(free_regions) = free_regions { @@ -205,6 +205,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( param_env, &mut flow_inits, &mdpe.move_data, + &borrow_set, ); (Some(Rc::new(regioncx)), opt_closure_req) } else { @@ -219,16 +220,16 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( id, &attributes, &dead_unwinds, - Borrows::new(tcx, mir, opt_regioncx.clone(), def_id, body_id, borrow_set), + Borrows::new(tcx, mir, opt_regioncx.clone(), def_id, body_id, &borrow_set), |rs, i| DebugFormatted::new(&rs.location(i)), )); - let movable_generator = !match tcx.hir.get(id) { + let movable_generator = match tcx.hir.get(id) { hir::map::Node::NodeExpr(&hir::Expr { node: hir::ExprClosure(.., Some(hir::GeneratorMovability::Static)), .. - }) => true, - _ => false, + }) => false, + _ => true, }; let dominators = mir.dominators(); diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index 942e4fb56cabc..3ca1bd23e86ef 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use borrow_check::borrow_set::BorrowSet; use rustc::hir::def_id::DefId; use rustc::mir::{ClosureRegionRequirements, ClosureOutlivesSubject, Mir}; use rustc::infer::InferCtxt; @@ -73,6 +74,7 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( param_env: ty::ParamEnv<'gcx>, flow_inits: &mut FlowAtLocation>, move_data: &MoveData<'tcx>, + _borrow_set: &BorrowSet<'tcx>, ) -> ( RegionInferenceContext<'tcx>, Option>, diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 19f5ad5589e88..b1fa7eeb3a550 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -47,7 +47,7 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> { scope_tree: Lrc, root_scope: Option, - borrow_set: BorrowSet<'tcx>, + borrow_set: Rc>, /// NLL region inference context with which NLL queries should be resolved nonlexical_regioncx: Option>>, @@ -60,7 +60,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { nonlexical_regioncx: Option>>, def_id: DefId, body_id: Option, - borrow_set: BorrowSet<'tcx> + borrow_set: &Rc> ) -> Self { let scope_tree = tcx.region_scope_tree(def_id); let root_scope = body_id.map(|body_id| { @@ -70,7 +70,7 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { Borrows { tcx: tcx, mir: mir, - borrow_set, + borrow_set: borrow_set.clone(), scope_tree, root_scope, nonlexical_regioncx, From df233f0f2c8d5e07e6c13873c5a9f7a2abda9707 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 7 Apr 2018 08:01:21 -0400 Subject: [PATCH 12/16] stop using `borrows` for anything but iterating over live data --- src/librustc_mir/borrow_check/borrow_set.rs | 16 +++++ .../borrow_check/error_reporting.rs | 7 +-- src/librustc_mir/borrow_check/mod.rs | 63 +++++++++++-------- src/librustc_mir/dataflow/impls/borrows.rs | 27 +------- 4 files changed, 56 insertions(+), 57 deletions(-) diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index 1fae97566d0a5..c2d7d68923dd9 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -18,6 +18,7 @@ use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::IndexVec; use std::fmt; use std::hash::Hash; +use std::ops::Index; use syntax_pos::Span; crate struct BorrowSet<'tcx> { @@ -49,6 +50,14 @@ crate struct BorrowSet<'tcx> { crate region_span_map: FxHashMap, } +impl<'tcx> Index for BorrowSet<'tcx> { + type Output = BorrowData<'tcx>; + + fn index(&self, index: BorrowIndex) -> &BorrowData<'tcx> { + &self.borrows[index] + } +} + #[derive(Debug)] crate struct BorrowData<'tcx> { /// Location where the borrow reservation starts. @@ -124,6 +133,13 @@ impl<'tcx> BorrowSet<'tcx> { region_span_map: visitor.region_span_map, } } + + crate fn activations_at_location(&self, location: Location) -> &[BorrowIndex] { + self.activation_map + .get(&location) + .map(|activations| &activations[..]) + .unwrap_or(&[]) + } } struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> { diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 8160a3201dac8..340ff5e178767 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -20,7 +20,7 @@ use super::{Context, MirBorrowckCtxt}; use super::{InitializationRequiringAction, PrefixSet}; use super::borrow_set::BorrowData; -use dataflow::{Borrows, FlowAtLocation, MovingOutStatements}; +use dataflow::{FlowAtLocation, MovingOutStatements}; use dataflow::move_paths::MovePathIndex; use util::borrowck_errors::{BorrowckErrors, Origin}; @@ -391,10 +391,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { context: Context, borrow: &BorrowData<'tcx>, drop_span: Span, - borrows: &Borrows<'cx, 'gcx, 'tcx> ) { - let end_span = borrows.opt_region_end_span(&borrow.region); - let scope_tree = borrows.scope_tree(); + let end_span = self.opt_region_end_span(&borrow.region); + let scope_tree = self.tcx.region_scope_tree(self.mir_def_id); let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All) .last() .unwrap(); diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 04f4aaf1332e9..23682bdee6689 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -29,7 +29,6 @@ use rustc_data_structures::indexed_vec::Idx; use std::rc::Rc; -use syntax::ast; use syntax_pos::Span; use dataflow::{do_dataflow, DebugFormatted}; @@ -237,7 +236,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let mut mbcx = MirBorrowckCtxt { tcx: tcx, mir: mir, - node_id: id, + mir_def_id: def_id, move_data: &mdpe.move_data, param_env: param_env, movable_generator, @@ -250,6 +249,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( moved_error_reported: FxHashSet(), nonlexical_regioncx: opt_regioncx, nonlexical_cause_info: None, + borrow_set, dominators, }; @@ -270,7 +270,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> { tcx: TyCtxt<'cx, 'gcx, 'tcx>, mir: &'cx Mir<'tcx>, - node_id: ast::NodeId, + mir_def_id: DefId, move_data: &'cx MoveData<'tcx>, param_env: ParamEnv<'gcx>, movable_generator: bool, @@ -303,6 +303,11 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> { /// find out which CFG points are contained in each borrow region. nonlexical_regioncx: Option>>, nonlexical_cause_info: Option, + + /// The set of borrows extracted from the MIR + borrow_set: Rc>, + + /// Dominators for MIR dominators: Dominators, } @@ -544,11 +549,10 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx if self.movable_generator { // Look for any active borrows to locals - let domain = flow_state.borrows.operator(); - let data = domain.borrows(); + let borrow_set = self.borrow_set.clone(); flow_state.borrows.with_iter_outgoing(|borrows| { for i in borrows { - let borrow = &data[i]; + let borrow = &borrow_set[i]; self.check_for_local_borrow(borrow, span); } }); @@ -560,13 +564,12 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx // Often, the storage will already have been killed by an explicit // StorageDead, but we don't always emit those (notably on unwind paths), // so this "extra check" serves as a kind of backup. - let domain = flow_state.borrows.operator(); - let data = domain.borrows(); + let borrow_set = self.borrow_set.clone(); flow_state.borrows.with_iter_outgoing(|borrows| { for i in borrows { - let borrow = &data[i]; + let borrow = &borrow_set[i]; let context = ContextKind::StorageDead.new(loc); - self.check_for_invalidation_at_exit(context, borrow, span, flow_state); + self.check_for_invalidation_at_exit(context, borrow, span); } }); } @@ -894,10 +897,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { this.report_use_while_mutably_borrowed(context, place_span, borrow) } ReadKind::Borrow(bk) => { - let end_issued_loan_span = flow_state - .borrows - .operator() - .opt_region_end_span(&borrow.region); + let end_issued_loan_span = this.opt_region_end_span(&borrow.region); error_reported = true; this.report_conflicting_borrow( context, @@ -936,10 +936,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { match kind { WriteKind::MutableBorrow(bk) => { - let end_issued_loan_span = flow_state - .borrows - .operator() - .opt_region_end_span(&borrow.region); + let end_issued_loan_span = this.opt_region_end_span(&borrow.region); error_reported = true; this.report_conflicting_borrow( @@ -956,7 +953,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { context, borrow, place_span.1, - flow_state.borrows.operator(), ); } WriteKind::Mutate => { @@ -1158,7 +1154,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { context: Context, borrow: &BorrowData<'tcx>, span: Span, - flow_state: &Flows<'cx, 'gcx, 'tcx>, ) { debug!("check_for_invalidation_at_exit({:?})", borrow); let place = &borrow.borrowed_place; @@ -1211,7 +1206,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { context, borrow, span, - flow_state.borrows.operator(), ) } } @@ -1266,9 +1260,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // Two-phase borrow support: For each activation that is newly // generated at this statement, check if it interferes with // another borrow. - let borrows = flow_state.borrows.operator(); - for &borrow_index in borrows.activations_at_location(location) { - let borrow = &borrows.borrows()[borrow_index]; + let borrow_set = self.borrow_set.clone(); + for &borrow_index in borrow_set.activations_at_location(location) { + let borrow = &borrow_set[borrow_index]; // only mutable borrows should be 2-phase assert!(match borrow.kind { @@ -1838,6 +1832,22 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _ => None, } } + + /// Returns the span for the "end point" given region. This will + /// return `None` if NLL is enabled, since that concept has no + /// meaning there. Otherwise, return region span if it exists and + /// span for end of the function if it doesn't exist. + pub(crate) fn opt_region_end_span(&self, region: &ty::Region<'tcx>) -> Option { + match self.nonlexical_regioncx { + Some(_) => None, + None => { + match self.borrow_set.region_span_map.get(region) { + Some(span) => Some(self.tcx.sess.codemap().end_point(*span)), + None => Some(self.tcx.sess.codemap().end_point(self.mir.span)) + } + } + } + } } #[derive(Copy, Clone, PartialEq, Eq, Debug)] @@ -2238,13 +2248,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // FIXME: analogous code in check_loans first maps `place` to // its base_path. - let data = flow_state.borrows.operator().borrows(); - // check for loan restricting path P being used. Accounts for // borrows of P, P.a.b, etc. let mut iter_incoming = flow_state.borrows.iter_incoming(); + let borrow_set = self.borrow_set.clone(); while let Some(i) = iter_incoming.next() { - let borrowed = &data[i]; + let borrowed = &borrow_set[i]; if self.places_conflict(&borrowed.borrowed_place, place, access) { debug!( diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index b1fa7eeb3a550..55c38dc89f636 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -16,7 +16,7 @@ use rustc::hir; use rustc::hir::def_id::DefId; use rustc::middle::region; use rustc::mir::{self, Location, Place, Mir}; -use rustc::ty::{Region, TyCtxt}; +use rustc::ty::TyCtxt; use rustc::ty::RegionKind; use rustc::ty::RegionKind::ReScope; @@ -30,8 +30,6 @@ pub use dataflow::indexes::BorrowIndex; use borrow_check::nll::region_infer::RegionInferenceContext; use borrow_check::nll::ToRegionVid; -use syntax_pos::Span; - use std::rc::Rc; /// `Borrows` stores the data used in the analyses that track the flow @@ -77,22 +75,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { } } - /// Returns the span for the "end point" given region. This will - /// return `None` if NLL is enabled, since that concept has no - /// meaning there. Otherwise, return region span if it exists and - /// span for end of the function if it doesn't exist. - pub(crate) fn opt_region_end_span(&self, region: &Region) -> Option { - match self.nonlexical_regioncx { - Some(_) => None, - None => { - match self.borrow_set.region_span_map.get(region) { - Some(span) => Some(self.tcx.sess.codemap().end_point(*span)), - None => Some(self.tcx.sess.codemap().end_point(self.mir.span)) - } - } - } - } - crate fn borrows(&self) -> &IndexVec> { &self.borrow_set.borrows } pub fn scope_tree(&self) -> &Lrc { &self.scope_tree } @@ -136,13 +118,6 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { sets.kill_all(borrow_indexes); } } - - crate fn activations_at_location(&self, location: Location) -> &[BorrowIndex] { - self.borrow_set.activation_map - .get(&location) - .map(|activations| &activations[..]) - .unwrap_or(&[]) - } } impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { From 033c4f2e3c43999e47f543f569dad181ec590b22 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 7 Apr 2018 08:08:27 -0400 Subject: [PATCH 13/16] just use an iterator --- src/librustc_mir/borrow_check/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 23682bdee6689..40af0c0b18d0c 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -2250,9 +2250,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // check for loan restricting path P being used. Accounts for // borrows of P, P.a.b, etc. - let mut iter_incoming = flow_state.borrows.iter_incoming(); let borrow_set = self.borrow_set.clone(); - while let Some(i) = iter_incoming.next() { + for i in flow_state.borrows.iter_incoming() { let borrowed = &borrow_set[i]; if self.places_conflict(&borrowed.borrowed_place, place, access) { From 818ae6feceb4282193800c7e3668d3dfd2912378 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 7 Apr 2018 08:20:24 -0400 Subject: [PATCH 14/16] don't expose the `borrows` field --- src/librustc_mir/borrow_check/flows.rs | 16 +++++++++++++--- src/librustc_mir/borrow_check/mod.rs | 13 ++++++------- 2 files changed, 19 insertions(+), 10 deletions(-) diff --git a/src/librustc_mir/borrow_check/flows.rs b/src/librustc_mir/borrow_check/flows.rs index b5cfdee6a454c..070dc1d09bf6b 100644 --- a/src/librustc_mir/borrow_check/flows.rs +++ b/src/librustc_mir/borrow_check/flows.rs @@ -14,17 +14,19 @@ //! but is not as ugly as it is right now. use rustc::mir::{BasicBlock, Location}; +use rustc_data_structures::indexed_set::Iter; use dataflow::{MaybeInitializedPlaces, MaybeUninitializedPlaces}; use dataflow::{EverInitializedPlaces, MovingOutStatements}; use dataflow::{Borrows}; use dataflow::{FlowAtLocation, FlowsAtLocation}; use dataflow::move_paths::HasMoveData; +use dataflow::move_paths::indexes::BorrowIndex; use std::fmt; // (forced to be `pub` due to its use as an associated type below.) -pub(crate) struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> { - pub borrows: FlowAtLocation>, +crate struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> { + borrows: FlowAtLocation>, pub inits: FlowAtLocation>, pub uninits: FlowAtLocation>, pub move_outs: FlowAtLocation>, @@ -32,7 +34,7 @@ pub(crate) struct Flows<'b, 'gcx: 'tcx, 'tcx: 'b> { } impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> { - pub fn new( + crate fn new( borrows: FlowAtLocation>, inits: FlowAtLocation>, uninits: FlowAtLocation>, @@ -47,6 +49,14 @@ impl<'b, 'gcx, 'tcx> Flows<'b, 'gcx, 'tcx> { ever_inits, } } + + crate fn borrows_in_scope(&self) -> impl Iterator + '_ { + self.borrows.iter_incoming() + } + + crate fn with_outgoing_borrows(&self, op: impl FnOnce(Iter)) { + self.borrows.with_iter_outgoing(op) + } } macro_rules! each_flow { diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 40af0c0b18d0c..5b4c66bd65c17 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -550,7 +550,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx if self.movable_generator { // Look for any active borrows to locals let borrow_set = self.borrow_set.clone(); - flow_state.borrows.with_iter_outgoing(|borrows| { + flow_state.with_outgoing_borrows(|borrows| { for i in borrows { let borrow = &borrow_set[i]; self.check_for_local_borrow(borrow, span); @@ -565,7 +565,7 @@ impl<'cx, 'gcx, 'tcx> DataflowResultsConsumer<'cx, 'tcx> for MirBorrowckCtxt<'cx // StorageDead, but we don't always emit those (notably on unwind paths), // so this "extra check" serves as a kind of backup. let borrow_set = self.borrow_set.clone(); - flow_state.borrows.with_iter_outgoing(|borrows| { + flow_state.with_outgoing_borrows(|borrows| { for i in borrows { let borrow = &borrow_set[i]; let context = ContextKind::StorageDead.new(loc); @@ -2224,10 +2224,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { unreachable!("iter::repeat returned None") } - /// This function iterates over all of the current borrows - /// (represented by 1-bits in `flow_state.borrows`) that conflict - /// with an access to a place, invoking the `op` callback for each - /// one. + /// This function iterates over all of the in-scope borrows that + /// conflict with an access to a place, invoking the `op` callback + /// for each one. /// /// "Current borrow" here means a borrow that reaches the point in /// the control-flow where the access occurs. @@ -2251,7 +2250,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { // check for loan restricting path P being used. Accounts for // borrows of P, P.a.b, etc. let borrow_set = self.borrow_set.clone(); - for i in flow_state.borrows.iter_incoming() { + for i in flow_state.borrows_in_scope() { let borrowed = &borrow_set[i]; if self.places_conflict(&borrowed.borrowed_place, place, access) { From 45d281d7fad8aad28b3193835b93b779634ffb80 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 9 Apr 2018 05:28:00 -0400 Subject: [PATCH 15/16] remove -Znll -- borrowck=mir implies nll now --- src/librustc/infer/error_reporting/mod.rs | 8 +- src/librustc/session/config.rs | 2 - src/librustc/ty/context.rs | 10 +- src/librustc_mir/borrow_check/borrow_set.rs | 14 +-- .../borrow_check/error_reporting.rs | 48 +------ src/librustc_mir/borrow_check/mod.rs | 72 +++-------- .../borrow_check/nll/explain_borrow/mod.rs | 117 +++++++++--------- .../borrow_check/nll/type_check/mod.rs | 2 +- src/librustc_mir/dataflow/impls/borrows.rs | 51 +++----- src/test/compile-fail/E0501.rs | 6 +- .../compile-fail/borrowck/borrowck-asm.rs | 2 +- .../borrowck/borrowck-closures-mut-and-imm.rs | 10 +- .../borrowck/borrowck-describe-lvalue.rs | 64 ++++++---- ...k-imm-ref-to-mut-rec-field-issue-3162-c.rs | 8 +- .../borrowck/borrowck-lend-flow-match.rs | 5 +- .../borrowck-match-already-borrowed.rs | 4 +- .../borrowck-mut-borrow-linear-errors.rs | 8 +- .../borrowck-overloaded-index-ref-index.rs | 1 + .../borrowck/borrowck-pat-reassign-binding.rs | 3 +- .../borrowck/borrowck-union-borrow.rs | 16 +++ ...o-phase-activation-sharing-interference.rs | 5 +- ...o-phase-allow-access-during-reservation.rs | 11 +- .../two-phase-cannot-nest-mut-self-calls.rs | 7 +- .../borrowck/two-phase-nonrecv-autoref.rs | 62 ++++------ ...hase-reservation-sharing-interference-2.rs | 7 +- ...-phase-reservation-sharing-interference.rs | 13 +- .../compile-fail/borrowck/two-phase-sneaky.rs | 7 +- .../coerce-overloaded-autoderef.rs | 2 + .../compile-fail/hrtb-identity-fn-borrows.rs | 1 + src/test/compile-fail/issue-36082.rs | 7 +- .../compile-fail/mir_check_cast_closure.rs | 4 +- src/test/compile-fail/mir_check_cast_reify.rs | 4 +- .../compile-fail/mir_check_cast_unsafe_fn.rs | 4 +- .../compile-fail/mir_check_cast_unsize.rs | 4 +- .../mut-pattern-internal-mutability.rs | 3 +- .../nll/loan_ends_mid_block_pair.rs | 2 +- .../nll/loan_ends_mid_block_vec.rs | 2 +- .../reference-carried-through-struct-field.rs | 2 +- .../nll/region-ends-after-if-condition.rs | 2 +- src/test/compile-fail/nll/return_from_loop.rs | 2 +- .../nll/where_clauses_in_functions.rs | 4 +- .../nll/where_clauses_in_structs.rs | 4 +- .../regions-pattern-typing-issue-19997.rs | 3 +- src/test/compile-fail/regions-static-bound.rs | 8 +- .../mir-opt/nll/liveness-call-subtlety.rs | 2 +- .../mir-opt/nll/liveness-drop-intra-block.rs | 2 +- src/test/mir-opt/nll/liveness-interblock.rs | 2 +- src/test/mir-opt/nll/named-lifetimes-basic.rs | 4 +- src/test/mir-opt/nll/reborrow-basic.rs | 4 +- src/test/mir-opt/nll/region-liveness-basic.rs | 4 +- .../nll/region-liveness-two-disjoint-uses.rs | 4 +- .../mir-opt/nll/region-subtyping-basic.rs | 4 +- .../run-pass/borrowck/two-phase-baseline.rs | 4 +- .../run-pass/impl-trait/example-calendar.rs | 2 +- .../ui/borrowck/borrowck-closures-two-mut.rs | 5 + .../borrowck/borrowck-closures-two-mut.stderr | 42 +++---- .../ui/borrowck/two-phase-method-receivers.rs | 4 +- .../two-phase-multiple-activations.rs | 4 +- src/test/ui/issue-45697-1.rs | 1 + src/test/ui/issue-45697-1.stderr | 16 ++- src/test/ui/issue-45697.rs | 1 + src/test/ui/issue-45697.stderr | 16 ++- src/test/ui/issue-46471-1.stderr | 17 +-- .../escape-argument-callee.rs | 4 +- .../escape-argument-callee.stderr | 2 +- .../closure-requirements/escape-argument.rs | 2 +- .../escape-upvar-nested.rs | 2 +- .../closure-requirements/escape-upvar-ref.rs | 2 +- .../propagate-approximated-fail-no-postdom.rs | 4 +- ...pagate-approximated-fail-no-postdom.stderr | 4 +- .../propagate-approximated-ref.rs | 4 +- .../propagate-approximated-ref.stderr | 6 +- ...horter-to-static-comparing-against-free.rs | 4 +- ...er-to-static-comparing-against-free.stderr | 4 +- ...approximated-shorter-to-static-no-bound.rs | 4 +- ...oximated-shorter-to-static-no-bound.stderr | 8 +- ...roximated-shorter-to-static-wrong-bound.rs | 4 +- ...mated-shorter-to-static-wrong-bound.stderr | 6 +- .../propagate-approximated-val.rs | 4 +- .../propagate-approximated-val.stderr | 6 +- .../propagate-despite-same-free-region.rs | 2 +- .../propagate-despite-same-free-region.stderr | 2 +- ...te-fail-to-approximate-longer-no-bounds.rs | 4 +- ...ail-to-approximate-longer-no-bounds.stderr | 4 +- ...fail-to-approximate-longer-wrong-bounds.rs | 4 +- ...-to-approximate-longer-wrong-bounds.stderr | 4 +- .../propagate-from-trait-match.rs | 4 +- .../propagate-from-trait-match.stderr | 6 +- ...region-lbr-anon-does-not-outlive-static.rs | 4 +- ...on-lbr-anon-does-not-outlive-static.stderr | 2 +- ...egion-lbr-named-does-not-outlive-static.rs | 4 +- ...n-lbr-named-does-not-outlive-static.stderr | 2 +- .../region-lbr1-does-not-outlive-ebr2.rs | 4 +- .../region-lbr1-does-not-outlive-ebr2.stderr | 2 +- ...does-outlive-lbr2-because-implied-bound.rs | 2 +- .../return-wrong-bound-region.rs | 4 +- .../return-wrong-bound-region.stderr | 4 +- src/test/ui/nll/constant.rs | 2 +- src/test/ui/nll/drop-may-dangle.rs | 2 +- src/test/ui/nll/drop-no-may-dangle.rs | 2 +- src/test/ui/nll/get_default.rs | 2 +- ...initialized-drop-implicit-fragment-drop.rs | 2 +- .../maybe-initialized-drop-uninitialized.rs | 2 +- .../maybe-initialized-drop-with-fragment.rs | 2 +- ...lized-drop-with-uninitialized-fragments.rs | 2 +- src/test/ui/nll/maybe-initialized-drop.rs | 2 +- src/test/ui/nll/projection-return.rs | 2 +- .../ui/nll/ty-outlives/impl-trait-captures.rs | 4 +- .../ty-outlives/impl-trait-captures.stderr | 2 +- .../ui/nll/ty-outlives/impl-trait-outlives.rs | 6 +- .../ty-outlives/impl-trait-outlives.stderr | 4 +- .../ty-outlives/projection-implied-bounds.rs | 4 +- .../projection-implied-bounds.stderr | 2 +- .../projection-no-regions-closure.rs | 6 +- .../projection-no-regions-closure.stderr | 4 +- .../ty-outlives/projection-no-regions-fn.rs | 6 +- .../projection-no-regions-fn.stderr | 4 +- .../projection-one-region-closure.rs | 8 +- .../projection-one-region-closure.stderr | 6 +- ...ojection-one-region-trait-bound-closure.rs | 8 +- ...tion-one-region-trait-bound-closure.stderr | 6 +- ...n-one-region-trait-bound-static-closure.rs | 2 +- ...ojection-two-region-trait-bound-closure.rs | 10 +- ...tion-two-region-trait-bound-closure.stderr | 8 +- ...y-param-closure-approximate-lower-bound.rs | 2 +- ...ram-closure-approximate-lower-bound.stderr | 6 +- ...param-closure-outlives-from-return-type.rs | 6 +- ...m-closure-outlives-from-return-type.stderr | 4 +- ...aram-closure-outlives-from-where-clause.rs | 6 +- ...-closure-outlives-from-where-clause.stderr | 12 +- .../ui/nll/ty-outlives/ty-param-fn-body.rs | 4 +- .../nll/ty-outlives/ty-param-fn-body.stderr | 2 +- src/test/ui/nll/ty-outlives/ty-param-fn.rs | 6 +- .../ui/nll/ty-outlives/ty-param-fn.stderr | 4 +- .../ty-outlives/ty-param-implied-bounds.rs | 2 +- src/tools/compiletest/src/runtest.rs | 2 +- 136 files changed, 508 insertions(+), 545 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 8d314e251972d..254fba095e236 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -303,7 +303,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ) { debug!("report_region_errors(): {} errors to start", errors.len()); - if will_later_be_reported_by_nll && self.tcx.nll() { + if will_later_be_reported_by_nll && self.tcx.use_mir() { // With `#![feature(nll)]`, we want to present a nice user // experience, so don't even mention the errors from the // AST checker. @@ -311,20 +311,20 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { return; } - // But with -Znll, it's nice to have some note for later. + // But with nll, it's nice to have some note for later. for error in errors { match *error { RegionResolutionError::ConcreteFailure(ref origin, ..) | RegionResolutionError::GenericBoundFailure(ref origin, ..) => { self.tcx .sess - .span_warn(origin.span(), "not reporting region error due to -Znll"); + .span_warn(origin.span(), "not reporting region error due to nll"); } RegionResolutionError::SubSupConflict(ref rvo, ..) => { self.tcx .sess - .span_warn(rvo.span(), "not reporting region error due to -Znll"); + .span_warn(rvo.span(), "not reporting region error due to nll"); } } } diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index d309026212bfa..9c59cdffed3c2 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1255,8 +1255,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, useful for profiling / PGO."), relro_level: Option = (None, parse_relro_level, [TRACKED], "choose which RELRO level to use"), - nll: bool = (false, parse_bool, [UNTRACKED], - "run the non-lexical lifetimes MIR pass"), disable_nll_user_type_assert: bool = (false, parse_bool, [UNTRACKED], "disable user provided type assertion in NLL"), trans_time_graph: bool = (false, parse_bool, [UNTRACKED], diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index a508f33db3f77..c4a34b4101aeb 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1471,12 +1471,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { self.on_disk_query_result_cache.serialize(self.global_tcx(), encoder) } - /// If true, we should use NLL-style region checking instead of - /// lexical style. - pub fn nll(self) -> bool { - self.features().nll || self.sess.opts.debugging_opts.nll - } - /// If true, we should use the MIR-based borrowck (we may *also* use /// the AST-based borrowck). pub fn use_mir(self) -> bool { @@ -1498,7 +1492,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { mode @ BorrowckMode::Compare => mode, mode @ BorrowckMode::Ast => { - if self.nll() { + if self.features().nll { BorrowckMode::Mir } else { mode @@ -1512,8 +1506,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// MIR borrowck, but not when NLL is used. They are also consumed /// by the validation stuff. pub fn emit_end_regions(self) -> bool { - // FIXME(#46875) -- we should not emit end regions when NLL is enabled, - // but for now we can't stop doing so because it causes false positives self.sess.opts.debugging_opts.emit_end_regions || self.sess.opts.debugging_opts.mir_emit_validate > 0 || self.use_mir() diff --git a/src/librustc_mir/borrow_check/borrow_set.rs b/src/librustc_mir/borrow_check/borrow_set.rs index c2d7d68923dd9..ccfb44a8b58fb 100644 --- a/src/librustc_mir/borrow_check/borrow_set.rs +++ b/src/librustc_mir/borrow_check/borrow_set.rs @@ -13,13 +13,12 @@ use dataflow::indexes::BorrowIndex; use rustc::mir::traversal; use rustc::mir::visit::{PlaceContext, Visitor}; use rustc::mir::{self, Location, Mir, Place}; -use rustc::ty::{self, Region, RegionKind, TyCtxt}; +use rustc::ty::{Region, TyCtxt}; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::IndexVec; use std::fmt; use std::hash::Hash; use std::ops::Index; -use syntax_pos::Span; crate struct BorrowSet<'tcx> { /// The fundamental map relating bitvector indexes to the borrows @@ -44,10 +43,6 @@ crate struct BorrowSet<'tcx> { /// Map from local to all the borrows on that local crate local_map: FxHashMap>, - - /// Maps regions to their corresponding source spans - /// Only contains ReScope()s as keys - crate region_span_map: FxHashMap, } impl<'tcx> Index for BorrowSet<'tcx> { @@ -103,7 +98,6 @@ impl<'tcx> BorrowSet<'tcx> { activation_map: FxHashMap(), region_map: FxHashMap(), local_map: FxHashMap(), - region_span_map: FxHashMap(), pending_activations: FxHashMap(), }; @@ -130,7 +124,6 @@ impl<'tcx> BorrowSet<'tcx> { activation_map: visitor.activation_map, region_map: visitor.region_map, local_map: visitor.local_map, - region_span_map: visitor.region_span_map, } } @@ -150,7 +143,6 @@ struct GatherBorrows<'a, 'gcx: 'tcx, 'tcx: 'a> { activation_map: FxHashMap>, region_map: FxHashMap, FxHashSet>, local_map: FxHashMap>, - region_span_map: FxHashMap, /// When we encounter a 2-phase borrow statement, it will always /// be assigning into a temporary TEMP: @@ -276,10 +268,6 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for GatherBorrows<'a, 'gcx, 'tcx> { statement: &mir::Statement<'tcx>, location: Location, ) { - if let mir::StatementKind::EndRegion(region_scope) = statement.kind { - self.region_span_map - .insert(ty::ReScope(region_scope), statement.source_info.span); - } return self.super_statement(block, statement, location); } } diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs index 340ff5e178767..3dc5a7a84900c 100644 --- a/src/librustc_mir/borrow_check/error_reporting.rs +++ b/src/librustc_mir/borrow_check/error_reporting.rs @@ -263,7 +263,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { (place, span): (&Place<'tcx>, Span), gen_borrow_kind: BorrowKind, issued_borrow: &BorrowData<'tcx>, - end_issued_loan_span: Option, ) { let issued_span = self.retrieve_borrow_span(issued_borrow); @@ -297,7 +296,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "it", rgt, "", - end_issued_loan_span, + None, Origin::Mir, ) } @@ -309,7 +308,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "", issued_span, "", - end_issued_loan_span, + None, Origin::Mir, ) } @@ -319,7 +318,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { span, &desc_place, issued_span, - end_issued_loan_span, + None, Origin::Mir, ) } @@ -331,7 +330,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { issued_span, "it", "", - end_issued_loan_span, + None, Origin::Mir, ), @@ -343,7 +342,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { lft, issued_span, "", - end_issued_loan_span, + None, Origin::Mir, ) } @@ -356,7 +355,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { lft, issued_span, "", - end_issued_loan_span, + None, Origin::Mir, ) } @@ -392,7 +391,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { borrow: &BorrowData<'tcx>, drop_span: Span, ) { - let end_span = self.opt_region_end_span(&borrow.region); let scope_tree = self.tcx.region_scope_tree(self.mir_def_id); let root_place = self.prefixes(&borrow.borrowed_place, PrefixSet::All) .last() @@ -427,7 +425,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span, borrow_span, proper_span, - end_span, ); } (RegionKind::ReScope(_), None) => { @@ -438,7 +435,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span, borrow_span, proper_span, - end_span, ); } (RegionKind::ReEarlyBound(_), Some(name)) @@ -454,7 +450,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span, borrow_span, proper_span, - end_span, ); } (RegionKind::ReEarlyBound(_), None) @@ -469,7 +464,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span, borrow_span, proper_span, - end_span, ); } (RegionKind::ReLateBound(_, _), _) @@ -491,7 +485,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span: Span, borrow_span: Span, _proper_span: Span, - end_span: Option, ) { let tcx = self.tcx; let mut err = @@ -501,9 +494,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span, format!("`{}` dropped here while still borrowed", name), ); - if let Some(end) = end_span { - err.span_label(end, "borrowed value needs to live until here"); - } self.explain_why_borrow_contains_point(context, borrow, &mut err); err.emit(); } @@ -516,7 +506,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span: Span, _borrow_span: Span, proper_span: Span, - end_span: Option, ) { let tcx = self.tcx; let mut err = @@ -527,9 +516,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { "temporary value dropped here while still borrowed", ); err.note("consider using a `let` binding to increase its lifetime"); - if let Some(end) = end_span { - err.span_label(end, "temporary value needs to live until here"); - } self.explain_why_borrow_contains_point(context, borrow, &mut err); err.emit(); } @@ -543,7 +529,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span: Span, borrow_span: Span, _proper_span: Span, - _end_span: Option, ) { debug!( "report_unscoped_local_value_does_not_live_long_enough(\ @@ -558,16 +543,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.span_label(borrow_span, "borrowed value does not live long enough"); err.span_label(drop_span, "borrowed value only lives until here"); - if !tcx.nll() { - tcx.note_and_explain_region( - scope_tree, - &mut err, - "borrowed value must be valid for ", - borrow.region, - "...", - ); - } - self.explain_why_borrow_contains_point(context, borrow, &mut err); err.emit(); } @@ -580,7 +555,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { drop_span: Span, _borrow_span: Span, proper_span: Span, - _end_span: Option, ) { debug!( "report_unscoped_temporary_value_does_not_live_long_enough(\ @@ -595,16 +569,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { err.span_label(proper_span, "temporary value does not live long enough"); err.span_label(drop_span, "temporary value only lives until here"); - if !tcx.nll() { - tcx.note_and_explain_region( - scope_tree, - &mut err, - "borrowed value must be valid for ", - borrow.region, - "...", - ); - } - self.explain_why_borrow_contains_point(context, borrow, &mut err); err.emit(); } diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 5b4c66bd65c17..22550319a1c63 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -98,19 +98,13 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( .as_local_node_id(def_id) .expect("do_mir_borrowck: non-local DefId"); - // Make our own copy of the MIR. This copy will be modified (in place) to - // contain non-lexical lifetimes. It will have a lifetime tied - // to the inference context. + // Replace all regions with fresh inference variables. This + // requires first making our own copy of the MIR. This copy will + // be modified (in place) to contain non-lexical lifetimes. It + // will have a lifetime tied to the inference context. let mut mir: Mir<'tcx> = input_mir.clone(); - let free_regions = if !tcx.nll() { - None - } else { - let mir = &mut mir; - - // Replace all regions with fresh inference variables. - Some(nll::replace_regions_in_mir(infcx, def_id, param_env, mir)) - }; - let mir = &mir; + let free_regions = nll::replace_regions_in_mir(infcx, def_id, param_env, &mut mir); + let mir = &mir; // no further changes let move_data: MoveData<'tcx> = match MoveData::gather_moves(mir, tcx) { Ok(move_data) => move_data, @@ -195,22 +189,17 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( let borrow_set = Rc::new(BorrowSet::build(tcx, mir)); // If we are in non-lexical mode, compute the non-lexical lifetimes. - let (opt_regioncx, opt_closure_req) = if let Some(free_regions) = free_regions { - let (regioncx, opt_closure_req) = nll::compute_regions( - infcx, - def_id, - free_regions, - mir, - param_env, - &mut flow_inits, - &mdpe.move_data, - &borrow_set, - ); - (Some(Rc::new(regioncx)), opt_closure_req) - } else { - assert!(!tcx.nll()); - (None, None) - }; + let (regioncx, opt_closure_req) = nll::compute_regions( + infcx, + def_id, + free_regions, + mir, + param_env, + &mut flow_inits, + &mdpe.move_data, + &borrow_set, + ); + let regioncx = Rc::new(regioncx); let flow_inits = flow_inits; // remove mut let flow_borrows = FlowAtLocation::new(do_dataflow( @@ -219,7 +208,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( id, &attributes, &dead_unwinds, - Borrows::new(tcx, mir, opt_regioncx.clone(), def_id, body_id, &borrow_set), + Borrows::new(tcx, mir, regioncx.clone(), def_id, body_id, &borrow_set), |rs, i| DebugFormatted::new(&rs.location(i)), )); @@ -247,7 +236,7 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( access_place_error_reported: FxHashSet(), reservation_error_reported: FxHashSet(), moved_error_reported: FxHashSet(), - nonlexical_regioncx: opt_regioncx, + nonlexical_regioncx: regioncx, nonlexical_cause_info: None, borrow_set, dominators, @@ -301,7 +290,7 @@ pub struct MirBorrowckCtxt<'cx, 'gcx: 'tcx, 'tcx: 'cx> { /// Non-lexical region inference context, if NLL is enabled. This /// contains the results from region inference and lets us e.g. /// find out which CFG points are contained in each borrow region. - nonlexical_regioncx: Option>>, + nonlexical_regioncx: Rc>, nonlexical_cause_info: Option, /// The set of borrows extracted from the MIR @@ -897,14 +886,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { this.report_use_while_mutably_borrowed(context, place_span, borrow) } ReadKind::Borrow(bk) => { - let end_issued_loan_span = this.opt_region_end_span(&borrow.region); error_reported = true; this.report_conflicting_borrow( context, place_span, bk, &borrow, - end_issued_loan_span, ) } } @@ -936,15 +923,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { match kind { WriteKind::MutableBorrow(bk) => { - let end_issued_loan_span = this.opt_region_end_span(&borrow.region); - error_reported = true; this.report_conflicting_borrow( context, place_span, bk, &borrow, - end_issued_loan_span, ) } WriteKind::StorageDeadOrDrop => { @@ -1832,22 +1816,6 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { _ => None, } } - - /// Returns the span for the "end point" given region. This will - /// return `None` if NLL is enabled, since that concept has no - /// meaning there. Otherwise, return region span if it exists and - /// span for end of the function if it doesn't exist. - pub(crate) fn opt_region_end_span(&self, region: &ty::Region<'tcx>) -> Option { - match self.nonlexical_regioncx { - Some(_) => None, - None => { - match self.borrow_set.region_span_map.get(region) { - Some(span) => Some(self.tcx.sess.codemap().end_point(*span)), - None => Some(self.tcx.sess.codemap().end_point(self.mir.span)) - } - } - } - } } #[derive(Copy, Clone, PartialEq, Eq, Debug)] 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 b12beb524e20d..d5e11a312ec26 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -29,82 +29,81 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { borrow: &BorrowData<'tcx>, err: &mut DiagnosticBuilder<'_>, ) { - if let Some(regioncx) = &self.nonlexical_regioncx { - let mir = self.mir; + let regioncx = &&self.nonlexical_regioncx; + let mir = self.mir; - if self.nonlexical_cause_info.is_none() { - self.nonlexical_cause_info = Some(regioncx.compute_causal_info(mir)); - } + if self.nonlexical_cause_info.is_none() { + self.nonlexical_cause_info = Some(regioncx.compute_causal_info(mir)); + } + + let cause_info = self.nonlexical_cause_info.as_ref().unwrap(); + if let Some(cause) = cause_info.why_region_contains_point(borrow.region, context.loc) { + match *cause.root_cause() { + Cause::LiveVar(local, location) => { + match find_regular_use(mir, regioncx, borrow, location, local) { + Some(p) => { + err.span_label( + mir.source_info(p).span, + format!("borrow later used here"), + ); + } + + None => { + span_bug!( + mir.source_info(context.loc).span, + "Cause should end in a LiveVar" + ); + } + } + } - let cause_info = self.nonlexical_cause_info.as_ref().unwrap(); - if let Some(cause) = cause_info.why_region_contains_point(borrow.region, context.loc) { - match *cause.root_cause() { - Cause::LiveVar(local, location) => { - match find_regular_use(mir, regioncx, borrow, location, local) { - Some(p) => { + Cause::DropVar(local, location) => { + match find_drop_use(mir, regioncx, borrow, location, local) { + Some(p) => match &mir.local_decls[local].name { + Some(local_name) => { err.span_label( mir.source_info(p).span, - format!("borrow later used here"), + format!( + "borrow later used here, when `{}` is dropped", + local_name + ), ); } - None => { - span_bug!( - mir.source_info(context.loc).span, - "Cause should end in a LiveVar" + err.span_label( + mir.local_decls[local].source_info.span, + "borrow may end up in a temporary, created here", ); - } - } - } - Cause::DropVar(local, location) => { - match find_drop_use(mir, regioncx, borrow, location, local) { - Some(p) => match &mir.local_decls[local].name { - Some(local_name) => { - err.span_label( - mir.source_info(p).span, - format!( - "borrow later used here, when `{}` is dropped", - local_name - ), - ); - } - None => { - err.span_label( - mir.local_decls[local].source_info.span, - "borrow may end up in a temporary, created here", - ); - - err.span_label( - mir.source_info(p).span, - "temporary later dropped here, \ - potentially using the reference", - ); - } - }, - - None => { - span_bug!( - mir.source_info(context.loc).span, - "Cause should end in a DropVar" + err.span_label( + mir.source_info(p).span, + "temporary later dropped here, \ + potentially using the reference", ); } - } - } + }, - Cause::UniversalRegion(region_vid) => { - if let Some(region) = regioncx.to_error_region(region_vid) { - self.tcx.note_and_explain_free_region( - err, - "borrowed value must be valid for ", - region, - "...", + None => { + span_bug!( + mir.source_info(context.loc).span, + "Cause should end in a DropVar" ); } } + } - _ => {} + Cause::UniversalRegion(region_vid) => { + if let Some(region) = regioncx.to_error_region(region_vid) { + self.tcx.note_and_explain_free_region( + err, + "borrowed value must be valid for ", + region, + "...", + ); + } } + + _ => {} } } } 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 544cb5eefc886..bdcff1a2d819c 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1596,7 +1596,7 @@ impl MirPass for TypeckMir { // When NLL is enabled, the borrow checker runs the typeck // itself, so we don't need this MIR pass anymore. - if tcx.nll() { + if tcx.use_mir() { return; } diff --git a/src/librustc_mir/dataflow/impls/borrows.rs b/src/librustc_mir/dataflow/impls/borrows.rs index 55c38dc89f636..a21691813a4d4 100644 --- a/src/librustc_mir/dataflow/impls/borrows.rs +++ b/src/librustc_mir/dataflow/impls/borrows.rs @@ -48,14 +48,14 @@ pub struct Borrows<'a, 'gcx: 'tcx, 'tcx: 'a> { borrow_set: Rc>, /// NLL region inference context with which NLL queries should be resolved - nonlexical_regioncx: Option>>, + nonlexical_regioncx: Rc>, } impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { crate fn new( tcx: TyCtxt<'a, 'gcx, 'tcx>, mir: &'a Mir<'tcx>, - nonlexical_regioncx: Option>>, + nonlexical_regioncx: Rc>, def_id: DefId, body_id: Option, borrow_set: &Rc> @@ -89,23 +89,23 @@ impl<'a, 'gcx, 'tcx> Borrows<'a, 'gcx, 'tcx> { fn kill_loans_out_of_scope_at_location(&self, sets: &mut BlockSets, location: Location) { - if let Some(ref regioncx) = self.nonlexical_regioncx { - // NOTE: The state associated with a given `location` - // reflects the dataflow on entry to the statement. If it - // does not contain `borrow_region`, then then that means - // that the statement at `location` kills the borrow. - // - // We are careful always to call this function *before* we - // set up the gen-bits for the statement or - // termanator. That way, if the effect of the statement or - // terminator *does* introduce a new loan of the same - // region, then setting that gen-bit will override any - // potential kill introduced here. - for (borrow_index, borrow_data) in self.borrow_set.borrows.iter_enumerated() { - let borrow_region = borrow_data.region.to_region_vid(); - if !regioncx.region_contains_point(borrow_region, location) { - sets.kill(&borrow_index); - } + let regioncx = &self.nonlexical_regioncx; + + // NOTE: The state associated with a given `location` + // reflects the dataflow on entry to the statement. If it + // does not contain `borrow_region`, then then that means + // that the statement at `location` kills the borrow. + // + // We are careful always to call this function *before* we + // set up the gen-bits for the statement or + // termanator. That way, if the effect of the statement or + // terminator *does* introduce a new loan of the same + // region, then setting that gen-bit will override any + // potential kill introduced here. + for (borrow_index, borrow_data) in self.borrow_set.borrows.iter_enumerated() { + let borrow_region = borrow_data.region.to_region_vid(); + if !regioncx.region_contains_point(borrow_region, location) { + sets.kill(&borrow_index); } } } @@ -153,18 +153,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for Borrows<'a, 'gcx, 'tcx> { self.kill_loans_out_of_scope_at_location(sets, location); match stmt.kind { - // EndRegion kills any borrows (reservations and active borrows both) - mir::StatementKind::EndRegion(region_scope) => { - if let Some(borrow_indexes) = - self.borrow_set.region_map.get(&ReScope(region_scope)) - { - assert!(self.nonlexical_regioncx.is_none()); - for idx in borrow_indexes { - sets.kill(idx); - } - } else { - // (if there is no entry, then there are no borrows to be tracked) - } + mir::StatementKind::EndRegion(_) => { } mir::StatementKind::Assign(ref lhs, ref rhs) => { diff --git a/src/test/compile-fail/E0501.rs b/src/test/compile-fail/E0501.rs index f7e246e8f0f41..5643e1ef09146 100644 --- a/src/test/compile-fail/E0501.rs +++ b/src/test/compile-fail/E0501.rs @@ -26,10 +26,12 @@ fn foo(a: &mut i32) { inside_closure(a) }; outside_closure_1(a); //[ast]~ ERROR cannot borrow `*a` as mutable because previous closure requires unique access - //[mir]~^ ERROR cannot borrow `*a` as mutable because previous closure requires unique access + //[mir]~^ ERROR cannot borrow `*a` as mutable because previous closure requires unique access outside_closure_2(a); //[ast]~ ERROR cannot borrow `*a` as immutable because previous closure requires unique access - //[mir]~^ ERROR cannot borrow `*a` as immutable because previous closure requires unique access + //[mir]~^ ERROR cannot borrow `*a` as immutable because previous closure requires unique access + + drop(bar); } fn main() { diff --git a/src/test/compile-fail/borrowck/borrowck-asm.rs b/src/test/compile-fail/borrowck/borrowck-asm.rs index 9ad3a8f9fc867..0b230be85ad97 100644 --- a/src/test/compile-fail/borrowck/borrowck-asm.rs +++ b/src/test/compile-fail/borrowck/borrowck-asm.rs @@ -14,7 +14,7 @@ // ignore-sparc // revisions: ast mir -//[mir]compile-flags: -Z borrowck=mir -Z nll +//[mir]compile-flags: -Z borrowck=mir #![feature(asm)] diff --git a/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs b/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs index f498d8d500e64..9057ba0790712 100644 --- a/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs +++ b/src/test/compile-fail/borrowck/borrowck-closures-mut-and-imm.rs @@ -29,7 +29,8 @@ fn a() { let mut x = 3; let c1 = || x = 4; let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x` - //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable + //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable + drop(c1); } fn b() { @@ -37,6 +38,7 @@ fn b() { let c1 = || set(&mut x); let c2 = || get(&x); //[ast]~ ERROR cannot borrow `x` //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable + drop(c1); } fn c() { @@ -44,6 +46,7 @@ fn c() { let c1 = || set(&mut x); let c2 = || x * 5; //[ast]~ ERROR cannot borrow `x` //[mir]~^ ERROR cannot borrow `x` as immutable because it is also borrowed as mutable + drop(c1); } fn d() { @@ -51,6 +54,7 @@ fn d() { let c2 = || x * 5; x = 5; //[ast]~ ERROR cannot assign //[mir]~^ ERROR cannot assign to `x` because it is borrowed + drop(c2); } fn e() { @@ -58,6 +62,7 @@ fn e() { let c1 = || get(&x); x = 5; //[ast]~ ERROR cannot assign //[mir]~^ ERROR cannot assign to `x` because it is borrowed + drop(c1); } fn f() { @@ -65,6 +70,7 @@ fn f() { let c1 = || get(&*x); *x = 5; //[ast]~ ERROR cannot assign to `*x` //[mir]~^ ERROR cannot assign to `*x` because it is borrowed + drop(c1); } fn g() { @@ -76,6 +82,7 @@ fn g() { let c1 = || get(&*x.f); *x.f = 5; //[ast]~ ERROR cannot assign to `*x.f` //[mir]~^ ERROR cannot assign to `*x.f` because it is borrowed + drop(c1); } fn h() { @@ -87,6 +94,7 @@ fn h() { let c1 = || get(&*x.f); let c2 = || *x.f = 5; //[ast]~ ERROR cannot borrow `x` as mutable //[mir]~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable + drop(c1); } fn main() { diff --git a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs index fa475949b36b0..3a7e4a13740d0 100644 --- a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs @@ -49,83 +49,93 @@ fn main() { // Local and field from struct { let mut f = Foo { x: 22 }; - let _x = f.x(); + let x = f.x(); f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed - //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed + //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed + drop(x); } // Local and field from tuple-struct { let mut g = Bar(22); - let _0 = g.x(); + let x = g.x(); g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed //[mir]~^ ERROR cannot use `g.0` because it was mutably borrowed + drop(x); } // Local and field from tuple { let mut h = (22, 23); - let _0 = &mut h.0; + let x = &mut h.0; h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed //[mir]~^ ERROR cannot use `h.0` because it was mutably borrowed + drop(x); } // Local and field from enum { let mut e = Baz::X(2); - let _e0 = e.x(); + let x = e.x(); match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed Baz::X(value) => value //[ast]~^ ERROR cannot use `e.0` because it was mutably borrowed //[mir]~^^ ERROR cannot use `e.0` because it was mutably borrowed }; + drop(x); } // Local and field from union unsafe { let mut u = U { b: 0 }; - let _ra = &mut u.a; + let x = &mut u.a; u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed + drop(x); } // Deref and field from struct { let mut f = Box::new(Foo { x: 22 }); - let _x = f.x(); + let x = f.x(); f.x; //[ast]~ ERROR cannot use `f.x` because it was mutably borrowed //[mir]~^ ERROR cannot use `f.x` because it was mutably borrowed + drop(x); } // Deref and field from tuple-struct { let mut g = Box::new(Bar(22)); - let _0 = g.x(); + let x = g.x(); g.0; //[ast]~ ERROR cannot use `g.0` because it was mutably borrowed //[mir]~^ ERROR cannot use `g.0` because it was mutably borrowed + drop(x); } // Deref and field from tuple { let mut h = Box::new((22, 23)); - let _0 = &mut h.0; + let x = &mut h.0; h.0; //[ast]~ ERROR cannot use `h.0` because it was mutably borrowed //[mir]~^ ERROR cannot use `h.0` because it was mutably borrowed + drop(x); } // Deref and field from enum { let mut e = Box::new(Baz::X(3)); - let _e0 = e.x(); + let x = e.x(); match *e { //[mir]~ ERROR cannot use `*e` because it was mutably borrowed Baz::X(value) => value //[ast]~^ ERROR cannot use `e.0` because it was mutably borrowed //[mir]~^^ ERROR cannot use `e.0` because it was mutably borrowed }; + drop(x); } // Deref and field from union unsafe { let mut u = Box::new(U { b: 0 }); - let _ra = &mut u.a; + let x = &mut u.a; u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed + drop(x); } // Constant index { let mut v = &[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; - let _v = &mut v; + let x = &mut v; match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed &[x, _, .., _, _] => println!("{}", x), //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed @@ -150,11 +160,12 @@ fn main() { //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed _ => panic!("other case"), } + drop(x); } // Subslices { let mut v = &[1, 2, 3, 4, 5]; - let _v = &mut v; + let x = &mut v; match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed &[x..] => println!("{:?}", x), //[ast]~^ ERROR cannot use `v[..]` because it was mutably borrowed @@ -179,13 +190,14 @@ fn main() { //[mir]~^^ ERROR cannot use `v[..]` because it was mutably borrowed _ => panic!("other case"), } + drop(x); } // Downcasted field { enum E { A(X), B { x: X } } let mut e = E::A(3); - let _e = &mut e; + let x = &mut e; match e { //[mir]~ ERROR cannot use `e` because it was mutably borrowed E::A(ref ax) => //[ast]~^ ERROR cannot borrow `e.0` as immutable because `e` is also borrowed as mutable @@ -197,13 +209,14 @@ fn main() { //[mir]~^^ ERROR cannot borrow `e.x` as immutable because it is also borrowed as mutable println!("e.bx: {:?}", bx), } + drop(x); } // Field in field { struct F { x: u32, y: u32 }; struct S { x: F, y: (u32, u32), }; let mut s = S { x: F { x: 1, y: 2}, y: (999, 998) }; - let _s = &mut s; + let x = &mut s; match s { //[mir]~ ERROR cannot use `s` because it was mutably borrowed S { y: (ref y0, _), .. } => //[ast]~^ ERROR cannot borrow `s.y.0` as immutable because `s` is also borrowed as mutable @@ -218,6 +231,7 @@ fn main() { println!("x0: {:?}", x0), _ => panic!("other case"), } + drop(x); } // Field of ref { @@ -231,6 +245,7 @@ fn main() { let p: &'a u8 = &*block.current; //[mir]~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable // No errors in AST because of issue rust#38899 + drop(x); } } // Field of ptr @@ -245,29 +260,32 @@ fn main() { let p : *const u8 = &*(*block).current; //[mir]~^ ERROR cannot borrow `*block.current` as immutable because it is also borrowed as mutable // No errors in AST because of issue rust#38899 + drop(x); } } // Field of index { struct F {x: u32, y: u32}; let mut v = &[F{x: 1, y: 2}, F{x: 3, y: 4}]; - let _v = &mut v; + let x = &mut v; v[0].y; //[ast]~^ ERROR cannot use `v[..].y` because it was mutably borrowed //[mir]~^^ ERROR cannot use `v[..].y` because it was mutably borrowed //[mir]~| ERROR cannot use `*v` because it was mutably borrowed + drop(x); } // Field of constant index { struct F {x: u32, y: u32}; let mut v = &[F{x: 1, y: 2}, F{x: 3, y: 4}]; - let _v = &mut v; + let x = &mut v; match v { //[mir]~ ERROR cannot use `v` because it was mutably borrowed &[_, F {x: ref xf, ..}] => println!("{}", xf), //[mir]~^ ERROR cannot borrow `v[..].x` as immutable because it is also borrowed as mutable // No errors in AST _ => panic!("other case") } + drop(x); } // Field from upvar { @@ -281,13 +299,15 @@ fn main() { } // Field from upvar nested { + // FIXME(#49824) -- the free region error below should probably not be there let mut x = 0; || { - || { - let y = &mut x; - &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time - //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time - *y = 1; + || { //[mir]~ ERROR free region `` does not outlive + let y = &mut x; + &mut x; //[ast]~ ERROR cannot borrow `**x` as mutable more than once at a time + //[mir]~^ ERROR cannot borrow `x` as mutable more than once at a time + *y = 1; + drop(y); } }; } diff --git a/src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs b/src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs index f09a0c7414ba9..6f0e0f43f6088 100644 --- a/src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs +++ b/src/test/compile-fail/borrowck/borrowck-imm-ref-to-mut-rec-field-issue-3162-c.rs @@ -13,10 +13,12 @@ fn main() { let mut _a = 3; - let _b = &mut _a; + let b = &mut _a; { - let _c = &*_b; + let c = &*b; _a = 4; //[ast]~ ERROR cannot assign to `_a` - //[mir]~^ ERROR cannot assign to `_a` because it is borrowed + //[mir]~^ ERROR cannot assign to `_a` because it is borrowed + drop(c); } + drop(b); } diff --git a/src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs b/src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs index 2fe764568bc82..f2f3e7914227c 100644 --- a/src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs +++ b/src/test/compile-fail/borrowck/borrowck-lend-flow-match.rs @@ -24,9 +24,10 @@ fn separate_arms() { // fact no outstanding loan of x! x = Some(0); } - Some(ref __isize) => { + Some(ref r) => { x = Some(1); //[ast]~ ERROR cannot assign - //[mir]~^ ERROR cannot assign to `x` because it is borrowed + //[mir]~^ ERROR cannot assign to `x` because it is borrowed + drop(r); } } x.clone(); // just to prevent liveness warnings diff --git a/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs b/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs index 3e57ac0ca1910..c2136e62a7b22 100644 --- a/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs +++ b/src/test/compile-fail/borrowck/borrowck-match-already-borrowed.rs @@ -25,16 +25,18 @@ fn match_enum() { Foo::A(x) => x //[ast]~ ERROR [E0503] //[mir]~^ ERROR [E0503] }; + drop(p); } fn main() { let mut x = 1; - let _x = &mut x; + let r = &mut x; let _ = match x { //[mir]~ ERROR [E0503] x => x + 1, //[ast]~ ERROR [E0503] //[mir]~^ ERROR [E0503] y => y + 2, //[ast]~ ERROR [E0503] //[mir]~^ ERROR [E0503] }; + drop(r); } diff --git a/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs b/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs index 63bb04a0e4c3a..7b0a71815a5f0 100644 --- a/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs +++ b/src/test/compile-fail/borrowck/borrowck-mut-borrow-linear-errors.rs @@ -17,14 +17,14 @@ fn main() { let mut x = 1; - let mut addr; + let mut addr = vec![]; loop { match 1 { - 1 => { addr = &mut x; } //[ast]~ ERROR [E0499] + 1 => { addr.push(&mut x); } //[ast]~ ERROR [E0499] //[mir]~^ ERROR [E0499] - 2 => { addr = &mut x; } //[ast]~ ERROR [E0499] + 2 => { addr.push(&mut x); } //[ast]~ ERROR [E0499] //[mir]~^ ERROR [E0499] - _ => { addr = &mut x; } //[ast]~ ERROR [E0499] + _ => { addr.push(&mut x); } //[ast]~ ERROR [E0499] //[mir]~^ ERROR [E0499] } } diff --git a/src/test/compile-fail/borrowck/borrowck-overloaded-index-ref-index.rs b/src/test/compile-fail/borrowck/borrowck-overloaded-index-ref-index.rs index 3a4c22eb1395a..109fe3d1128e1 100644 --- a/src/test/compile-fail/borrowck/borrowck-overloaded-index-ref-index.rs +++ b/src/test/compile-fail/borrowck/borrowck-overloaded-index-ref-index.rs @@ -71,4 +71,5 @@ fn main() { s[2] = 20; //[ast]~^ ERROR cannot assign to immutable indexed content //[mir]~^^ ERROR cannot assign to immutable item + drop(rs); } diff --git a/src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs b/src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs index 0f3a841821080..d917a0abb88d0 100644 --- a/src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs +++ b/src/test/compile-fail/borrowck/borrowck-pat-reassign-binding.rs @@ -21,7 +21,8 @@ fn main() { Some(ref i) => { // But on this branch, `i` is an outstanding borrow x = Some(*i+1); //[ast]~ ERROR cannot assign to `x` - //[mir]~^ ERROR cannot assign to `x` because it is borrowed + //[mir]~^ ERROR cannot assign to `x` because it is borrowed + drop(i); } } x.clone(); // just to prevent liveness warnings diff --git a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs index 0241b3870c7e6..97193bd019123 100644 --- a/src/test/compile-fail/borrowck/borrowck-union-borrow.rs +++ b/src/test/compile-fail/borrowck/borrowck-union-borrow.rs @@ -25,82 +25,98 @@ fn main() { { let ra = &u.a; let ra2 = &u.a; // OK + drop(ra); } { let ra = &u.a; let a = u.a; // OK + drop(ra); } { let ra = &u.a; let rma = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable //[mir]~^ ERROR cannot borrow `u.a` as mutable because it is also borrowed as immutable + drop(ra); } { let ra = &u.a; u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed + drop(ra); } // Imm borrow, other field { let ra = &u.a; let rb = &u.b; // OK + drop(ra); } { let ra = &u.a; let b = u.b; // OK + drop(ra); } { let ra = &u.a; let rmb = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable because `u` is also borrowed as immutable (via `u.a`) //[mir]~^ ERROR cannot borrow `u.b` as mutable because it is also borrowed as immutable + drop(ra); } { let ra = &u.a; u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed + drop(ra); } // Mut borrow, same field { let rma = &mut u.a; let ra = &u.a; //[ast]~ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable //[mir]~^ ERROR cannot borrow `u.a` as immutable because it is also borrowed as mutable + drop(rma); } { let ra = &mut u.a; let a = u.a; //[ast]~ ERROR cannot use `u.a` because it was mutably borrowed //[mir]~^ ERROR cannot use `u.a` because it was mutably borrowed + drop(ra); } { let rma = &mut u.a; let rma2 = &mut u.a; //[ast]~ ERROR cannot borrow `u.a` as mutable more than once at a time //[mir]~^ ERROR cannot borrow `u.a` as mutable more than once at a time + drop(rma); } { let rma = &mut u.a; u.a = 1; //[ast]~ ERROR cannot assign to `u.a` because it is borrowed //[mir]~^ ERROR cannot assign to `u.a` because it is borrowed + drop(rma); } // Mut borrow, other field { let rma = &mut u.a; let rb = &u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as immutable because `u` is also borrowed as mutable (via `u.a`) //[mir]~^ ERROR cannot borrow `u.b` as immutable because it is also borrowed as mutable + drop(rma); } { let ra = &mut u.a; let b = u.b; //[ast]~ ERROR cannot use `u.b` because it was mutably borrowed //[mir]~^ ERROR cannot use `u.b` because it was mutably borrowed + drop(ra); } { let rma = &mut u.a; let rmb2 = &mut u.b; //[ast]~ ERROR cannot borrow `u` (via `u.b`) as mutable more than once at a time //[mir]~^ ERROR cannot borrow `u.b` as mutable more than once at a time + drop(rma); } { let rma = &mut u.a; u.b = 1; //[ast]~ ERROR cannot assign to `u.b` because it is borrowed //[mir]~^ ERROR cannot assign to `u.b` because it is borrowed + drop(rma); } } } diff --git a/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs b/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs index 90933c6b31fa8..77b237e34f2b7 100644 --- a/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs +++ b/src/test/compile-fail/borrowck/two-phase-activation-sharing-interference.rs @@ -13,10 +13,9 @@ // revisions: nll_target // The following revisions are disabled due to missing support from two-phase beyond autorefs -//[lxl_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref -//[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref -Z nll +//[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref -//[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll +//[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows // This is an important corner case pointed out by Niko: one is // allowed to initiate a shared borrow during a reservation, but it diff --git a/src/test/compile-fail/borrowck/two-phase-allow-access-during-reservation.rs b/src/test/compile-fail/borrowck/two-phase-allow-access-during-reservation.rs index d2f4154433ab1..5deabf9376482 100644 --- a/src/test/compile-fail/borrowck/two-phase-allow-access-during-reservation.rs +++ b/src/test/compile-fail/borrowck/two-phase-allow-access-during-reservation.rs @@ -13,11 +13,9 @@ // revisions: nll_target // The following revisions are disabled due to missing support for two_phase_beyond_autoref -//[lxl_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two_phase_beyond_autoref -//[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two_phase_beyond_autoref -Z nll +//[nll_beyond] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two_phase_beyond_autoref - -//[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll +//[nll_target] compile-flags: -Z borrowck=mir -Z two-phase-borrows // This is the second counter-example from Niko's blog post // smallcultfollowing.com/babysteps/blog/2017/03/01/nested-method-calls-via-two-phase-borrowing/ @@ -44,9 +42,8 @@ fn main() { /*3*/ *p += 1; // (mutable borrow of `i` starts here, since `p` is used) - /*4*/ let k = i; //[lxl_beyond]~ ERROR cannot use `i` because it was mutably borrowed [E0503] - //[nll_beyond]~^ ERROR cannot use `i` because it was mutably borrowed [E0503] - //[nll_target]~^^ ERROR cannot use `i` because it was mutably borrowed [E0503] + /*4*/ let k = i; //[nll_beyond]~ ERROR cannot use `i` because it was mutably borrowed [E0503] + //[nll_target]~^ ERROR cannot use `i` because it was mutably borrowed [E0503] /*5*/ *p += 1; diff --git a/src/test/compile-fail/borrowck/two-phase-cannot-nest-mut-self-calls.rs b/src/test/compile-fail/borrowck/two-phase-cannot-nest-mut-self-calls.rs index 01b04708599c0..15700a1d61a1f 100644 --- a/src/test/compile-fail/borrowck/two-phase-cannot-nest-mut-self-calls.rs +++ b/src/test/compile-fail/borrowck/two-phase-cannot-nest-mut-self-calls.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// revisions: lxl nll -//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows -//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll +// compile-flags: -Z borrowck=mir -Z two-phase-borrows // This is the third counter-example from Niko's blog post // smallcultfollowing.com/babysteps/blog/2017/03/01/nested-method-calls-via-two-phase-borrowing/ @@ -26,8 +24,7 @@ fn main() { vec.get({ vec.push(2); - //[lxl]~^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable - //[nll]~^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable + //~^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable 0 }); diff --git a/src/test/compile-fail/borrowck/two-phase-nonrecv-autoref.rs b/src/test/compile-fail/borrowck/two-phase-nonrecv-autoref.rs index ef39fabda10e6..4303048138d91 100644 --- a/src/test/compile-fail/borrowck/two-phase-nonrecv-autoref.rs +++ b/src/test/compile-fail/borrowck/two-phase-nonrecv-autoref.rs @@ -8,12 +8,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// revisions: ast lxl nll +// revisions: ast nll //[ast]compile-flags: -//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows -//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll +//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -//[g2p]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll -Z two-phase-beyond-autoref +//[g2p]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref // the above revision is disabled until two-phase-beyond-autoref support is better // This is a test checking that when we limit two-phase borrows to @@ -69,44 +68,38 @@ fn overloaded_call_traits() { fn twice_ten_sm i32>(f: &mut F) { f(f(10)); - //[lxl]~^ ERROR cannot borrow `*f` as mutable more than once at a time - //[nll]~^^ ERROR cannot borrow `*f` as mutable more than once at a time - //[g2p]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time - //[ast]~^^^^ ERROR cannot borrow `*f` as mutable more than once at a time + //[nll]~^ ERROR cannot borrow `*f` as mutable more than once at a time + //[g2p]~^^ ERROR cannot borrow `*f` as mutable more than once at a time + //[ast]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time } fn twice_ten_si i32>(f: &mut F) { f(f(10)); } fn twice_ten_so i32>(f: Box) { f(f(10)); - //[lxl]~^ ERROR use of moved value: `*f` - //[nll]~^^ ERROR use of moved value: `*f` - //[g2p]~^^^ ERROR use of moved value: `*f` - //[ast]~^^^^ ERROR use of moved value: `*f` + //[nll]~^ ERROR use of moved value: `*f` + //[g2p]~^^ ERROR use of moved value: `*f` + //[ast]~^^^ ERROR use of moved value: `*f` } fn twice_ten_om(f: &mut FnMut(i32) -> i32) { f(f(10)); - //[lxl]~^ ERROR cannot borrow `*f` as mutable more than once at a time - //[nll]~^^ ERROR cannot borrow `*f` as mutable more than once at a time - //[g2p]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time - //[ast]~^^^^ ERROR cannot borrow `*f` as mutable more than once at a time + //[nll]~^ ERROR cannot borrow `*f` as mutable more than once at a time + //[g2p]~^^ ERROR cannot borrow `*f` as mutable more than once at a time + //[ast]~^^^ ERROR cannot borrow `*f` as mutable more than once at a time } fn twice_ten_oi(f: &mut Fn(i32) -> i32) { f(f(10)); } fn twice_ten_oo(f: Box i32>) { f(f(10)); - //[lxl]~^ ERROR cannot move a value of type - //[lxl]~^^ ERROR cannot move a value of type - //[lxl]~^^^ ERROR use of moved value: `*f` - //[nll]~^^^^ ERROR cannot move a value of type - //[nll]~^^^^^ ERROR cannot move a value of type - //[nll]~^^^^^^ ERROR use of moved value: `*f` - //[g2p]~^^^^^^^ ERROR cannot move a value of type - //[g2p]~^^^^^^^^ ERROR cannot move a value of type - //[g2p]~^^^^^^^^^ ERROR use of moved value: `*f` - //[ast]~^^^^^^^^^^ ERROR use of moved value: `*f` + //[nll]~^ ERROR cannot move a value of type + //[nll]~^^ ERROR cannot move a value of type + //[nll]~^^^ ERROR use of moved value: `*f` + //[g2p]~^^^^ ERROR cannot move a value of type + //[g2p]~^^^^^ ERROR cannot move a value of type + //[g2p]~^^^^^^ ERROR use of moved value: `*f` + //[ast]~^^^^^^^ ERROR use of moved value: `*f` } twice_ten_sm(&mut |x| x + 1); @@ -144,10 +137,9 @@ fn coerce_unsized() { // This is not okay. double_access(&mut a, &a); - //[lxl]~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] - //[nll]~^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] - //[g2p]~^^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] - //[ast]~^^^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] + //[nll]~^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] + //[g2p]~^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] + //[ast]~^^^ ERROR cannot borrow `a` as immutable because it is also borrowed as mutable [E0502] // But this is okay. a.m(a.i(10)); @@ -173,16 +165,14 @@ impl IndexMut for I { fn coerce_index_op() { let mut i = I(10); i[i[3]] = 4; - //[lxl]~^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] - //[nll]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] - //[ast]~^^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + //[nll]~^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + //[ast]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] i[3] = i[4]; i[i[3]] = i[4]; - //[lxl]~^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] - //[nll]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] - //[ast]~^^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + //[nll]~^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] + //[ast]~^^ ERROR cannot borrow `i` as immutable because it is also borrowed as mutable [E0502] } fn main() { diff --git a/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference-2.rs b/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference-2.rs index fc9100c8a9a86..f9326d944b8e4 100644 --- a/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference-2.rs +++ b/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference-2.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// revisions: lxl nll -//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows -//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll +// compile-flags: -Z borrowck=mir -Z two-phase-borrows // This is similar to two-phase-reservation-sharing-interference.rs // in that it shows a reservation that overlaps with a shared borrow. @@ -26,12 +24,11 @@ #![feature(rustc_attrs)] #[rustc_error] -fn main() { //[nll]~ ERROR compilation successful +fn main() { //~ ERROR compilation successful let mut v = vec![0, 1, 2]; let shared = &v; v.push(shared.len()); - //[lxl]~^ ERROR cannot borrow `v` as mutable because it is also borrowed as immutable [E0502] assert_eq!(v, [0, 1, 2, 3]); } diff --git a/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs b/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs index 058022ad588e8..1333167b780a8 100644 --- a/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs +++ b/src/test/compile-fail/borrowck/two-phase-reservation-sharing-interference.rs @@ -10,15 +10,13 @@ // ignore-tidy-linelength -// revisions: lxl_beyond nll_beyond nll_target +// revisions: nll_beyond nll_target // The following revisions are disabled due to missing support from two-phase beyond autorefs -//[lxl_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref -//[lxl_beyond] should-fail -//[nll_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref -Z nll +//[nll_beyond]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z two-phase-beyond-autoref //[nll_beyond] should-fail -//[nll_target]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll +//[nll_target]compile-flags: -Z borrowck=mir -Z two-phase-borrows // This is a corner case that the current implementation is (probably) // treating more conservatively than is necessary. But it also does @@ -46,9 +44,8 @@ fn main() { // with the shared borrow. But in the current implementation, // its an error. delay = &mut vec; - //[lxl_beyond]~^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable - //[nll_beyond]~^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable - //[nll_target]~^^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable + //[nll_beyond]~^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable + //[nll_target]~^^ ERROR cannot borrow `vec` as mutable because it is also borrowed as immutable shared[0]; } diff --git a/src/test/compile-fail/borrowck/two-phase-sneaky.rs b/src/test/compile-fail/borrowck/two-phase-sneaky.rs index 32747407c67f0..eec4b470d75f7 100644 --- a/src/test/compile-fail/borrowck/two-phase-sneaky.rs +++ b/src/test/compile-fail/borrowck/two-phase-sneaky.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// revisions: lxl nll -//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows -//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll +// cmpile-flags: -Z borrowck=mir -Z two-phase-borrows // This is the first counter-example from Niko's blog post // smallcultfollowing.com/babysteps/blog/2017/03/01/nested-method-calls-via-two-phase-borrowing/ @@ -22,8 +20,7 @@ fn main() { v[0].push_str({ v.push(format!("foo")); - //[lxl]~^ ERROR cannot borrow `v` as mutable more than once at a time [E0499] - //[nll]~^^ ERROR cannot borrow `v` as mutable more than once at a time [E0499] + //~^ ERROR cannot borrow `v` as mutable more than once at a time [E0499] "World!" }); diff --git a/src/test/compile-fail/coerce-overloaded-autoderef.rs b/src/test/compile-fail/coerce-overloaded-autoderef.rs index 0487b03171adb..5a05f59c6f402 100644 --- a/src/test/compile-fail/coerce-overloaded-autoderef.rs +++ b/src/test/compile-fail/coerce-overloaded-autoderef.rs @@ -22,6 +22,7 @@ fn double_mut_borrow(x: &mut Box) { let z = borrow_mut(x); //[ast]~^ ERROR cannot borrow `*x` as mutable more than once at a time //[mir]~^^ ERROR cannot borrow `*x` as mutable more than once at a time + drop((y, z)); } fn double_imm_borrow(x: &mut Box) { @@ -30,6 +31,7 @@ fn double_imm_borrow(x: &mut Box) { **x += 1; //[ast]~^ ERROR cannot assign to `**x` because it is borrowed //[mir]~^^ ERROR cannot assign to `**x` because it is borrowed + drop((y, z)); } fn double_mut_borrow2(x: &mut Box) { diff --git a/src/test/compile-fail/hrtb-identity-fn-borrows.rs b/src/test/compile-fail/hrtb-identity-fn-borrows.rs index 5f5b70dda5e81..e98cf4eb2abd9 100644 --- a/src/test/compile-fail/hrtb-identity-fn-borrows.rs +++ b/src/test/compile-fail/hrtb-identity-fn-borrows.rs @@ -33,6 +33,7 @@ fn call_repeatedly(f: F) f.call(&x); f.call(&x); x = 5; + drop(y); } fn main() { diff --git a/src/test/compile-fail/issue-36082.rs b/src/test/compile-fail/issue-36082.rs index fc3e0633750d8..ed6a2f85fbe23 100644 --- a/src/test/compile-fail/issue-36082.rs +++ b/src/test/compile-fail/issue-36082.rs @@ -11,6 +11,8 @@ // revisions: ast mir //[mir]compile-flags: -Z borrowck=mir +// FIXME(#49821) -- No tip about using a let binding + use std::cell::RefCell; fn main() { @@ -24,10 +26,9 @@ fn main() { //[ast]~| NOTE temporary value does not live long enough //[ast]~| NOTE consider using a `let` binding to increase its lifetime //[mir]~^^^^^ ERROR borrowed value does not live long enough [E0597] - //[mir]~| NOTE temporary value dropped here while still borrowed //[mir]~| NOTE temporary value does not live long enough - //[mir]~| NOTE consider using a `let` binding to increase its lifetime + //[mir]~| NOTE temporary value only lives until here println!("{}", val); + //[mir]~^ borrow later used here } //[ast]~^ NOTE temporary value needs to live until here -//[mir]~^^ NOTE temporary value needs to live until here diff --git a/src/test/compile-fail/mir_check_cast_closure.rs b/src/test/compile-fail/mir_check_cast_closure.rs index 6562efeb6d893..d8f5956b58530 100644 --- a/src/test/compile-fail/mir_check_cast_closure.rs +++ b/src/test/compile-fail/mir_check_cast_closure.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z borrowck=mir -Z nll +// compile-flags: -Z borrowck=mir #![allow(dead_code)] @@ -16,7 +16,7 @@ fn bar<'a, 'b>() -> fn(&'a u32, &'b u32) -> &'a u32 { let g: fn(_, _) -> _ = |_x, y| y; //~^ ERROR free region `'b` does not outlive free region `'a` g - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll } fn main() {} diff --git a/src/test/compile-fail/mir_check_cast_reify.rs b/src/test/compile-fail/mir_check_cast_reify.rs index f6ad2820d17ce..1f9174b3574a7 100644 --- a/src/test/compile-fail/mir_check_cast_reify.rs +++ b/src/test/compile-fail/mir_check_cast_reify.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z borrowck=mir -Z nll +// compile-flags: -Zborrowck=mir #![allow(dead_code)] @@ -44,7 +44,7 @@ fn bar<'a>(x: &'a u32) -> &'static u32 { // The MIR type checker must therefore relate `'?0` to `'?1` and `'?2` // as part of checking the `ReifyFnPointer`. let f: fn(_) -> _ = foo; - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR free region `'a` does not outlive free region `'static` f(x) } diff --git a/src/test/compile-fail/mir_check_cast_unsafe_fn.rs b/src/test/compile-fail/mir_check_cast_unsafe_fn.rs index c9b378dacd540..27ca2728ddfd6 100644 --- a/src/test/compile-fail/mir_check_cast_unsafe_fn.rs +++ b/src/test/compile-fail/mir_check_cast_unsafe_fn.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z borrowck=mir -Z nll +// compile-flags: -Zborrowck=mir #![allow(dead_code)] @@ -16,7 +16,7 @@ fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 { // Here the NLL checker must relate the types in `f` to the types // in `g`. These are related via the `UnsafeFnPointer` cast. let g: unsafe fn(_) -> _ = f; - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR free region `'a` does not outlive free region `'static` unsafe { g(input) } } diff --git a/src/test/compile-fail/mir_check_cast_unsize.rs b/src/test/compile-fail/mir_check_cast_unsize.rs index 1df56793f73bd..e30bed6105815 100644 --- a/src/test/compile-fail/mir_check_cast_unsize.rs +++ b/src/test/compile-fail/mir_check_cast_unsize.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z borrowck=mir -Z nll +// compile-flags: -Z borrowck=mir #![allow(dead_code)] #![feature(dyn_trait)] @@ -18,7 +18,7 @@ use std::fmt::Debug; fn bar<'a>(x: &'a u32) -> &'static dyn Debug { //~^ ERROR free region `'a` does not outlive free region `'static` x - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll } fn main() {} diff --git a/src/test/compile-fail/mut-pattern-internal-mutability.rs b/src/test/compile-fail/mut-pattern-internal-mutability.rs index 72727cdfe54d2..a05ee64937eb7 100644 --- a/src/test/compile-fail/mut-pattern-internal-mutability.rs +++ b/src/test/compile-fail/mut-pattern-internal-mutability.rs @@ -25,5 +25,6 @@ fn main() { // check borrowing is detected successfully let &mut ref x = foo; *foo += 1; //[ast]~ ERROR cannot assign to `*foo` because it is borrowed - //[mir]~^ ERROR cannot assign to `*foo` because it is borrowed + //[mir]~^ ERROR cannot assign to `*foo` because it is borrowed + drop(x); } diff --git a/src/test/compile-fail/nll/loan_ends_mid_block_pair.rs b/src/test/compile-fail/nll/loan_ends_mid_block_pair.rs index fdc650a072131..97126e98cbf3a 100644 --- a/src/test/compile-fail/nll/loan_ends_mid_block_pair.rs +++ b/src/test/compile-fail/nll/loan_ends_mid_block_pair.rs @@ -9,7 +9,7 @@ // except according to those terms. -// compile-flags:-Zborrowck=compare -Znll +// compile-flags:-Zborrowck=compare #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/compile-fail/nll/loan_ends_mid_block_vec.rs b/src/test/compile-fail/nll/loan_ends_mid_block_vec.rs index f22d2fc23e057..b5357d0ee827c 100644 --- a/src/test/compile-fail/nll/loan_ends_mid_block_vec.rs +++ b/src/test/compile-fail/nll/loan_ends_mid_block_vec.rs @@ -9,7 +9,7 @@ // except according to those terms. -// compile-flags:-Zborrowck=compare -Znll +// compile-flags:-Zborrowck=compare #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/compile-fail/nll/reference-carried-through-struct-field.rs b/src/test/compile-fail/nll/reference-carried-through-struct-field.rs index efa6cc273b6f4..589a3daa38d85 100644 --- a/src/test/compile-fail/nll/reference-carried-through-struct-field.rs +++ b/src/test/compile-fail/nll/reference-carried-through-struct-field.rs @@ -9,7 +9,7 @@ // except according to those terms. //revisions: ast mir -//[mir] compile-flags: -Z borrowck=mir -Z nll +//[mir] compile-flags: -Z borrowck=mir #![allow(unused_assignments)] diff --git a/src/test/compile-fail/nll/region-ends-after-if-condition.rs b/src/test/compile-fail/nll/region-ends-after-if-condition.rs index 1128d65af95c5..e1c47a6bbff2c 100644 --- a/src/test/compile-fail/nll/region-ends-after-if-condition.rs +++ b/src/test/compile-fail/nll/region-ends-after-if-condition.rs @@ -12,7 +12,7 @@ // in the type of `p` includes the points after `&v[0]` up to (but not // including) the call to `use_x`. The `else` branch is not included. -// compile-flags:-Zborrowck=compare -Znll +// compile-flags:-Zborrowck=compare #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/compile-fail/nll/return_from_loop.rs b/src/test/compile-fail/nll/return_from_loop.rs index 7ed59ef2a879b..13f1ca6431b3d 100644 --- a/src/test/compile-fail/nll/return_from_loop.rs +++ b/src/test/compile-fail/nll/return_from_loop.rs @@ -12,7 +12,7 @@ // in the type of `p` includes the points after `&v[0]` up to (but not // including) the call to `use_x`. The `else` branch is not included. -// compile-flags:-Zborrowck=compare -Znll +// compile-flags:-Zborrowck=compare #![allow(warnings)] #![feature(rustc_attrs)] diff --git a/src/test/compile-fail/nll/where_clauses_in_functions.rs b/src/test/compile-fail/nll/where_clauses_in_functions.rs index ecea8756903ae..1a3dc76005db4 100644 --- a/src/test/compile-fail/nll/where_clauses_in_functions.rs +++ b/src/test/compile-fail/nll/where_clauses_in_functions.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z borrowck=mir -Z nll +// compile-flags: -Zborrowck=mir #![allow(dead_code)] @@ -22,7 +22,7 @@ where fn bar<'a, 'b>(x: &'a u32, y: &'b u32) -> (&'a u32, &'b u32) { foo(x, y) //~^ ERROR lifetime mismatch [E0623] - //~| WARNING not reporting region error due to -Znll + //~| WARNING not reporting region error due to nll } fn main() {} diff --git a/src/test/compile-fail/nll/where_clauses_in_structs.rs b/src/test/compile-fail/nll/where_clauses_in_structs.rs index f1a6dc48e13b8..69f0f43af1342 100644 --- a/src/test/compile-fail/nll/where_clauses_in_structs.rs +++ b/src/test/compile-fail/nll/where_clauses_in_structs.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags: -Z borrowck=mir -Z nll +// compile-flags: -Z borrowck=mir #![allow(dead_code)] @@ -22,7 +22,7 @@ struct Foo<'a: 'b, 'b> { fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) { Foo { x, y }; //~^ ERROR lifetime mismatch [E0623] - //~| WARNING not reporting region error due to -Znll + //~| WARNING not reporting region error due to nll } fn main() {} diff --git a/src/test/compile-fail/regions-pattern-typing-issue-19997.rs b/src/test/compile-fail/regions-pattern-typing-issue-19997.rs index 6fbc65ce6a71f..1f23dcbb72523 100644 --- a/src/test/compile-fail/regions-pattern-typing-issue-19997.rs +++ b/src/test/compile-fail/regions-pattern-typing-issue-19997.rs @@ -18,7 +18,8 @@ fn main() { match (&a1,) { (&ref b0,) => { a1 = &f; //[ast]~ ERROR cannot assign - //[mir]~^ ERROR cannot assign to `a1` because it is borrowed + //[mir]~^ ERROR cannot assign to `a1` because it is borrowed + drop(b0); } } } diff --git a/src/test/compile-fail/regions-static-bound.rs b/src/test/compile-fail/regions-static-bound.rs index 13f93090fbbb4..a0097b9f6d7df 100644 --- a/src/test/compile-fail/regions-static-bound.rs +++ b/src/test/compile-fail/regions-static-bound.rs @@ -9,7 +9,7 @@ // except according to those terms. // revisions: ll nll -//[nll] compile-flags: -Znll -Zborrowck=mir +//[nll] compile-flags:-Zborrowck=mir fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t } @@ -17,16 +17,16 @@ fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static () where 'a: 'b, 'b: 'static { t } fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a { t //[ll]~ ERROR E0312 - //[nll]~^ WARNING not reporting region error due to -Znll + //[nll]~^ WARNING not reporting region error due to nll //[nll]~| ERROR free region `'a` does not outlive free region `'static` } fn error(u: &(), v: &()) { static_id(&u); //[ll]~ ERROR explicit lifetime required in the type of `u` [E0621] - //[nll]~^ WARNING not reporting region error due to -Znll + //[nll]~^ WARNING not reporting region error due to nll //[nll]~| ERROR explicit lifetime required in the type of `u` [E0621] static_id_indirect(&v); //[ll]~ ERROR explicit lifetime required in the type of `v` [E0621] - //[nll]~^ WARNING not reporting region error due to -Znll + //[nll]~^ WARNING not reporting region error due to nll //[nll]~| ERROR explicit lifetime required in the type of `v` [E0621] } diff --git a/src/test/mir-opt/nll/liveness-call-subtlety.rs b/src/test/mir-opt/nll/liveness-call-subtlety.rs index 09288cf69ff58..f41b39845a579 100644 --- a/src/test/mir-opt/nll/liveness-call-subtlety.rs +++ b/src/test/mir-opt/nll/liveness-call-subtlety.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Znll +// compile-flags:-Zborrowck=mir fn can_panic() -> Box { Box::new(44) diff --git a/src/test/mir-opt/nll/liveness-drop-intra-block.rs b/src/test/mir-opt/nll/liveness-drop-intra-block.rs index 64ffc7446062c..073b44d6e3387 100644 --- a/src/test/mir-opt/nll/liveness-drop-intra-block.rs +++ b/src/test/mir-opt/nll/liveness-drop-intra-block.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Znll +// compile-flags:-Zborrowck=mir #![allow(warnings)] diff --git a/src/test/mir-opt/nll/liveness-interblock.rs b/src/test/mir-opt/nll/liveness-interblock.rs index 671f5e5292aa4..6a8749084068a 100644 --- a/src/test/mir-opt/nll/liveness-interblock.rs +++ b/src/test/mir-opt/nll/liveness-interblock.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Znll +// compile-flags:-Zborrowck=mir fn cond() -> bool { false } diff --git a/src/test/mir-opt/nll/named-lifetimes-basic.rs b/src/test/mir-opt/nll/named-lifetimes-basic.rs index 8feac15d69a82..5cca3e55259d0 100644 --- a/src/test/mir-opt/nll/named-lifetimes-basic.rs +++ b/src/test/mir-opt/nll/named-lifetimes-basic.rs @@ -13,8 +13,8 @@ // suitable variables and that we setup the outlives relationship // between R0 and R1 properly. -// compile-flags:-Znll -Zverbose -// ^^^^^^^^^ force compiler to dump more region information +// compile-flags:-Zborrowck=mir -Zverbose +// ^^^^^^^^^ force compiler to dump more region information // ignore-tidy-linelength #![allow(warnings)] diff --git a/src/test/mir-opt/nll/reborrow-basic.rs b/src/test/mir-opt/nll/reborrow-basic.rs index 92e42a73bbb6a..b7c8d81b77fdb 100644 --- a/src/test/mir-opt/nll/reborrow-basic.rs +++ b/src/test/mir-opt/nll/reborrow-basic.rs @@ -12,8 +12,8 @@ // in the type of `r_a` must outlive the region (`R7`) that appears in // the type of `r_b` -// compile-flags:-Znll -Zverbose -// ^^^^^^^^^ force compiler to dump more region information +// compile-flags:-Zborrowck=mir -Zverbose +// ^^^^^^^^^ force compiler to dump more region information #![allow(warnings)] diff --git a/src/test/mir-opt/nll/region-liveness-basic.rs b/src/test/mir-opt/nll/region-liveness-basic.rs index 19d733d4f6b6a..75d8a6a4f6ac5 100644 --- a/src/test/mir-opt/nll/region-liveness-basic.rs +++ b/src/test/mir-opt/nll/region-liveness-basic.rs @@ -12,8 +12,8 @@ // in the type of `p` includes the points after `&v[0]` up to (but not // including) the call to `use_x`. The `else` branch is not included. -// compile-flags:-Znll -Zverbose -// ^^^^^^^^^ force compiler to dump more region information +// compile-flags:-Zborrowck=mir -Zverbose +// ^^^^^^^^^ force compiler to dump more region information #![allow(warnings)] diff --git a/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs b/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs index 821cd73667193..153739133ac82 100644 --- a/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs +++ b/src/test/mir-opt/nll/region-liveness-two-disjoint-uses.rs @@ -14,8 +14,8 @@ // but only at a particular point, and hence they wind up including // distinct regions. -// compile-flags:-Znll -Zverbose -// ^^^^^^^^^ force compiler to dump more region information +// compile-flags:-Zborrowck=mir -Zverbose +// ^^^^^^^^^ force compiler to dump more region information #![allow(warnings)] diff --git a/src/test/mir-opt/nll/region-subtyping-basic.rs b/src/test/mir-opt/nll/region-subtyping-basic.rs index a3f68ed5ebf5e..16952143d0a5b 100644 --- a/src/test/mir-opt/nll/region-subtyping-basic.rs +++ b/src/test/mir-opt/nll/region-subtyping-basic.rs @@ -12,8 +12,8 @@ // in the type of `p` includes the points after `&v[0]` up to (but not // including) the call to `use_x`. The `else` branch is not included. -// compile-flags:-Znll -Zverbose -// ^^^^^^^^^ force compiler to dump more region information +// compile-flags:-Zborrowck=mir -Zverbose +// ^^^^^^^^^ force compiler to dump more region information #![allow(warnings)] diff --git a/src/test/run-pass/borrowck/two-phase-baseline.rs b/src/test/run-pass/borrowck/two-phase-baseline.rs index 6623444926398..ca15591a10192 100644 --- a/src/test/run-pass/borrowck/two-phase-baseline.rs +++ b/src/test/run-pass/borrowck/two-phase-baseline.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// revisions: lxl nll -//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows -//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll +// compile-flags: -Z borrowck=mir -Z two-phase-borrows // This is the "goto example" for why we want two phase borrows. diff --git a/src/test/run-pass/impl-trait/example-calendar.rs b/src/test/run-pass/impl-trait/example-calendar.rs index b1db203071788..e3b7322e48b6b 100644 --- a/src/test/run-pass/impl-trait/example-calendar.rs +++ b/src/test/run-pass/impl-trait/example-calendar.rs @@ -9,7 +9,7 @@ // except according to those terms. // revisions: normal nll -//[nll] compile-flags: -Znll -Zborrowck=mir +//[nll] compile-flags:-Zborrowck=mir #![feature(fn_traits, step_trait, diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.rs b/src/test/ui/borrowck/borrowck-closures-two-mut.rs index b6946154fa00a..55e73af9e6a1b 100644 --- a/src/test/ui/borrowck/borrowck-closures-two-mut.rs +++ b/src/test/ui/borrowck/borrowck-closures-two-mut.rs @@ -23,6 +23,7 @@ fn a() { let c1 = to_fn_mut(|| x = 4); let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable more than once //~| ERROR cannot borrow `x` as mutable more than once + drop((c1, c2)); } fn set(x: &mut isize) { @@ -34,6 +35,7 @@ fn b() { let c1 = to_fn_mut(|| set(&mut x)); let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once //~| ERROR cannot borrow `x` as mutable more than once + drop((c1, c2)); } fn c() { @@ -41,6 +43,7 @@ fn c() { let c1 = to_fn_mut(|| x = 5); let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as mutable more than once //~| ERROR cannot borrow `x` as mutable more than once + drop((c1, c2)); } fn d() { @@ -49,6 +52,7 @@ fn d() { let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nested closure) //~^ ERROR cannot borrow `x` as mutable more than once //~| ERROR cannot borrow `x` as mutable more than once + drop((c1, c2)); } fn g() { @@ -61,6 +65,7 @@ fn g() { let c2 = to_fn_mut(|| set(&mut *x.f)); //~^ ERROR cannot borrow `x` as mutable more than once //~| ERROR cannot borrow `x` as mutable more than once + drop((c1, c2)); } fn main() { diff --git a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr index c739165ddbd37..a4f8e8b408ba5 100644 --- a/src/test/ui/borrowck/borrowck-closures-two-mut.stderr +++ b/src/test/ui/borrowck/borrowck-closures-two-mut.stderr @@ -9,12 +9,12 @@ LL | let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable mo | ^^ - borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here -LL | //~| ERROR cannot borrow `x` as mutable more than once +... LL | } | - first borrow ends here error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast) - --> $DIR/borrowck-closures-two-mut.rs:35:24 + --> $DIR/borrowck-closures-two-mut.rs:36:24 | LL | let c1 = to_fn_mut(|| set(&mut x)); | -- - previous borrow occurs due to use of `x` in closure @@ -24,12 +24,12 @@ LL | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as muta | ^^ - borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here -LL | //~| ERROR cannot borrow `x` as mutable more than once +... LL | } | - first borrow ends here error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast) - --> $DIR/borrowck-closures-two-mut.rs:42:24 + --> $DIR/borrowck-closures-two-mut.rs:44:24 | LL | let c1 = to_fn_mut(|| x = 5); | -- - previous borrow occurs due to use of `x` in closure @@ -39,12 +39,12 @@ LL | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as muta | ^^ - borrow occurs due to use of `x` in closure | | | second mutable borrow occurs here -LL | //~| ERROR cannot borrow `x` as mutable more than once +... LL | } | - first borrow ends here error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast) - --> $DIR/borrowck-closures-two-mut.rs:49:24 + --> $DIR/borrowck-closures-two-mut.rs:52:24 | LL | let c1 = to_fn_mut(|| x = 5); | -- - previous borrow occurs due to use of `x` in closure @@ -59,7 +59,7 @@ LL | } | - first borrow ends here error[E0499]: cannot borrow `x` as mutable more than once at a time (Ast) - --> $DIR/borrowck-closures-two-mut.rs:61:24 + --> $DIR/borrowck-closures-two-mut.rs:65:24 | LL | let c1 = to_fn_mut(|| set(&mut *x.f)); | -- - previous borrow occurs due to use of `x` in closure @@ -85,11 +85,11 @@ LL | let c2 = to_fn_mut(|| x = 5); //~ ERROR cannot borrow `x` as mutable mo | | | second mutable borrow occurs here LL | //~| ERROR cannot borrow `x` as mutable more than once -LL | } - | - first borrow ends here +LL | drop((c1, c2)); + | -- borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir) - --> $DIR/borrowck-closures-two-mut.rs:35:24 + --> $DIR/borrowck-closures-two-mut.rs:36:24 | LL | let c1 = to_fn_mut(|| set(&mut x)); | -- - previous borrow occurs due to use of `x` in closure @@ -100,11 +100,11 @@ LL | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as muta | | | second mutable borrow occurs here LL | //~| ERROR cannot borrow `x` as mutable more than once -LL | } - | - first borrow ends here +LL | drop((c1, c2)); + | -- borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir) - --> $DIR/borrowck-closures-two-mut.rs:42:24 + --> $DIR/borrowck-closures-two-mut.rs:44:24 | LL | let c1 = to_fn_mut(|| x = 5); | -- - previous borrow occurs due to use of `x` in closure @@ -115,11 +115,11 @@ LL | let c2 = to_fn_mut(|| set(&mut x)); //~ ERROR cannot borrow `x` as muta | | | second mutable borrow occurs here LL | //~| ERROR cannot borrow `x` as mutable more than once -LL | } - | - first borrow ends here +LL | drop((c1, c2)); + | -- borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir) - --> $DIR/borrowck-closures-two-mut.rs:49:24 + --> $DIR/borrowck-closures-two-mut.rs:52:24 | LL | let c1 = to_fn_mut(|| x = 5); | -- - previous borrow occurs due to use of `x` in closure @@ -130,11 +130,11 @@ LL | let c2 = to_fn_mut(|| { let _y = to_fn_mut(|| set(&mut x)); }); // (nes | | | second mutable borrow occurs here ... -LL | } - | - first borrow ends here +LL | drop((c1, c2)); + | -- borrow later used here error[E0499]: cannot borrow `x` as mutable more than once at a time (Mir) - --> $DIR/borrowck-closures-two-mut.rs:61:24 + --> $DIR/borrowck-closures-two-mut.rs:65:24 | LL | let c1 = to_fn_mut(|| set(&mut *x.f)); | -- - previous borrow occurs due to use of `x` in closure @@ -145,8 +145,8 @@ LL | let c2 = to_fn_mut(|| set(&mut *x.f)); | | | second mutable borrow occurs here ... -LL | } - | - first borrow ends here +LL | drop((c1, c2)); + | -- borrow later used here error: aborting due to 10 previous errors diff --git a/src/test/ui/borrowck/two-phase-method-receivers.rs b/src/test/ui/borrowck/two-phase-method-receivers.rs index e690263a916f3..6d7ed61bdd8b5 100644 --- a/src/test/ui/borrowck/two-phase-method-receivers.rs +++ b/src/test/ui/borrowck/two-phase-method-receivers.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// revisions: lxl nll -//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows -//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll +// compile-flags: -Z borrowck=mir -Z two-phase-borrows // run-pass diff --git a/src/test/ui/borrowck/two-phase-multiple-activations.rs b/src/test/ui/borrowck/two-phase-multiple-activations.rs index e1ed41bfb2c64..9ea9696511b71 100644 --- a/src/test/ui/borrowck/two-phase-multiple-activations.rs +++ b/src/test/ui/borrowck/two-phase-multiple-activations.rs @@ -8,9 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// revisions: lxl nll -//[lxl]compile-flags: -Z borrowck=mir -Z two-phase-borrows -//[nll]compile-flags: -Z borrowck=mir -Z two-phase-borrows -Z nll +// compile-flags: -Z borrowck=mir -Z two-phase-borrows // run-pass diff --git a/src/test/ui/issue-45697-1.rs b/src/test/ui/issue-45697-1.rs index 7734b14b2ab7b..b8be209833a6e 100644 --- a/src/test/ui/issue-45697-1.rs +++ b/src/test/ui/issue-45697-1.rs @@ -30,6 +30,7 @@ fn main() { *y.pointer += 1; //~^ ERROR cannot assign to `*y.pointer` because it is borrowed (Ast) [E0506] //~| ERROR cannot use `*y.pointer` because it was mutably borrowed (Mir) [E0503] + //~| ERROR cannot assign to `*y.pointer` because it is borrowed (Mir) [E0506] *z.pointer += 1; } } diff --git a/src/test/ui/issue-45697-1.stderr b/src/test/ui/issue-45697-1.stderr index aa899c5aee9eb..cf108691a0e4f 100644 --- a/src/test/ui/issue-45697-1.stderr +++ b/src/test/ui/issue-45697-1.stderr @@ -13,8 +13,22 @@ LL | let z = copy_borrowed_ptr(&mut y); | ------ borrow of `y` occurs here LL | *y.pointer += 1; | ^^^^^^^^^^^^^^^ use of borrowed `y` +... +LL | *z.pointer += 1; + | --------------- borrow later used here -error: aborting due to 2 previous errors +error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Mir) + --> $DIR/issue-45697-1.rs:30:9 + | +LL | let z = copy_borrowed_ptr(&mut y); + | ------ borrow of `*y.pointer` occurs here +LL | *y.pointer += 1; + | ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here +... +LL | *z.pointer += 1; + | --------------- borrow later used here + +error: aborting due to 3 previous errors Some errors occurred: E0503, E0506. For more information about an error, try `rustc --explain E0503`. diff --git a/src/test/ui/issue-45697.rs b/src/test/ui/issue-45697.rs index 4e93eccd6f649..27acc2c89f75d 100644 --- a/src/test/ui/issue-45697.rs +++ b/src/test/ui/issue-45697.rs @@ -30,6 +30,7 @@ fn main() { *y.pointer += 1; //~^ ERROR cannot assign to `*y.pointer` because it is borrowed (Ast) [E0506] //~| ERROR cannot use `*y.pointer` because it was mutably borrowed (Mir) [E0503] + //~| ERROR cannot assign to `*y.pointer` because it is borrowed (Mir) [E0506] *z.pointer += 1; } } diff --git a/src/test/ui/issue-45697.stderr b/src/test/ui/issue-45697.stderr index babfc33b94582..a85972fcd7a1c 100644 --- a/src/test/ui/issue-45697.stderr +++ b/src/test/ui/issue-45697.stderr @@ -13,8 +13,22 @@ LL | let z = copy_borrowed_ptr(&mut y); | ------ borrow of `y` occurs here LL | *y.pointer += 1; | ^^^^^^^^^^^^^^^ use of borrowed `y` +... +LL | *z.pointer += 1; + | --------------- borrow later used here -error: aborting due to 2 previous errors +error[E0506]: cannot assign to `*y.pointer` because it is borrowed (Mir) + --> $DIR/issue-45697.rs:30:9 + | +LL | let z = copy_borrowed_ptr(&mut y); + | ------ borrow of `*y.pointer` occurs here +LL | *y.pointer += 1; + | ^^^^^^^^^^^^^^^ assignment to borrowed `*y.pointer` occurs here +... +LL | *z.pointer += 1; + | --------------- borrow later used here + +error: aborting due to 3 previous errors Some errors occurred: E0503, E0506. For more information about an error, try `rustc --explain E0503`. diff --git a/src/test/ui/issue-46471-1.stderr b/src/test/ui/issue-46471-1.stderr index bfd5bfa9f7274..0108056bc7278 100644 --- a/src/test/ui/issue-46471-1.stderr +++ b/src/test/ui/issue-46471-1.stderr @@ -12,13 +12,16 @@ LL | } error[E0597]: `z` does not live long enough (Mir) --> $DIR/issue-46471-1.rs:16:9 | -LL | &mut z - | ^^^^^^ borrowed value does not live long enough -LL | }; - | - `z` dropped here while still borrowed -... -LL | } - | - borrowed value needs to live until here +LL | let y = { + | _____________- +LL | | let mut z = 0; +LL | | &mut z + | | ^^^^^^ borrowed value does not live long enough +LL | | }; + | | - + | | | + | |_____borrowed value only lives until here + | borrow later used here error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.rs b/src/test/ui/nll/closure-requirements/escape-argument-callee.rs index 41c744fec6e76..1e168028c7c9a 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.rs +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.rs @@ -22,7 +22,7 @@ // that appear free in its type (hence, we see it before the closure's // "external requirements" report). -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![feature(rustc_attrs)] @@ -35,7 +35,7 @@ fn test() { let y = 22; let mut closure = expect_sig(|p, y| *p = y); //~^ ERROR does not outlive free region - //~| WARNING not reporting region error due to -Znll + //~| WARNING not reporting region error due to nll closure(&mut p, &y); } diff --git a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr index 5f84001a8fb99..d876c751a41d2 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/escape-argument-callee.rs:36:50 | LL | let mut closure = expect_sig(|p, y| *p = y); diff --git a/src/test/ui/nll/closure-requirements/escape-argument.rs b/src/test/ui/nll/closure-requirements/escape-argument.rs index 7e918c6431de4..7a28cb26f3570 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument.rs +++ b/src/test/ui/nll/closure-requirements/escape-argument.rs @@ -22,7 +22,7 @@ // basically checking that the MIR type checker correctly enforces the // closure signature. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![feature(rustc_attrs)] diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs index 05700ae00ad4f..598839f872e01 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs +++ b/src/test/ui/nll/closure-requirements/escape-upvar-nested.rs @@ -15,7 +15,7 @@ // // except that the closure does so via a second closure. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![feature(rustc_attrs)] diff --git a/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs b/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs index 93d8bfafcbaa4..49d31bbc139d7 100644 --- a/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs +++ b/src/test/ui/nll/closure-requirements/escape-upvar-ref.rs @@ -19,7 +19,7 @@ // `'b`. This relationship is propagated to the closure creator, // which reports an error. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![feature(rustc_attrs)] diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs index 30a6dfc5b3edd..e7ec0b9684d2c 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.rs @@ -11,7 +11,7 @@ // Test where we fail to approximate due to demanding a postdom // relationship between our upper bounds. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![feature(rustc_attrs)] @@ -53,7 +53,7 @@ fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell |_outlives1, _outlives2, _outlives3, x, y| { // Only works if 'x: 'y: let p = x.get(); - //~^ WARN not reporting region error due to -Znll + //~^ WARN not reporting region error due to nll //~| ERROR does not outlive free region demand_y(x, y, p) }, diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index 0c058e40a5086..ef5a31e40d445 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/propagate-approximated-fail-no-postdom.rs:55:21 | LL | let p = x.get(); @@ -16,7 +16,7 @@ note: No external requirements LL | / |_outlives1, _outlives2, _outlives3, x, y| { LL | | // Only works if 'x: 'y: LL | | let p = x.get(); -LL | | //~^ WARN not reporting region error due to -Znll +LL | | //~^ WARN not reporting region error due to nll LL | | //~| ERROR does not outlive free region LL | | demand_y(x, y, p) LL | | }, diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs index 91128035f3d95..da8ce55162f37 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.rs @@ -22,7 +22,7 @@ // Note: the use of `Cell` here is to introduce invariance. One less // variable. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![feature(rustc_attrs)] @@ -54,7 +54,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { //~^ ERROR lifetime mismatch // Only works if 'x: 'y: - demand_y(x, y, x.get()) //~ WARNING not reporting region error due to -Znll + demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll }); } diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr index 947b95b1c5321..3a3236fd16c49 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -1,7 +1,7 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/propagate-approximated-ref.rs:57:9 | -LL | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to -Znll +LL | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll | ^^^^^^^^^^^^^^^^^^^^^^^ note: External requirements @@ -12,7 +12,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, LL | | //~^ ERROR lifetime mismatch LL | | LL | | // Only works if 'x: 'y: -LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to -Znll +LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll LL | | }); | |_____^ | diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs index f210346a82a67..84bfd6ea4f253 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.rs @@ -12,7 +12,7 @@ // where `'x` is bound in closure type but `'a` is free. This forces // us to approximate `'x` one way or the other. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![feature(rustc_attrs)] @@ -29,7 +29,7 @@ fn case1() { let a = 0; let cell = Cell::new(&a); foo(cell, |cell_a, cell_x| { - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure //~^ ERROR does not outlive free region }) diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index d39cdc34471ab..6480cbe443127 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:5 | LL | foo(cell, |cell_a, cell_x| { @@ -15,7 +15,7 @@ note: No external requirements | LL | foo(cell, |cell_a, cell_x| { | _______________^ -LL | | //~^ WARNING not reporting region error due to -Znll +LL | | //~^ WARNING not reporting region error due to nll LL | | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure LL | | //~^ ERROR does not outlive free region LL | | }) diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs index c66472d5ce9b1..df715c52921a0 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs @@ -16,7 +16,7 @@ // FIXME(#45827) Because of shortcomings in the MIR type checker, // these errors are not (yet) reported. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![feature(rustc_attrs)] @@ -46,7 +46,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { //~^ ERROR does not outlive free region // Only works if 'x: 'y: - demand_y(x, y, x.get()) //~ WARNING not reporting region error due to -Znll + demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll }); } diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index 3131142ec73bf..6dcc8421177d9 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -1,7 +1,7 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:49:9 | -LL | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to -Znll +LL | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll | ^^^^^^^^^^^^^^^^^^^^^^^ note: External requirements @@ -12,7 +12,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { LL | | //~^ ERROR does not outlive free region LL | | LL | | // Only works if 'x: 'y: -LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to -Znll +LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll LL | | }); | |_____^ | @@ -31,7 +31,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { LL | | //~^ ERROR does not outlive free region LL | | LL | | // Only works if 'x: 'y: -LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to -Znll +LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll LL | | }); | |_____^ diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs index f4011a0e5335e..fdbb312572f89 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs @@ -17,7 +17,7 @@ // FIXME(#45827) Because of shortcomings in the MIR type checker, // these errors are not (yet) reported. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![feature(rustc_attrs)] @@ -49,7 +49,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { //~^ ERROR does not outlive free region // Only works if 'x: 'y: demand_y(x, y, x.get()) - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll }); } diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 5b038653b6068..1291f2e9901b0 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:51:9 | LL | demand_y(x, y, x.get()) @@ -12,7 +12,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, LL | | //~^ ERROR does not outlive free region LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) -LL | | //~^ WARNING not reporting region error due to -Znll +LL | | //~^ WARNING not reporting region error due to nll LL | | }); | |_____^ | @@ -31,7 +31,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, LL | | //~^ ERROR does not outlive free region LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) -LL | | //~^ WARNING not reporting region error due to -Znll +LL | | //~^ WARNING not reporting region error due to nll LL | | }); | |_____^ diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs index d163f304ae5b1..0449dc1d1a75c 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.rs @@ -15,7 +15,7 @@ // relationships. In the 'main' variant, there are a number of // anonymous regions as well. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![feature(rustc_attrs)] @@ -47,7 +47,7 @@ fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { //~^ ERROR lifetime mismatch // Only works if 'x: 'y: - demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to -Znll + demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to nll }); } diff --git a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr index 475fdd947817e..d1824a9415102 100644 --- a/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -1,7 +1,7 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/propagate-approximated-val.rs:50:9 | -LL | demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to -Znll +LL | demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to nll | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: External requirements @@ -12,7 +12,7 @@ LL | establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| LL | | //~^ ERROR lifetime mismatch LL | | LL | | // Only works if 'x: 'y: -LL | | demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to -Znll +LL | | demand_y(outlives1, outlives2, x.get()) //~ WARNING not reporting region error due to nll LL | | }); | |_____^ | diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs index 1ccfa61f4ce46..c21c824b22c3b 100644 --- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs +++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.rs @@ -13,7 +13,7 @@ // need to propagate; but in fact we do because identity of free // regions is erased. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose // compile-pass #![feature(rustc_attrs)] diff --git a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr index ab4faaca75633..d6eeda881daf2 100644 --- a/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-despite-same-free-region.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/propagate-despite-same-free-region.rs:54:21 | LL | let p = x.get(); diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs index eb512a3b9b1fb..7699d10173495 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.rs @@ -17,7 +17,7 @@ // as it knows of no relationships between `'x` and any // non-higher-ranked regions. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![feature(rustc_attrs)] @@ -45,7 +45,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { // Only works if 'x: 'y: demand_y(x, y, x.get()) - //~^ WARN not reporting region error due to -Znll + //~^ WARN not reporting region error due to nll //~| ERROR does not outlive free region }); } diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index ce808f56b4297..ffae47bd081c3 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9 | LL | demand_y(x, y, x.get()) @@ -17,7 +17,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | _______________________________________________^ LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) -LL | | //~^ WARN not reporting region error due to -Znll +LL | | //~^ WARN not reporting region error due to nll LL | | //~| ERROR does not outlive free region LL | | }); | |_____^ diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs index 9307424642972..afb61b221be94 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.rs @@ -17,7 +17,7 @@ // as it only knows of regions that `'x` is outlived by, and none that // `'x` outlives. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![feature(rustc_attrs)] @@ -49,7 +49,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { // Only works if 'x: 'y: demand_y(x, y, x.get()) - //~^ WARN not reporting region error due to -Znll + //~^ WARN not reporting region error due to nll //~| ERROR does not outlive free region }); } diff --git a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index 547ff75bac62c..01af756b8332c 100644 --- a/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9 | LL | demand_y(x, y, x.get()) @@ -17,7 +17,7 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, | _______________________________________________^ LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) -LL | | //~^ WARN not reporting region error due to -Znll +LL | | //~^ WARN not reporting region error due to nll LL | | //~| ERROR does not outlive free region LL | | }); | |_____^ diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs index 91796355752a5..7baf24f88f8fa 100644 --- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs +++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.rs @@ -14,7 +14,7 @@ // the same `'a` for which it implements `Trait`, which can only be the `'a` // from the function definition. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![feature(rustc_attrs)] #![allow(dead_code)] @@ -53,7 +53,7 @@ where // The latter does not hold. require(value); - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll }); } diff --git a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr index 5bdfc7e935fea..a8b4ed528015f 100644 --- a/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr +++ b/src/test/ui/nll/closure-requirements/propagate-from-trait-match.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/propagate-from-trait-match.rs:55:9 | LL | require(value); @@ -13,7 +13,7 @@ LL | | //~^ ERROR the parameter type `T` may not live long enough LL | | LL | | // This function call requires that ... | -LL | | //~^ WARNING not reporting region error due to -Znll +LL | | //~^ WARNING not reporting region error due to nll LL | | }); | |_____^ | @@ -35,7 +35,7 @@ LL | | //~^ ERROR the parameter type `T` may not live long enough LL | | LL | | // This function call requires that ... | -LL | | //~^ WARNING not reporting region error due to -Znll +LL | | //~^ WARNING not reporting region error due to nll LL | | }); | |_____^ | diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs index ac21fe25bd112..a6b2e531ac28f 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs +++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs @@ -13,11 +13,11 @@ // a variety of errors from the older, AST-based machinery (notably // borrowck), and then we get the NLL error at the end. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose fn foo(x: &u32) -> &'static u32 { &*x - //~^ WARN not reporting region error due to -Znll + //~^ WARN not reporting region error due to nll //~| ERROR explicit lifetime required in the type of `x` } diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr index 1e93ae1ee07c6..a823e62d3b843 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr +++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5 | LL | &*x diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs index a1be8e8518515..dedbd8df41b13 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs +++ b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.rs @@ -13,11 +13,11 @@ // a variety of errors from the older, AST-based machinery (notably // borrowck), and then we get the NLL error at the end. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose fn foo<'a>(x: &'a u32) -> &'static u32 { &*x - //~^ WARN not reporting region error due to -Znll + //~^ WARN not reporting region error due to nll //~| ERROR does not outlive free region } diff --git a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr index ac3bf4b459fec..9520b446303c3 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr +++ b/src/test/ui/nll/closure-requirements/region-lbr-named-does-not-outlive-static.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5 | LL | &*x diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs index 00b09e2ab21ad..8598668bef50e 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs +++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs @@ -13,11 +13,11 @@ // a variety of errors from the older, AST-based machinery (notably // borrowck), and then we get the NLL error at the end. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 { &*x - //~^ WARN not reporting region error due to -Znll + //~^ WARN not reporting region error due to nll //~| ERROR lifetime mismatch } diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr index 3af6d7d21f753..415aefdeee947 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr +++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:19:5 | LL | &*x diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs index 7454a8e71f270..6d2bb30980236 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs +++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-outlive-lbr2-because-implied-bound.rs @@ -11,7 +11,7 @@ // Basic test for free regions in the NLL code. This test does not // report an error because of the (implied) bound that `'b: 'a`. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose // compile-pass #![allow(warnings)] diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs index 754df4f2c5db6..60f82ca0eefb9 100644 --- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs +++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.rs @@ -12,14 +12,14 @@ // the first, but actually returns the second. This should fail within // the closure. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![feature(rustc_attrs)] #[rustc_regions] fn test() { expect_sig(|a, b| b); // ought to return `a` - //~^ WARN not reporting region error due to -Znll + //~^ WARN not reporting region error due to nll //~| ERROR does not outlive free region } diff --git a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr index b34f4c470df49..4d021fb545494 100644 --- a/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr +++ b/src/test/ui/nll/closure-requirements/return-wrong-bound-region.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/return-wrong-bound-region.rs:21:23 | LL | expect_sig(|a, b| b); // ought to return `a` @@ -26,7 +26,7 @@ note: No external requirements | LL | / fn test() { LL | | expect_sig(|a, b| b); // ought to return `a` -LL | | //~^ WARN not reporting region error due to -Znll +LL | | //~^ WARN not reporting region error due to nll LL | | //~| ERROR does not outlive free region LL | | } | |_^ diff --git a/src/test/ui/nll/constant.rs b/src/test/ui/nll/constant.rs index 589d8ffd28f0b..10ce0652d43c2 100644 --- a/src/test/ui/nll/constant.rs +++ b/src/test/ui/nll/constant.rs @@ -11,7 +11,7 @@ // Test that MIR borrowck and NLL analysis can handle constants of // arbitrary types without ICEs. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose // compile-pass const HI: &str = "hi"; diff --git a/src/test/ui/nll/drop-may-dangle.rs b/src/test/ui/nll/drop-may-dangle.rs index 6dcbe0a528d90..b357b3facf9bb 100644 --- a/src/test/ui/nll/drop-may-dangle.rs +++ b/src/test/ui/nll/drop-may-dangle.rs @@ -12,7 +12,7 @@ // in the type of `p` includes the points after `&v[0]` up to (but not // including) the call to `use_x`. The `else` branch is not included. -// compile-flags:-Znll -Zborrowck=mir +// compile-flags:-Zborrowck=mir // compile-pass #![allow(warnings)] diff --git a/src/test/ui/nll/drop-no-may-dangle.rs b/src/test/ui/nll/drop-no-may-dangle.rs index e5478e39fecca..513609316311a 100644 --- a/src/test/ui/nll/drop-no-may-dangle.rs +++ b/src/test/ui/nll/drop-no-may-dangle.rs @@ -13,7 +13,7 @@ // because of destructor. (Note that the stderr also identifies this // destructor in the error message.) -// compile-flags:-Znll -Zborrowck=mir +// compile-flags:-Zborrowck=mir #![allow(warnings)] #![feature(dropck_eyepatch)] diff --git a/src/test/ui/nll/get_default.rs b/src/test/ui/nll/get_default.rs index e5944e75e4241..728c84695eacf 100644 --- a/src/test/ui/nll/get_default.rs +++ b/src/test/ui/nll/get_default.rs @@ -13,7 +13,7 @@ // a variety of errors from the older, AST-based machinery (notably // borrowck), and then we get the NLL error at the end. -// compile-flags:-Znll -Zborrowck=compare +// compile-flags:-Zborrowck=compare struct Map { } diff --git a/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs b/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs index d4df2a01c8143..5538eca362974 100644 --- a/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs +++ b/src/test/ui/nll/maybe-initialized-drop-implicit-fragment-drop.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll +//compile-flags: -Z emit-end-regions -Zborrowck=mir #![allow(warnings)] diff --git a/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs b/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs index 7e8a4e0ec95fc..ae815a5efe97c 100644 --- a/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs +++ b/src/test/ui/nll/maybe-initialized-drop-uninitialized.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//compile-flags: -Z emit-end-regions -Zborrowck=mir -Z nll +// compile-flags: -Z emit-end-regions -Zborrowck=mir // compile-pass #![allow(warnings)] diff --git a/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs b/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs index 2eb90dca7026e..00d146e0f02d6 100644 --- a/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs +++ b/src/test/ui/nll/maybe-initialized-drop-with-fragment.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll +//compile-flags: -Z emit-end-regions -Zborrowck=mir #![allow(warnings)] diff --git a/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs index f639d8f243f14..cd46014a7f5ca 100644 --- a/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs +++ b/src/test/ui/nll/maybe-initialized-drop-with-uninitialized-fragments.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll +//compile-flags: -Z emit-end-regions -Zborrowck=mir #![allow(warnings)] diff --git a/src/test/ui/nll/maybe-initialized-drop.rs b/src/test/ui/nll/maybe-initialized-drop.rs index c2cc479d28e3e..9a3aca346208d 100644 --- a/src/test/ui/nll/maybe-initialized-drop.rs +++ b/src/test/ui/nll/maybe-initialized-drop.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//compile-flags: -Z emit-end-regions -Zborrowck=mir -Znll +//compile-flags: -Z emit-end-regions -Zborrowck=mir #![allow(warnings)] diff --git a/src/test/ui/nll/projection-return.rs b/src/test/ui/nll/projection-return.rs index 1515911fe870e..c1abcb434e68f 100644 --- a/src/test/ui/nll/projection-return.rs +++ b/src/test/ui/nll/projection-return.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Znll -Zborrowck=mir +// compile-flags:-Zborrowck=mir // compile-pass #![feature(rustc_attrs)] diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs index 571bd9fd76e86..f21127064d4c2 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] @@ -19,7 +19,7 @@ impl<'a, T> Foo<'a> for T { } fn foo<'a, T>(x: &T) -> impl Foo<'a> { x - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR explicit lifetime required in the type of `x` [E0621] } diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr index 92e4f72da3a10..f836960a28cf3 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/impl-trait-captures.rs:21:5 | LL | x diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs index 2e0671f1a51e8..182e11da082f8 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs @@ -8,14 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] use std::fmt::Debug; fn no_region<'a, T>(x: Box) -> impl Debug + 'a - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll where T: Debug, { @@ -31,7 +31,7 @@ where } fn wrong_region<'a, 'b, T>(x: Box) -> impl Debug + 'a - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll where T: 'b + Debug, { diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr index 2b90d53774e65..50b80282e6241 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr @@ -1,10 +1,10 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/impl-trait-outlives.rs:17:35 | LL | fn no_region<'a, T>(x: Box) -> impl Debug + 'a | ^^^^^^^^^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/impl-trait-outlives.rs:33:42 | LL | fn wrong_region<'a, 'b, T>(x: Box) -> impl Debug + 'a diff --git a/src/test/ui/nll/ty-outlives/projection-implied-bounds.rs b/src/test/ui/nll/ty-outlives/projection-implied-bounds.rs index 0ec6d7b74ad5a..d8f077467d9fc 100644 --- a/src/test/ui/nll/ty-outlives/projection-implied-bounds.rs +++ b/src/test/ui/nll/ty-outlives/projection-implied-bounds.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose // Test that we can deduce when projections like `T::Item` outlive the // function body. Test that this does not imply that `T: 'a` holds. @@ -43,7 +43,7 @@ where #[rustc_errors] fn generic2(value: T) { twice(value, |value_ref, item| invoke2(value_ref, item)); - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR the parameter type `T` may not live long enough } diff --git a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr index fa53967ed3aca..0a2bd3247655a 100644 --- a/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr +++ b/src/test/ui/nll/ty-outlives/projection-implied-bounds.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-implied-bounds.rs:45:36 | LL | twice(value, |value_ref, item| invoke2(value_ref, item)); diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs index 0493bd1ea0d9c..7b3ed6a94fcbb 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose // Tests closures that propagate an outlives relationship to their // creator where the subject is a projection with no regions (`::Item` may not live long enough } @@ -52,7 +52,7 @@ where T: 'b + Iterator, { with_signature(x, |mut y| Box::new(y.next())) - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR the associated type `::Item` may not live long enough } diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr index bcdf984f65a8a..0efbbdff12a3f 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-closure.stderr @@ -1,10 +1,10 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-no-regions-closure.rs:36:31 | LL | with_signature(x, |mut y| Box::new(y.next())) | ^^^^^^^^^^^^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-no-regions-closure.rs:54:31 | LL | with_signature(x, |mut y| Box::new(y.next())) diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs index 5f2e84e247a3c..32b73a51e11a5 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] #![feature(dyn_trait)] @@ -22,7 +22,7 @@ where T: Iterator, { Box::new(x.next()) - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| the associated type `::Item` may not live long enough } @@ -38,7 +38,7 @@ where T: 'b + Iterator, { Box::new(x.next()) - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| the associated type `::Item` may not live long enough } diff --git a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr index 95851e7edc70c..b2c5f28268db8 100644 --- a/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr +++ b/src/test/ui/nll/ty-outlives/projection-no-regions-fn.stderr @@ -1,10 +1,10 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-no-regions-fn.rs:24:5 | LL | Box::new(x.next()) | ^^^^^^^^^^^^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-no-regions-fn.rs:40:5 | LL | Box::new(x.next()) diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs index 9a5e04deddfc9..cfe2880bfed47 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.rs @@ -22,7 +22,7 @@ // // Ensuring that both `T: 'a` and `'b: 'a` holds does work (`elements_outlive`). -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] #![feature(dyn_trait)] @@ -54,7 +54,7 @@ where T: Anything<'b>, { with_signature(cell, t, |cell, t| require(cell, t)); - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR the parameter type `T` may not live long enough //~| ERROR does not outlive free region } @@ -66,7 +66,7 @@ where 'a: 'a, { with_signature(cell, t, |cell, t| require(cell, t)); - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR the parameter type `T` may not live long enough //~| ERROR does not outlive free region } @@ -88,7 +88,7 @@ where // can do better here with a more involved verification step. with_signature(cell, t, |cell, t| require(cell, t)); - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR the parameter type `T` may not live long enough //~| ERROR free region `ReEarlyBound(1, 'b)` does not outlive free region `ReEarlyBound(0, 'a)` } diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr index aa45cf1870106..0d5a2dc7c5598 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -1,16 +1,16 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-one-region-closure.rs:56:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-one-region-closure.rs:68:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-one-region-closure.rs:90:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs index 232025b57355c..16e91f2708fe9 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.rs @@ -14,7 +14,7 @@ // case, the best way to satisfy the trait bound is to show that `'b: // 'a`, which can be done in various ways. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] #![feature(dyn_trait)] @@ -46,7 +46,7 @@ where T: Anything<'b>, { with_signature(cell, t, |cell, t| require(cell, t)); - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR does not outlive free region } @@ -57,7 +57,7 @@ where 'a: 'a, { with_signature(cell, t, |cell, t| require(cell, t)); - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR does not outlive free region } @@ -78,7 +78,7 @@ where // can do better here with a more involved verification step. with_signature(cell, t, |cell, t| require(cell, t)); - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR does not outlive free region } diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr index 7a8010ad8e0ea..d4aca8380b469 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr @@ -1,16 +1,16 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-one-region-trait-bound-closure.rs:48:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-one-region-trait-bound-closure.rs:59:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-one-region-trait-bound-closure.rs:80:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); diff --git a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs index a1bdd1b89f9a9..0d42636c844a5 100644 --- a/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs +++ b/src/test/ui/nll/ty-outlives/projection-one-region-trait-bound-static-closure.rs @@ -12,7 +12,7 @@ // outlive `'static`. In this case, we don't get any errors, and in fact // we don't even propagate constraints from the closures to the callers. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose // compile-pass #![allow(warnings)] diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs index e3cee00ed4eb3..7c8ef140a2907 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.rs @@ -15,7 +15,7 @@ // the trait bound, and hence we propagate it to the caller as a type // test. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] #![feature(dyn_trait)] @@ -47,7 +47,7 @@ where T: Anything<'b, 'c>, { with_signature(cell, t, |cell, t| require(cell, t)); - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR associated type `>::AssocType` may not live long enough } @@ -58,7 +58,7 @@ where 'a: 'a, { with_signature(cell, t, |cell, t| require(cell, t)); - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR associated type `>::AssocType` may not live long enough } @@ -79,7 +79,7 @@ where // can do better here with a more involved verification step. with_signature(cell, t, |cell, t| require(cell, t)); - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR associated type `>::AssocType` may not live long enough } @@ -107,7 +107,7 @@ where T: Anything<'b, 'b>, { with_signature(cell, t, |cell, t| require(cell, t)); - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR does not outlive free region } diff --git a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index c7cbdaec3395c..7e36e467e4eba 100644 --- a/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/src/test/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -1,22 +1,22 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-two-region-trait-bound-closure.rs:49:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-two-region-trait-bound-closure.rs:60:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-two-region-trait-bound-closure.rs:81:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/projection-two-region-trait-bound-closure.rs:109:39 | LL | with_signature(cell, t, |cell, t| require(cell, t)); diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs index 423747a6bd6cb..80b42c29563f1 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] #![feature(dyn_trait)] diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr index 997cc57cfa28c..c8feaddff9382 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-approximate-lower-bound.stderr @@ -1,16 +1,16 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ty-param-closure-approximate-lower-bound.rs:35:31 | LL | twice(cell, value, |a, b| invoke(a, b)); | ^^^^^^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:31 | LL | twice(cell, value, |a, b| invoke(a, b)); | ^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ty-param-closure-approximate-lower-bound.rs:43:31 | LL | twice(cell, value, |a, b| invoke(a, b)); diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs index 95a483b3c355d..50763a1d50808 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] #![feature(dyn_trait)] @@ -35,7 +35,7 @@ where // `'a` (and subsequently reports an error). with_signature(x, |y| y) - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR the parameter type `T` may not live long enough } @@ -51,7 +51,7 @@ where T: 'b + Debug, { x - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR the parameter type `T` may not live long enough } diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr index ba08bc1ff7b43..500595e0c5dca 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-return-type.stderr @@ -1,10 +1,10 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ty-param-closure-outlives-from-return-type.rs:37:27 | LL | with_signature(x, |y| y) | ^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ty-param-closure-outlives-from-return-type.rs:53:5 | LL | x diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs index 1149f250a46e2..b70fc2b2ec4b4 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.rs @@ -12,7 +12,7 @@ // `correct_region` for an explanation of how this test is setup; it's // somewhat intricate. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose #![allow(warnings)] #![feature(dyn_trait)] @@ -43,7 +43,7 @@ fn no_region<'a, T>(a: Cell<&'a ()>, b: T) { // function, there is no where clause *anywhere*, and hence we // get an error (but reported by the closure creator). require(&x, &y) - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll }) } @@ -77,7 +77,7 @@ where //~^ ERROR the parameter type `T` may not live long enough // See `correct_region` require(&x, &y) - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll }) } diff --git a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr index fcdb0b0a4a9fe..4d8a66ba8e1c4 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-closure-outlives-from-where-clause.stderr @@ -1,10 +1,10 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ty-param-closure-outlives-from-where-clause.rs:45:9 | LL | require(&x, &y) | ^^^^^^^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ty-param-closure-outlives-from-where-clause.rs:79:9 | LL | require(&x, &y) @@ -19,7 +19,7 @@ LL | | //~^ ERROR the parameter type `T` may not live long enough LL | | // LL | | // See `correct_region`, which explains the point of this ... | -LL | | //~^ WARNING not reporting region error due to -Znll +LL | | //~^ WARNING not reporting region error due to nll LL | | }) | |_____^ | @@ -40,7 +40,7 @@ LL | | //~^ ERROR the parameter type `T` may not live long enough LL | | // LL | | // See `correct_region`, which explains the point of this ... | -LL | | //~^ WARNING not reporting region error due to -Znll +LL | | //~^ WARNING not reporting region error due to nll LL | | }) | |_____^ | @@ -109,7 +109,7 @@ LL | with_signature(a, b, |x, y| { LL | | //~^ ERROR the parameter type `T` may not live long enough LL | | // See `correct_region` LL | | require(&x, &y) -LL | | //~^ WARNING not reporting region error due to -Znll +LL | | //~^ WARNING not reporting region error due to nll LL | | }) | |_____^ | @@ -130,7 +130,7 @@ LL | with_signature(a, b, |x, y| { LL | | //~^ ERROR the parameter type `T` may not live long enough LL | | // See `correct_region` LL | | require(&x, &y) -LL | | //~^ WARNING not reporting region error due to -Znll +LL | | //~^ WARNING not reporting region error due to nll LL | | }) | |_____^ | diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs b/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs index e66c1853b64b9..fb4ea63f8532c 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs +++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Znll -Zborrowck=mir +// compile-flags:-Zborrowck=mir // Test that we assume that universal types like `T` outlive the // function body. @@ -28,7 +28,7 @@ fn region_within_body(t: T) { // Error here, because T: 'a is not satisfied. fn region_static<'a, T>(cell: Cell<&'a usize>, t: T) { outlives(cell, t) - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| ERROR the parameter type `T` may not live long enough } diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr index 34ed709a2730e..0596861e67b57 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-fn-body.stderr @@ -1,4 +1,4 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ty-param-fn-body.rs:30:5 | LL | outlives(cell, t) diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.rs b/src/test/ui/nll/ty-outlives/ty-param-fn.rs index aa3a03afa35cd..42d662e14193c 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn.rs +++ b/src/test/ui/nll/ty-outlives/ty-param-fn.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Znll -Zborrowck=mir +// compile-flags:-Zborrowck=mir #![allow(warnings)] #![feature(dyn_trait)] @@ -20,7 +20,7 @@ where T: Debug, { x - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| the parameter type `T` may not live long enough } @@ -36,7 +36,7 @@ where T: 'b + Debug, { x - //~^ WARNING not reporting region error due to -Znll + //~^ WARNING not reporting region error due to nll //~| the parameter type `T` may not live long enough } diff --git a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr index 98ccfc52029ff..0d09cac8c3851 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-fn.stderr +++ b/src/test/ui/nll/ty-outlives/ty-param-fn.stderr @@ -1,10 +1,10 @@ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ty-param-fn.rs:22:5 | LL | x | ^ -warning: not reporting region error due to -Znll +warning: not reporting region error due to nll --> $DIR/ty-param-fn.rs:38:5 | LL | x diff --git a/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs b/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs index d4ae9b20e56ff..51927d353ecc4 100644 --- a/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs +++ b/src/test/ui/nll/ty-outlives/ty-param-implied-bounds.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// compile-flags:-Znll -Zborrowck=mir -Zverbose +// compile-flags:-Zborrowck=mir -Zverbose // compile-pass // Test that we assume that universal types like `T` outlive the diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index db0ac9279046c..f394a60ad9ffc 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1686,7 +1686,7 @@ impl<'test> TestCx<'test> { match self.config.compare_mode { Some(CompareMode::Nll) => { - rustc.args(&["-Znll", "-Zborrowck=mir", "-Ztwo-phase-borrows"]); + rustc.args(&["-Zborrowck=mir", "-Ztwo-phase-borrows"]); }, None => {}, } From 96dba9358c5ad24bc33eeb3a9a39a4868c331bcf Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 10 Apr 2018 09:11:31 -0400 Subject: [PATCH 16/16] s/`use_mir`/`use_mir_borrowck`/ --- src/librustc/infer/error_reporting/mod.rs | 2 +- src/librustc/ty/context.rs | 4 ++-- src/librustc_mir/borrow_check/mod.rs | 2 +- src/librustc_mir/borrow_check/nll/type_check/mod.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 254fba095e236..d8a2c95ab5904 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -303,7 +303,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { ) { debug!("report_region_errors(): {} errors to start", errors.len()); - if will_later_be_reported_by_nll && self.tcx.use_mir() { + if will_later_be_reported_by_nll && self.tcx.use_mir_borrowck() { // With `#![feature(nll)]`, we want to present a nice user // experience, so don't even mention the errors from the // AST checker. diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index c4a34b4101aeb..4bd3318017c5b 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -1473,7 +1473,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { /// If true, we should use the MIR-based borrowck (we may *also* use /// the AST-based borrowck). - pub fn use_mir(self) -> bool { + pub fn use_mir_borrowck(self) -> bool { self.borrowck_mode().use_mir() } @@ -1508,7 +1508,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn emit_end_regions(self) -> bool { self.sess.opts.debugging_opts.emit_end_regions || self.sess.opts.debugging_opts.mir_emit_validate > 0 || - self.use_mir() + self.use_mir_borrowck() } #[inline] diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 22550319a1c63..a5e398bc80154 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -73,7 +73,7 @@ fn mir_borrowck<'a, 'tcx>( let input_mir = tcx.mir_validated(def_id); debug!("run query mir_borrowck: {}", tcx.item_path_str(def_id)); - if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.use_mir() { + if !tcx.has_attr(def_id, "rustc_mir_borrowck") && !tcx.use_mir_borrowck() { return None; } 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 bdcff1a2d819c..5098e6a34f7e0 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -1596,7 +1596,7 @@ impl MirPass for TypeckMir { // When NLL is enabled, the borrow checker runs the typeck // itself, so we don't need this MIR pass anymore. - if tcx.use_mir() { + if tcx.use_mir_borrowck() { return; }