diff options
| author | Santiago Pastorino <spastorino@gmail.com> | 2018-07-01 19:43:01 -0300 |
|---|---|---|
| committer | Santiago Pastorino <spastorino@gmail.com> | 2018-07-01 20:46:07 -0300 |
| commit | 0957ede5027c0bffe208904998675a17bfd4cd59 (patch) | |
| tree | c453480ba2599e5f99cd5e4c099d4bedc112ed74 /src | |
| parent | 24f91e878244990595649120f402cc13263ae54f (diff) | |
| download | rust-0957ede5027c0bffe208904998675a17bfd4cd59.tar.gz rust-0957ede5027c0bffe208904998675a17bfd4cd59.zip | |
Make causal tracking lazy
Diffstat (limited to 'src')
14 files changed, 225 insertions, 319 deletions
diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index dec37bdf719..dca0d4f442a 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -1000,6 +1000,10 @@ impl<'tcx> Terminator<'tcx> { self.kind.successors_mut() } + pub fn unwind(&self) -> Option<&Option<BasicBlock>> { + self.kind.unwind() + } + pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> { self.kind.unwind_mut() } @@ -1195,6 +1199,31 @@ impl<'tcx> TerminatorKind<'tcx> { } } + pub fn unwind(&self) -> Option<&Option<BasicBlock>> { + match *self { + TerminatorKind::Goto { .. } + | TerminatorKind::Resume + | TerminatorKind::Abort + | TerminatorKind::Return + | TerminatorKind::Unreachable + | TerminatorKind::GeneratorDrop + | TerminatorKind::Yield { .. } + | TerminatorKind::SwitchInt { .. } + | TerminatorKind::FalseEdges { .. } => None, + TerminatorKind::Call { + cleanup: ref unwind, + .. + } + | TerminatorKind::Assert { + cleanup: ref unwind, + .. + } + | TerminatorKind::DropAndReplace { ref unwind, .. } + | TerminatorKind::Drop { ref unwind, .. } + | TerminatorKind::FalseUnwind { ref unwind, .. } => Some(unwind), + } + } + pub fn unwind_mut(&mut self) -> Option<&mut Option<BasicBlock>> { match *self { TerminatorKind::Goto { .. } diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs index 68aa9aeabf8..25a0123755f 100644 --- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs @@ -12,7 +12,7 @@ use borrow_check::borrow_set::BorrowSet; use borrow_check::location::LocationTable; use borrow_check::nll::ToRegionVid; use borrow_check::nll::facts::AllFacts; -use borrow_check::nll::region_infer::{Cause, RegionInferenceContext}; +use borrow_check::nll::region_infer::RegionInferenceContext; use borrow_check::nll::type_check::AtLocation; use rustc::hir; use rustc::infer::InferCtxt; @@ -33,7 +33,7 @@ pub(super) fn generate_constraints<'cx, 'gcx, 'tcx>( location_table: &LocationTable, mir: &Mir<'tcx>, borrow_set: &BorrowSet<'tcx>, - liveness_set_from_typeck: &[(ty::Region<'tcx>, Location, Cause)], + liveness_set_from_typeck: &[(ty::Region<'tcx>, Location)], ) { let mut cg = ConstraintGeneration { borrow_set, @@ -69,14 +69,14 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx /// We sometimes have `substs` within an rvalue, or within a /// call. Make them live at the location where they appear. fn visit_substs(&mut self, substs: &&'tcx Substs<'tcx>, location: Location) { - self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location)); + self.add_regular_live_constraint(*substs, location); self.super_substs(substs); } /// We sometimes have `region` within an rvalue, or within a /// call. Make them live at the location where they appear. fn visit_region(&mut self, region: &ty::Region<'tcx>, location: Location) { - self.add_regular_live_constraint(*region, location, Cause::LiveOther(location)); + self.add_regular_live_constraint(*region, location); self.super_region(region); } @@ -94,7 +94,7 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx ); } TyContext::Location(location) => { - self.add_regular_live_constraint(*ty, location, Cause::LiveOther(location)); + self.add_regular_live_constraint(*ty, location); } } @@ -104,14 +104,14 @@ impl<'cg, 'cx, 'gcx, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'cx, 'gcx /// We sometimes have `generator_substs` within an rvalue, or within a /// call. Make them live at the location where they appear. fn visit_generator_substs(&mut self, substs: &GeneratorSubsts<'tcx>, location: Location) { - self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location)); + self.add_regular_live_constraint(*substs, location); self.super_generator_substs(substs); } /// We sometimes have `closure_substs` within an rvalue, or within a /// call. Make them live at the location where they appear. fn visit_closure_substs(&mut self, substs: &ClosureSubsts<'tcx>, location: Location) { - self.add_regular_live_constraint(*substs, location, Cause::LiveOther(location)); + self.add_regular_live_constraint(*substs, location); self.super_closure_substs(substs); } @@ -233,7 +233,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> { /// that we also have to respect. fn add_region_liveness_constraints_from_type_check( &mut self, - liveness_set: &[(ty::Region<'tcx>, Location, Cause)], + liveness_set: &[(ty::Region<'tcx>, Location)], ) { debug!( "add_region_liveness_constraints_from_type_check(liveness_set={} items)", @@ -247,16 +247,16 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> { .. } = self; - for (region, location, cause) in liveness_set { + for (region, location) in liveness_set { debug!("generate: {:#?} is live at {:#?}", region, location); let region_vid = regioncx.to_region_vid(region); - regioncx.add_live_point(region_vid, *location, &cause); + regioncx.add_live_point(region_vid, *location); } if let Some(all_facts) = all_facts { all_facts .region_live_at - .extend(liveness_set.into_iter().flat_map(|(region, location, _)| { + .extend(liveness_set.into_iter().flat_map(|(region, location)| { let r = regioncx.to_region_vid(region); let p1 = location_table.start_index(*location); let p2 = location_table.mid_index(*location); @@ -269,7 +269,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> { /// `location` -- i.e., it may be used later. This means that all /// regions appearing in the type `live_ty` must be live at /// `location`. - fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location, cause: Cause) + fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location) where T: TypeFoldable<'tcx>, { @@ -282,7 +282,7 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> { .tcx .for_each_free_region(&live_ty, |live_region| { let vid = live_region.to_region_vid(); - self.regioncx.add_live_point(vid, location, &cause); + self.regioncx.add_live_point(vid, location); }); } diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs index 58e9d814826..a65019690e3 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/find_use.rs @@ -8,50 +8,32 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use borrow_check::borrow_set::BorrowData; -use borrow_check::nll::region_infer::RegionInferenceContext; +use std::collections::VecDeque; +use std::rc::Rc; + +use borrow_check::nll::region_infer::{Cause, RegionInferenceContext}; +use borrow_check::nll::ToRegionVid; use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor}; use rustc::mir::{Local, Location, Mir}; +use rustc::ty::{RegionVid, TyCtxt}; use rustc_data_structures::fx::FxHashSet; use util::liveness::{self, DefUse, LivenessMode}; -crate fn regular_use<'gcx, 'tcx>( - mir: &'gcx Mir, - regioncx: &'tcx RegionInferenceContext, - borrow: &'tcx BorrowData, +crate fn find<'cx, 'gcx: 'tcx, 'tcx: 'cx>( + mir: &'cx Mir<'tcx>, + regioncx: &'cx Rc<RegionInferenceContext<'tcx>>, + tcx: TyCtxt<'cx, 'gcx, 'tcx>, + region_vid: RegionVid, start_point: Location, - local: Local, -) -> Option<Location> { +) -> Option<Cause> { let mut uf = UseFinder { mir, regioncx, - borrow, + tcx, + region_vid, start_point, - local, liveness_mode: LivenessMode { include_regular_use: true, - include_drops: false, - }, - }; - - uf.find() -} - -crate fn drop_use<'gcx, 'tcx>( - mir: &'gcx Mir, - regioncx: &'tcx RegionInferenceContext, - borrow: &'tcx BorrowData, - start_point: Location, - local: Local, -) -> Option<Location> { - let mut uf = UseFinder { - mir, - regioncx, - borrow, - start_point, - local, - liveness_mode: LivenessMode { - include_regular_use: false, include_drops: true, }, }; @@ -59,23 +41,23 @@ crate fn drop_use<'gcx, 'tcx>( uf.find() } -struct UseFinder<'gcx, 'tcx> { - mir: &'gcx Mir<'gcx>, - regioncx: &'tcx RegionInferenceContext<'tcx>, - borrow: &'tcx BorrowData<'tcx>, +struct UseFinder<'cx, 'gcx: 'tcx, 'tcx: 'cx> { + mir: &'cx Mir<'tcx>, + regioncx: &'cx Rc<RegionInferenceContext<'tcx>>, + tcx: TyCtxt<'cx, 'gcx, 'tcx>, + region_vid: RegionVid, start_point: Location, - local: Local, liveness_mode: LivenessMode, } -impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> { - fn find(&mut self) -> Option<Location> { - let mut stack = vec![]; +impl<'cx, 'gcx, 'tcx> UseFinder<'cx, 'gcx, 'tcx> { + fn find(&mut self) -> Option<Cause> { + let mut queue = VecDeque::new(); let mut visited = FxHashSet(); - stack.push(self.start_point); - while let Some(p) = stack.pop() { - if !self.regioncx.region_contains_point(self.borrow.region, p) { + queue.push_back(self.start_point); + while let Some(p) = queue.pop_front() { + if !self.regioncx.region_contains_point(self.region_vid, p) { continue; } @@ -84,23 +66,36 @@ impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> { } let block_data = &self.mir[p.block]; - let (defined, used) = self.def_use(p, block_data.visitable(p.statement_index)); - - if used { - return Some(p); - } else if !defined { - if p.statement_index < block_data.statements.len() { - stack.push(Location { - statement_index: p.statement_index + 1, - ..p - }); - } else { - stack.extend(block_data.terminator().successors().map(|&basic_block| { - Location { - statement_index: 0, - block: basic_block, - } - })); + + match self.def_use(p, block_data.visitable(p.statement_index)) { + Some(DefUseResult::Def) => {} + + Some(DefUseResult::UseLive { local }) => { + return Some(Cause::LiveVar(local, p)); + } + + Some(DefUseResult::UseDrop { local }) => { + return Some(Cause::DropVar(local, p)); + } + + None => { + if p.statement_index < block_data.statements.len() { + queue.push_back(Location { + statement_index: p.statement_index + 1, + ..p + }); + } else { + queue.extend( + block_data + .terminator() + .successors() + .filter(|&bb| Some(&Some(*bb)) != block_data.terminator().unwind()) + .map(|&bb| Location { + statement_index: 0, + block: bb, + }), + ); + } } } } @@ -108,34 +103,65 @@ impl<'gcx, 'tcx> UseFinder<'gcx, 'tcx> { None } - fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> (bool, bool) { + fn def_use(&self, location: Location, thing: &dyn MirVisitable<'tcx>) -> Option<DefUseResult> { let mut visitor = DefUseVisitor { - defined: false, - used: false, - local: self.local, + mir: self.mir, + tcx: self.tcx, + region_vid: self.region_vid, liveness_mode: self.liveness_mode, + def_use_result: None, }; thing.apply(location, &mut visitor); - (visitor.defined, visitor.used) + visitor.def_use_result } } -struct DefUseVisitor { - defined: bool, - used: bool, - local: Local, +struct DefUseVisitor<'cx, 'gcx: 'tcx, 'tcx: 'cx> { + mir: &'cx Mir<'tcx>, + tcx: TyCtxt<'cx, 'gcx, 'tcx>, + region_vid: RegionVid, liveness_mode: LivenessMode, + def_use_result: Option<DefUseResult>, +} + +enum DefUseResult { + Def, + + UseLive { local: Local }, + + UseDrop { local: Local }, } -impl<'tcx> Visitor<'tcx> for DefUseVisitor { +impl<'cx, 'gcx, 'tcx> Visitor<'tcx> for DefUseVisitor<'cx, 'gcx, 'tcx> { fn visit_local(&mut self, &local: &Local, context: PlaceContext<'tcx>, _: Location) { - if local == self.local { + let local_ty = self.mir.local_decls[local].ty; + + let mut found_it = false; + self.tcx.for_each_free_region(&local_ty, |r| { + if r.to_region_vid() == self.region_vid { + found_it = true; + } + }); + + if found_it { match liveness::categorize(context, self.liveness_mode) { - Some(DefUse::Def) => self.defined = true, - Some(DefUse::Use) => self.used = true, - None => (), + Some(DefUse::Def) => { + self.def_use_result = Some(DefUseResult::Def); + } + + Some(DefUse::Use) => { + self.def_use_result = if context.is_drop() { + Some(DefUseResult::UseDrop { local }) + } else { + Some(DefUseResult::UseLive { local }) + }; + } + + None => { + self.def_use_result = None; + } } } } 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 acc164b14c3..bc4646b7c78 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -38,87 +38,72 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { kind_place: Option<(WriteKind, &Place<'tcx>)>, err: &mut DiagnosticBuilder<'_>, ) { - let regioncx = &&self.nonlexical_regioncx; + debug!( + "explain_why_borrow_contains_point(context={:?}, borrow={:?}, kind_place={:?})", + context, borrow, kind_place, + ); + + let regioncx = &self.nonlexical_regioncx; let mir = self.mir; + let tcx = self.tcx; let borrow_region_vid = regioncx.to_region_vid(borrow.region); - if let Some(cause) = regioncx.why_region_contains_point(borrow_region_vid, context.loc) { - match cause { - Cause::LiveVar(local, location) => match find_use::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" - ); - } - }, + debug!( + "explain_why_borrow_contains_point: borrow_region_vid={:?}", + borrow_region_vid + ); - Cause::DropVar(local, location) => match find_use::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), - ); + let region_sub = regioncx.find_constraint(borrow_region_vid, context.loc); - if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place { - if let Place::Local(borrowed_local) = place { - let dropped_local_scope = - mir.local_decls[local].visibility_scope; - let borrowed_local_scope = - mir.local_decls[*borrowed_local].visibility_scope; + debug!( + "explain_why_borrow_contains_point: region_sub={:?}", + region_sub + ); - if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope) { - err.note( - "values in a scope are dropped \ - in the opposite order they are defined", - ); - } - } - } - } - None => { - err.span_label( - mir.local_decls[local].source_info.span, - "borrow may end up in a temporary, created here", - ); + match find_use::find(mir, regioncx, tcx, region_sub, context.loc) { + Some(Cause::LiveVar(_local, location)) => { + err.span_label( + mir.source_info(location).span, + format!("borrow later used here"), + ); + } - err.span_label( - mir.source_info(p).span, - "temporary later dropped here, \ - potentially using the reference", - ); - } - }, + Some(Cause::DropVar(local, location)) => match &mir.local_decls[local].name { + Some(local_name) => { + err.span_label( + mir.source_info(location).span, + format!("borrow later used here, when `{}` is dropped", local_name), + ); - None => { - span_bug!( - mir.source_info(context.loc).span, - "Cause should end in a DropVar" - ); - } - }, + if let Some((WriteKind::StorageDeadOrDrop, place)) = kind_place { + if let Place::Local(borrowed_local) = place { + let dropped_local_scope = mir.local_decls[local].visibility_scope; + let borrowed_local_scope = + mir.local_decls[*borrowed_local].visibility_scope; - 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, - "...", - ); + if mir.is_sub_scope(borrowed_local_scope, dropped_local_scope) { + err.note( + "values in a scope are dropped \ + in the opposite order they are defined", + ); + } + } } } - _ => {} + None => {} + }, + + None => { + if let Some(region) = regioncx.to_error_region(region_sub) { + self.tcx.note_and_explain_free_region( + err, + "borrowed value must be valid for ", + region, + "...", + ); + } } } } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting.rs index 970652d8872..6543516b9c2 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting.rs @@ -9,7 +9,7 @@ // except according to those terms. use std::fmt; -use borrow_check::nll::region_infer::{Cause, ConstraintIndex, RegionInferenceContext}; +use borrow_check::nll::region_infer::{ConstraintIndex, RegionInferenceContext}; use borrow_check::nll::region_infer::values::ToElementIndex; use borrow_check::nll::type_check::Locations; use rustc::hir::def_id::DefId; @@ -259,15 +259,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - crate fn why_region_contains_point(&self, fr1: RegionVid, elem: Location) -> Option<Cause> { - // Find some constraint `X: Y` where: - // - `fr1: X` transitively - // - and `Y` is live at `elem` + // Find some constraint `X: Y` where: + // - `fr1: X` transitively + // - and `Y` is live at `elem` + crate fn find_constraint(&self, fr1: RegionVid, elem: Location) -> RegionVid { let index = self.blame_constraint(fr1, elem); - let region_sub = self.constraints[index].sub; - - // then return why `Y` was live at `elem` - self.liveness_constraints.cause(region_sub, elem) + self.constraints[index].sub } /// Tries to finds a good span to blame for the fact that `fr1` diff --git a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs index 014b37a0a27..fd6d79d160e 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -75,8 +75,6 @@ pub struct RegionInferenceContext<'tcx> { universal_regions: UniversalRegions<'tcx>, } -struct TrackCauses(bool); - struct RegionDefinition<'tcx> { /// Why we created this variable. Mostly these will be /// `RegionVariableOrigin::NLL`, but some variables get created @@ -105,13 +103,6 @@ pub(crate) enum Cause { /// point inserted because Local was dropped at the given Location DropVar(Local, Location), - - /// point inserted because the type was live at the given Location, - /// but not as part of some local variable - LiveOther(Location), - - /// part of the initial set of values for a universally quantified region - UniversalRegion(RegionVid), } /// A "type test" corresponds to an outlives constraint between a type @@ -283,7 +274,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.liveness_constraints.add_element( variable, point_index, - &Cause::UniversalRegion(variable), ); } @@ -291,7 +281,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.liveness_constraints.add_element( variable, variable, - &Cause::UniversalRegion(variable), ); } } @@ -337,13 +326,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// /// Returns `true` if this constraint is new and `false` is the /// constraint was already present. - pub(super) fn add_live_point(&mut self, v: RegionVid, point: Location, cause: &Cause) -> bool { + pub(super) fn add_live_point(&mut self, v: RegionVid, point: Location) -> bool { debug!("add_live_point({:?}, {:?})", v, point); assert!(self.inferred_values.is_none(), "values already inferred"); - debug!("add_live_point: @{:?} Adding cause {:?}", point, cause); let element = self.elements.index(point); - self.liveness_constraints.add_element(v, element, &cause) + self.liveness_constraints.add_element(v, element) } /// Indicates that the region variable `sup` must outlive `sub` is live at the point `point`. @@ -436,7 +424,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // The initial values for each region are derived from the liveness // constraints we have accumulated. - let mut inferred_values = self.liveness_constraints.duplicate(TrackCauses(false)); + let mut inferred_values = self.liveness_constraints.clone(); let dependency_map = self.dependency_map.as_ref().unwrap(); diff --git a/src/librustc_mir/borrow_check/nll/region_infer/values.rs b/src/librustc_mir/borrow_check/nll/region_infer/values.rs index e914be52db0..5be4297f660 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/values.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/values.rs @@ -8,18 +8,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use borrow_check::nll::region_infer::TrackCauses; use rustc::mir::{BasicBlock, Location, Mir}; use rustc::ty::RegionVid; use rustc_data_structures::bitvec::SparseBitMatrix; -use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexed_vec::Idx; use rustc_data_structures::indexed_vec::IndexVec; use std::fmt::Debug; use std::rc::Rc; -use super::Cause; - /// Maps between the various kinds of elements of a region value to /// the internal indices that w use. pub(super) struct RegionValueElements { @@ -180,19 +176,12 @@ impl ToElementIndex for RegionElementIndex { /// compact `SparseBitMatrix` representation, with one row per region /// variable. The columns consist of either universal regions or /// points in the CFG. +#[derive(Clone)] pub(super) struct RegionValues { elements: Rc<RegionValueElements>, matrix: SparseBitMatrix<RegionVid, RegionElementIndex>, - - /// If cause tracking is enabled, maps from a pair (r, e) - /// consisting of a region `r` that contains some element `e` to - /// the reason that the element is contained. There should be an - /// entry for every bit set to 1 in `SparseBitMatrix`. - causes: Option<CauseMap>, } -type CauseMap = FxHashMap<(RegionVid, RegionElementIndex), Cause>; - impl RegionValues { /// Creates a new set of "region values" that tracks causal information. /// Each of the regions in num_region_variables will be initialized with an @@ -209,25 +198,6 @@ impl RegionValues { RegionVid::new(num_region_variables), RegionElementIndex::new(elements.num_elements()), ), - causes: Some(CauseMap::default()), - } - } - - /// Duplicates the region values. If track_causes is false, then the - /// resulting value will not track causal information (and any existing - /// causal information is dropped). Otherwise, the causal information is - /// preserved and maintained. Tracking the causal information makes region - /// propagation significantly slower, so we prefer not to do it until an - /// error is reported. - pub(super) fn duplicate(&self, track_causes: TrackCauses) -> Self { - Self { - elements: self.elements.clone(), - matrix: self.matrix.clone(), - causes: if track_causes.0 { - self.causes.clone() - } else { - None - }, } } @@ -237,10 +207,10 @@ impl RegionValues { &mut self, r: RegionVid, elem: E, - cause: &Cause, ) -> bool { let i = self.elements.index(elem); - self.add_internal(r, i, |_| cause.clone()) + debug!("add(r={:?}, elem={:?})", r, elem); + self.matrix.add(r, i) } /// Add all elements in `r_from` to `r_to` (because e.g. `r_to: @@ -249,40 +219,6 @@ impl RegionValues { self.matrix.merge(r_from, r_to) } - /// Internal method to add an element to a region. - /// - /// Takes a "lazy" cause -- this function will return the cause, but it will only - /// be invoked if cause tracking is enabled. - fn add_internal<F>(&mut self, r: RegionVid, i: RegionElementIndex, make_cause: F) -> bool - where - F: FnOnce(&CauseMap) -> Cause, - { - if self.matrix.add(r, i) { - debug!("add(r={:?}, i={:?})", r, self.elements.to_element(i)); - - if let Some(causes) = &mut self.causes { - let cause = make_cause(causes); - causes.insert((r, i), cause); - } - - true - } else { - if let Some(causes) = &mut self.causes { - let cause = make_cause(causes); - let old_cause = causes.get_mut(&(r, i)).unwrap(); - // #49998: compare using root cause alone to avoid - // useless traffic from similar outlives chains. - - if cause < *old_cause { - *old_cause = cause; - return true; - } - } - - false - } - } - /// True if the region `r` contains the given element. pub(super) fn contains<E: ToElementIndex>(&self, r: RegionVid, elem: E) -> bool { let i = self.elements.index(elem); @@ -398,18 +334,4 @@ impl RegionValues { )); } } - - /// Given a region `r` that contains the element `elem`, returns the `Cause` - /// that tells us *why* `elem` is found in that region. - /// - /// Returns None if cause tracking is disabled or `elem` is not - /// actually found in `r`. - pub(super) fn cause<T: ToElementIndex>(&self, r: RegionVid, elem: T) -> Option<Cause> { - let index = self.elements.index(elem); - if let Some(causes) = &self.causes { - causes.get(&(r, index)).cloned() - } else { - None - } - } } diff --git a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs index d84dcc56782..dbdfef21970 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/liveness.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/liveness.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use borrow_check::nll::region_infer::Cause; use borrow_check::nll::type_check::AtLocation; use dataflow::move_paths::{HasMoveData, MoveData}; use dataflow::MaybeInitializedPlaces; @@ -88,8 +87,7 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo .simulate_block(self.mir, bb, |location, live_locals| { for live_local in live_locals.iter() { let live_local_ty = self.mir.local_decls[live_local].ty; - let cause = Cause::LiveVar(live_local, location); - Self::push_type_live_constraint(&mut self.cx, live_local_ty, location, cause); + Self::push_type_live_constraint(&mut self.cx, live_local_ty, location); } }); @@ -161,7 +159,6 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo cx: &mut TypeChecker<'_, 'gcx, 'tcx>, value: T, location: Location, - cause: Cause, ) where T: TypeFoldable<'tcx>, { @@ -173,7 +170,7 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo cx.tcx().for_each_free_region(&value, |live_region| { cx.constraints .liveness_set - .push((live_region, location, cause.clone())); + .push((live_region, location)); }); } @@ -210,9 +207,8 @@ impl<'gen, 'typeck, 'flow, 'gcx, 'tcx> TypeLivenessGenerator<'gen, 'typeck, 'flo // All things in the `outlives` array may be touched by // the destructor and must be live at this point. - let cause = Cause::DropVar(dropped_local, location); for &kind in &drop_data.dropck_result.kinds { - Self::push_type_live_constraint(&mut self.cx, kind, location, cause); + Self::push_type_live_constraint(&mut self.cx, kind, location); } } 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 e3d20d9a8db..d5cf55c0f77 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -14,7 +14,6 @@ use borrow_check::location::LocationTable; use borrow_check::nll::constraint_set::ConstraintSet; use borrow_check::nll::facts::AllFacts; -use borrow_check::nll::region_infer::Cause; use borrow_check::nll::region_infer::{ClosureRegionRequirementsExt, TypeTest}; use borrow_check::nll::universal_regions::UniversalRegions; use dataflow::move_paths::MoveData; @@ -615,7 +614,7 @@ crate struct MirTypeckRegionConstraints<'tcx> { /// not otherwise appear in the MIR -- in particular, the /// late-bound regions that it instantiates at call-sites -- and /// hence it must report on their liveness constraints. - crate liveness_set: Vec<(ty::Region<'tcx>, Location, Cause)>, + crate liveness_set: Vec<(ty::Region<'tcx>, Location)>, crate outlives_constraints: ConstraintSet, @@ -986,7 +985,6 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { self.constraints.liveness_set.push(( late_bound_region, term_location, - Cause::LiveOther(term_location), )); } diff --git a/src/test/ui/generator/borrowing.nll.stderr b/src/test/ui/generator/borrowing.nll.stderr index 243e9018585..015538b16f9 100644 --- a/src/test/ui/generator/borrowing.nll.stderr +++ b/src/test/ui/generator/borrowing.nll.stderr @@ -2,15 +2,10 @@ error[E0597]: `a` does not live long enough --> $DIR/borrowing.rs:18:18 | LL | unsafe { (|| yield &a).resume() } - | ^^^^^^^^^^^^^ - | | - | borrowed value does not live long enough - | borrow may end up in a temporary, created here + | ^^^^^^^^^^^^^ borrowed value does not live long enough LL | //~^ ERROR: `a` does not live long enough LL | }; - | -- temporary later dropped here, potentially using the reference - | | - | borrowed value only lives until here + | - borrowed value only lives until here error[E0597]: `a` does not live long enough --> $DIR/borrowing.rs:24:9 diff --git a/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr index 70870b98365..08839c23c37 100644 --- a/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr +++ b/src/test/ui/generator/ref-escapes-but-not-over-yield.nll.stderr @@ -1,19 +1,11 @@ error[E0597]: `b` does not live long enough --> $DIR/ref-escapes-but-not-over-yield.rs:24:13 | -LL | let mut b = move || { - | _________________- -LL | | yield(); -LL | | let b = 5; -LL | | a = &b; - | | ^^ borrowed value does not live long enough -LL | | //~^ ERROR `b` does not live long enough -LL | | }; - | | - - | | | - | | borrowed value only lives until here - | |_____temporary later dropped here, potentially using the reference - | borrow may end up in a temporary, created here +LL | a = &b; + | ^^ borrowed value does not live long enough +LL | //~^ ERROR `b` does not live long enough +LL | }; + | - borrowed value only lives until here error: aborting due to previous error diff --git a/src/test/ui/issue-47646.stderr b/src/test/ui/issue-47646.stderr index b1289146e0e..4bdce85d18b 100644 --- a/src/test/ui/issue-47646.stderr +++ b/src/test/ui/issue-47646.stderr @@ -3,15 +3,9 @@ error[E0502]: cannot borrow `heap` as immutable because it is also borrowed as m | LL | let borrow = heap.peek_mut(); | ---- mutable borrow occurs here -LL | -LL | match (borrow, ()) { - | ------------ borrow may end up in a temporary, created here -LL | (Some(_), ()) => { +... LL | println!("{:?}", heap); //~ ERROR cannot borrow `heap` as immutable | ^^^^ immutable borrow occurs here -... -LL | }; - | - temporary later dropped here, potentially using the reference error: aborting due to previous error diff --git a/src/test/ui/span/destructor-restrictions.nll.stderr b/src/test/ui/span/destructor-restrictions.nll.stderr index 5de246cbb73..8be4cf445da 100644 --- a/src/test/ui/span/destructor-restrictions.nll.stderr +++ b/src/test/ui/span/destructor-restrictions.nll.stderr @@ -2,14 +2,9 @@ error[E0597]: `*a` does not live long enough --> $DIR/destructor-restrictions.rs:18:10 | LL | *a.borrow() + 1 - | ^--------- - | | - | borrowed value does not live long enough - | borrow may end up in a temporary, created here + | ^ borrowed value does not live long enough LL | }; //~^ ERROR `*a` does not live long enough - | -- temporary later dropped here, potentially using the reference - | | - | borrowed value only lives until here + | - borrowed value only lives until here error: aborting due to previous error diff --git a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr index 56f2d14390e..ec2f5a25631 100644 --- a/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr +++ b/src/test/ui/span/issue-23338-locals-die-before-temps-of-body.nll.stderr @@ -2,28 +2,17 @@ error[E0597]: `y` does not live long enough --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:20:5 | LL | y.borrow().clone() - | ^--------- - | | - | borrowed value does not live long enough - | borrow may end up in a temporary, created here + | ^ borrowed value does not live long enough LL | } - | - - | | - | borrowed value only lives until here - | temporary later dropped here, potentially using the reference + | - borrowed value only lives until here error[E0597]: `y` does not live long enough --> $DIR/issue-23338-locals-die-before-temps-of-body.rs:27:9 | LL | y.borrow().clone() - | ^--------- - | | - | borrowed value does not live long enough - | borrow may end up in a temporary, created here + | ^ borrowed value does not live long enough LL | }; - | -- temporary later dropped here, potentially using the reference - | | - | borrowed value only lives until here + | - borrowed value only lives until here error: aborting due to 2 previous errors |
