diff options
| author | Matthew Jasper <mjjasper1@gmail.com> | 2018-08-07 21:30:01 +0100 |
|---|---|---|
| committer | Matthew Jasper <mjjasper1@gmail.com> | 2018-08-14 20:35:46 +0100 |
| commit | 74ce76a00964bc648b3639ea565359e477b7002b (patch) | |
| tree | 6f444185afe908b19c06a60176914c74dfc17f11 | |
| parent | 092f03a07aa075c6b5cfecc47a8be6e133073819 (diff) | |
| download | rust-74ce76a00964bc648b3639ea565359e477b7002b.tar.gz rust-74ce76a00964bc648b3639ea565359e477b7002b.zip | |
Treat assigning the destination of a call as an assignment
| -rw-r--r-- | src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs | 45 | ||||
| -rw-r--r-- | src/librustc_mir/borrow_check/nll/region_infer/mod.rs | 4 |
2 files changed, 42 insertions, 7 deletions
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs index c2670389e2d..3a83db3ad6a 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs @@ -14,7 +14,7 @@ use rustc::hir::def_id::DefId; use rustc::infer::error_reporting::nice_region_error::NiceRegionError; use rustc::infer::InferCtxt; use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKind}; -use rustc::ty::RegionVid; +use rustc::ty::{TyCtxt, RegionVid}; use rustc_data_structures::indexed_vec::IndexVec; use rustc_errors::Diagnostic; use std::collections::VecDeque; @@ -67,6 +67,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn best_blame_constraint( &self, mir: &Mir<'tcx>, + tcx: TyCtxt<'_, '_, 'tcx>, from_region: RegionVid, target_test: impl Fn(RegionVid) -> bool, ) -> (ConstraintCategory, Span, RegionVid) { @@ -92,7 +93,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Classify each of the constraints along the path. let mut categorized_path: Vec<(ConstraintCategory, Span)> = path .iter() - .map(|&index| self.classify_constraint(index, mir)) + .map(|&index| self.classify_constraint(index, mir, tcx)) .collect(); debug!( "best_blame_constraint: categorized_path={:#?}", @@ -231,6 +232,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, index: ConstraintIndex, mir: &Mir<'tcx>, + tcx: TyCtxt<'_, '_, 'tcx>, ) -> (ConstraintCategory, Span) { let constraint = self.constraints[index]; debug!("classify_constraint: constraint={:?}", constraint); @@ -254,7 +256,34 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!("classify_constraint: terminator.kind={:?}", terminator.kind); match terminator.kind { TerminatorKind::DropAndReplace { .. } => ConstraintCategory::Assignment, - TerminatorKind::Call { .. } => ConstraintCategory::CallArgument, + // Classify calls differently depending on whether or not + // the sub region appears in the destination type (so the + // sup region is in the return type). If the return type + // contains the sub-region, then this is either an + // assignment or a return, depending on whether we are + // writing to the RETURN_PLACE or not. + // + // The idea here is that the region is being propagated + // from an input into the output place, so it's a kind of + // assignment. Otherwise, if the sub-region only appears in + // the argument types, then use the CallArgument + // classification. + TerminatorKind::Call { destination: Some((ref place, _)), .. } => { + if tcx.any_free_region_meets( + &place.ty(mir, tcx).to_ty(tcx), + |region| self.to_region_vid(region) == constraint.sub, + ) { + match place { + Place::Local(mir::RETURN_PLACE) => ConstraintCategory::Return, + _ => ConstraintCategory::Assignment, + } + } else { + ConstraintCategory::CallArgument + } + } + TerminatorKind::Call { destination: None, .. } => { + ConstraintCategory::CallArgument + } _ => ConstraintCategory::Other, } } else { @@ -304,7 +333,12 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) { debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr); - let (category, span, _) = self.best_blame_constraint(mir, fr, |r| r == outlived_fr); + let (category, span, _) = self.best_blame_constraint( + mir, + infcx.tcx, + fr, + |r| r == outlived_fr + ); // Check if we can use one of the "nice region errors". 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> { crate fn find_outlives_blame_span( &self, mir: &Mir<'tcx>, + tcx: TyCtxt<'_, '_, 'tcx>, fr1: RegionVid, fr2: RegionVid, ) -> Span { - let (_, span, _) = self.best_blame_constraint(mir, fr1, |r| r == fr2); + let (_, span, _) = self.best_blame_constraint(mir, tcx, fr1, |r| r == fr2); span } } 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 f7dfa5a7ae5..ebcc044093a 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -1040,7 +1040,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { longer_fr, shorter_fr, ); - let blame_span = self.find_outlives_blame_span(mir, longer_fr, shorter_fr); + let blame_span = self.find_outlives_blame_span(mir, infcx.tcx, longer_fr, shorter_fr); if let Some(propagated_outlives_requirements) = propagated_outlives_requirements { // Shrink `fr` until we find a non-local region (if we do). @@ -1128,7 +1128,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }; // Find the code to blame for the fact that `longer_fr` outlives `error_fr`. - let span = self.find_outlives_blame_span(mir, longer_fr, error_region); + let span = self.find_outlives_blame_span(mir, infcx.tcx, longer_fr, error_region); // Obviously, this error message is far from satisfactory. // At present, though, it only appears in unit tests -- |
