Skip to content

Commit 74ce76a

Browse files
committed
Treat assigning the destination of a call as an assignment
1 parent 092f03a commit 74ce76a

File tree

2 files changed

+42
-7
lines changed
  • src/librustc_mir/borrow_check/nll/region_infer

2 files changed

+42
-7
lines changed

src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs

Lines changed: 40 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use rustc::hir::def_id::DefId;
1414
use rustc::infer::error_reporting::nice_region_error::NiceRegionError;
1515
use rustc::infer::InferCtxt;
1616
use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKind};
17-
use rustc::ty::RegionVid;
17+
use rustc::ty::{TyCtxt, RegionVid};
1818
use rustc_data_structures::indexed_vec::IndexVec;
1919
use rustc_errors::Diagnostic;
2020
use std::collections::VecDeque;
@@ -67,6 +67,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
6767
fn best_blame_constraint(
6868
&self,
6969
mir: &Mir<'tcx>,
70+
tcx: TyCtxt<'_, '_, 'tcx>,
7071
from_region: RegionVid,
7172
target_test: impl Fn(RegionVid) -> bool,
7273
) -> (ConstraintCategory, Span, RegionVid) {
@@ -92,7 +93,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
9293
// Classify each of the constraints along the path.
9394
let mut categorized_path: Vec<(ConstraintCategory, Span)> = path
9495
.iter()
95-
.map(|&index| self.classify_constraint(index, mir))
96+
.map(|&index| self.classify_constraint(index, mir, tcx))
9697
.collect();
9798
debug!(
9899
"best_blame_constraint: categorized_path={:#?}",
@@ -231,6 +232,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
231232
&self,
232233
index: ConstraintIndex,
233234
mir: &Mir<'tcx>,
235+
tcx: TyCtxt<'_, '_, 'tcx>,
234236
) -> (ConstraintCategory, Span) {
235237
let constraint = self.constraints[index];
236238
debug!("classify_constraint: constraint={:?}", constraint);
@@ -254,7 +256,34 @@ impl<'tcx> RegionInferenceContext<'tcx> {
254256
debug!("classify_constraint: terminator.kind={:?}", terminator.kind);
255257
match terminator.kind {
256258
TerminatorKind::DropAndReplace { .. } => ConstraintCategory::Assignment,
257-
TerminatorKind::Call { .. } => ConstraintCategory::CallArgument,
259+
// Classify calls differently depending on whether or not
260+
// the sub region appears in the destination type (so the
261+
// sup region is in the return type). If the return type
262+
// contains the sub-region, then this is either an
263+
// assignment or a return, depending on whether we are
264+
// writing to the RETURN_PLACE or not.
265+
//
266+
// The idea here is that the region is being propagated
267+
// from an input into the output place, so it's a kind of
268+
// assignment. Otherwise, if the sub-region only appears in
269+
// the argument types, then use the CallArgument
270+
// classification.
271+
TerminatorKind::Call { destination: Some((ref place, _)), .. } => {
272+
if tcx.any_free_region_meets(
273+
&place.ty(mir, tcx).to_ty(tcx),
274+
|region| self.to_region_vid(region) == constraint.sub,
275+
) {
276+
match place {
277+
Place::Local(mir::RETURN_PLACE) => ConstraintCategory::Return,
278+
_ => ConstraintCategory::Assignment,
279+
}
280+
} else {
281+
ConstraintCategory::CallArgument
282+
}
283+
}
284+
TerminatorKind::Call { destination: None, .. } => {
285+
ConstraintCategory::CallArgument
286+
}
258287
_ => ConstraintCategory::Other,
259288
}
260289
} else {
@@ -304,7 +333,12 @@ impl<'tcx> RegionInferenceContext<'tcx> {
304333
) {
305334
debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
306335

307-
let (category, span, _) = self.best_blame_constraint(mir, fr, |r| r == outlived_fr);
336+
let (category, span, _) = self.best_blame_constraint(
337+
mir,
338+
infcx.tcx,
339+
fr,
340+
|r| r == outlived_fr
341+
);
308342

309343
// Check if we can use one of the "nice region errors".
310344
if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) {
@@ -446,10 +480,11 @@ impl<'tcx> RegionInferenceContext<'tcx> {
446480
crate fn find_outlives_blame_span(
447481
&self,
448482
mir: &Mir<'tcx>,
483+
tcx: TyCtxt<'_, '_, 'tcx>,
449484
fr1: RegionVid,
450485
fr2: RegionVid,
451486
) -> Span {
452-
let (_, span, _) = self.best_blame_constraint(mir, fr1, |r| r == fr2);
487+
let (_, span, _) = self.best_blame_constraint(mir, tcx, fr1, |r| r == fr2);
453488
span
454489
}
455490
}

src/librustc_mir/borrow_check/nll/region_infer/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,7 +1040,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
10401040
longer_fr, shorter_fr,
10411041
);
10421042

1043-
let blame_span = self.find_outlives_blame_span(mir, longer_fr, shorter_fr);
1043+
let blame_span = self.find_outlives_blame_span(mir, infcx.tcx, longer_fr, shorter_fr);
10441044

10451045
if let Some(propagated_outlives_requirements) = propagated_outlives_requirements {
10461046
// Shrink `fr` until we find a non-local region (if we do).
@@ -1128,7 +1128,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
11281128
};
11291129

11301130
// Find the code to blame for the fact that `longer_fr` outlives `error_fr`.
1131-
let span = self.find_outlives_blame_span(mir, longer_fr, error_region);
1131+
let span = self.find_outlives_blame_span(mir, infcx.tcx, longer_fr, error_region);
11321132

11331133
// Obviously, this error message is far from satisfactory.
11341134
// At present, though, it only appears in unit tests --

0 commit comments

Comments
 (0)