Make causal tracking lazy

上级 24f91e87
......@@ -1000,6 +1000,10 @@ pub fn successors_mut(&mut self) -> SuccessorsMut {
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 @@ pub fn successors_mut(&mut self) -> SuccessorsMut {
}
}
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 { .. }
......
......@@ -12,7 +12,7 @@
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 @@ fn visit_basic_block_data(&mut self, bb: BasicBlock, data: &BasicBlockData<'tcx>
/// 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 @@ fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) {
);
}
TyContext::Location(location) => {
self.add_regular_live_constraint(*ty, location, Cause::LiveOther(location));
self.add_regular_live_constraint(*ty, location);
}
}
......@@ -104,14 +104,14 @@ fn visit_ty(&mut self, ty: &ty::Ty<'tcx>, ty_context: TyContext) {
/// 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 @@ fn add_region_liveness_constraints_from_type_check(
..
} = 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 @@ fn add_region_liveness_constraints_from_type_check(
/// `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 @@ fn add_regular_live_constraint<T>(&mut self, live_ty: T, location: Location, cau
.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);
});
}
......
......@@ -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 @@
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 @@ fn find(&mut self) -> Option<Location> {
}
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 @@ fn find(&mut self) -> Option<Location> {
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;
}
}
}
}
......
......@@ -38,87 +38,72 @@ pub(in borrow_check) fn explain_why_borrow_contains_point(
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,
"...",
);
}
}
}
}
......
......@@ -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 @@ pub(super) fn report_error(
}
}
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`
......
......@@ -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 @@ fn init_universal_regions(&mut self) {
self.liveness_constraints.add_element(
variable,
point_index,
&Cause::UniversalRegion(variable),
);
}
......@@ -291,7 +281,6 @@ fn init_universal_regions(&mut self) {
self.liveness_constraints.add_element(
variable,
variable,
&Cause::UniversalRegion(variable),
);
}
}
......@@ -337,13 +326,12 @@ pub fn region_contains_point<R>(&self, r: R, p: Location) -> bool
///
/// 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 @@ fn compute_region_values(&self, _mir: &Mir<'tcx>) -> RegionValues {
// 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();
......
......@@ -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 @@ fn to_element_index(self, _elements: &RegionValueElements) -> 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 @@ pub(super) fn new(elements: &Rc<RegionValueElements>, num_region_variables: usiz
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 @@ pub(super) fn add_element<E: ToElementIndex>(
&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 @@ pub(super) fn add_region(&mut self, r_to: RegionVid, r_from: RegionVid) -> bool
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 @@ fn push_location_range(str: &mut String, location1: Location, location2: Locatio
));
}
}
/// 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
}
}
}
......@@ -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 @@ fn add_liveness_constraints(&mut self, bb: BasicBlock) {
.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 @@ fn push_type_live_constraint<T>(
cx: &mut TypeChecker<'_, 'gcx, 'tcx>,
value: T,
location: Location,
cause: Cause,
) where
T: TypeFoldable<'tcx>,
{
......@@ -173,7 +170,7 @@ fn push_type_live_constraint<T>(
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 @@ fn add_drop_live_constraint(
// 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);
}
}
......
......@@ -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 @@ struct BorrowCheckContext<'a, 'tcx: 'a> {
/// 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 @@ fn check_terminator(
self.constraints.liveness_set.push((
late_bound_region,
term_location,
Cause::LiveOther(term_location),
));
}
......
......@@ -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
......
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
......
......@@ -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
......
......@@ -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
......
......@@ -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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册