From ea0224f5ab5e0fce6f83ae395c30058dcd434be7 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 3 Jul 2018 05:28:49 -0400 Subject: [PATCH 01/10] error_report: rustfmt --- .../nll/region_infer/error_reporting.rs | 107 ++++++++++++------ 1 file changed, 72 insertions(+), 35 deletions(-) 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 6543516b9c2c6..fdeb1c47ea6e6 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 @@ -8,17 +8,18 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt; -use borrow_check::nll::region_infer::{ConstraintIndex, RegionInferenceContext}; use borrow_check::nll::region_infer::values::ToElementIndex; +use borrow_check::nll::region_infer::{Cause, ConstraintIndex, RegionInferenceContext}; +use borrow_check::nll::region_infer::{ConstraintIndex, RegionInferenceContext}; use borrow_check::nll::type_check::Locations; use rustc::hir::def_id::DefId; -use rustc::infer::InferCtxt; use rustc::infer::error_reporting::nice_region_error::NiceRegionError; -use rustc::mir::{self, Location, Mir, Place, StatementKind, TerminatorKind, Rvalue}; +use rustc::infer::InferCtxt; +use rustc::mir::{self, Location, Mir, Place, Rvalue, StatementKind, TerminatorKind}; use rustc::ty::RegionVid; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::indexed_vec::IndexVec; +use std::fmt; use syntax_pos::Span; /// Constraints that are considered interesting can be categorized to @@ -50,16 +51,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// When reporting an error, it is useful to be able to determine which constraints influenced /// the region being reported as an error. This function finds all of the paths from the /// constraint. - fn find_constraint_paths_from_region( - &self, - r0: RegionVid - ) -> Vec> { + fn find_constraint_paths_from_region(&self, r0: RegionVid) -> Vec> { let constraints = self.constraints.clone(); // Mapping of regions to the previous region and constraint index that led to it. let mut previous = FxHashMap(); // Regions yet to be visited. - let mut next = vec! [ r0 ]; + let mut next = vec![r0]; // Regions that have been visited. let mut visited = FxHashSet(); // Ends of paths. @@ -68,8 +66,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { // When we've still got points to visit... while let Some(current) = next.pop() { // ...take the next point... - debug!("find_constraint_paths_from_region: current={:?} visited={:?} next={:?}", - current, visited, next); + debug!( + "find_constraint_paths_from_region: current={:?} visited={:?} next={:?}", + current, visited, next + ); // ...but make sure not to visit this point again... visited.insert(current); @@ -78,8 +78,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { for (index, constraint) in constraints.iter_enumerated() { if constraint.sub == current { // ...add the regions that join us with to the path we've taken... - debug!("find_constraint_paths_from_region: index={:?} constraint={:?}", - index, constraint); + debug!( + "find_constraint_paths_from_region: index={:?} constraint={:?}", + index, constraint + ); let next_region = constraint.sup.clone(); // ...unless we've visited it since this was added... @@ -95,27 +97,41 @@ impl<'tcx> RegionInferenceContext<'tcx> { if upcoming.is_empty() { // If we didn't find any edges then this is the end of a path... - debug!("find_constraint_paths_from_region: new end region current={:?}", current); + debug!( + "find_constraint_paths_from_region: new end region current={:?}", + current + ); end_regions.insert(current); } else { // ...but, if we did find edges, then add these to the regions yet to visit. - debug!("find_constraint_paths_from_region: extend next upcoming={:?}", upcoming); + debug!( + "find_constraint_paths_from_region: extend next upcoming={:?}", + upcoming + ); next.extend(upcoming); } - } // Now we've visited each point, compute the final paths. let mut paths: Vec> = Vec::new(); - debug!("find_constraint_paths_from_region: end_regions={:?}", end_regions); + debug!( + "find_constraint_paths_from_region: end_regions={:?}", + end_regions + ); for end_region in end_regions { - debug!("find_constraint_paths_from_region: end_region={:?}", end_region); + debug!( + "find_constraint_paths_from_region: end_region={:?}", + end_region + ); // Get the constraint and region that led to this end point. // We can unwrap as we know if end_point was in the vector that it // must also be in our previous map. let (mut index, mut region) = previous.get(&end_region).unwrap(); - debug!("find_constraint_paths_from_region: index={:?} region={:?}", index, region); + debug!( + "find_constraint_paths_from_region: index={:?} region={:?}", + index, region + ); // Keep track of the indices. let mut path: Vec = vec![index]; @@ -125,7 +141,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { index = p.0; region = p.1; - debug!("find_constraint_paths_from_region: index={:?} region={:?}", index, region); + debug!( + "find_constraint_paths_from_region: index={:?} region={:?}", + index, region + ); path.push(index); } @@ -140,16 +159,28 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// This function will return true if a constraint is interesting and false if a constraint /// is not. It is useful in filtering constraint paths to only interesting points. fn constraint_is_interesting(&self, index: &ConstraintIndex) -> bool { - self.constraints.get(*index).filter(|constraint| { - debug!("constraint_is_interesting: locations={:?} constraint={:?}", - constraint.locations, constraint); - if let Locations::Interesting(_) = constraint.locations { true } else { false } - }).is_some() + self.constraints + .get(*index) + .filter(|constraint| { + debug!( + "constraint_is_interesting: locations={:?} constraint={:?}", + constraint.locations, constraint + ); + if let Locations::Interesting(_) = constraint.locations { + true + } else { + false + } + }) + .is_some() } /// This function classifies a constraint from a location. - fn classify_constraint(&self, index: &ConstraintIndex, - mir: &Mir<'tcx>) -> Option<(ConstraintCategory, Span)> { + fn classify_constraint( + &self, + index: &ConstraintIndex, + mir: &Mir<'tcx>, + ) -> Option<(ConstraintCategory, Span)> { let constraint = self.constraints.get(*index)?; let span = constraint.locations.span(mir); let location = constraint.locations.from_location()?; @@ -182,7 +213,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { _ => ConstraintCategory::Other, } } - }, + } _ => ConstraintCategory::Other, } }; @@ -234,9 +265,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { let path = constraints.iter().min_by_key(|p| p.len()).unwrap(); debug!("report_error: shortest_path={:?}", path); - let mut categorized_path = path.iter().filter_map(|index| { - self.classify_constraint(index, mir) - }).collect::>(); + let mut categorized_path = path.iter() + .filter_map(|index| self.classify_constraint(index, mir)) + .collect::>(); debug!("report_error: categorized_path={:?}", categorized_path); categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0)); @@ -244,8 +275,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { if let Some((category, span)) = &categorized_path.first() { let mut diag = infcx.tcx.sess.struct_span_err( - *span, &format!("{} requires that data must outlive {}", - category, outlived_fr_string), + *span, + &format!( + "{} requires that data must outlive {}", + category, outlived_fr_string + ), ); diag.emit(); @@ -269,8 +303,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Tries to finds a good span to blame for the fact that `fr1` /// contains `fr2`. - pub(super) fn blame_constraint(&self, fr1: RegionVid, - elem: impl ToElementIndex) -> ConstraintIndex { + pub(super) fn blame_constraint( + &self, + fr1: RegionVid, + elem: impl ToElementIndex, + ) -> ConstraintIndex { // Find everything that influenced final value of `fr`. let influenced_fr1 = self.dependencies(fr1); From 09f431fad5b8d67f278aa3130d3eccd0cd526cce Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 3 Jul 2018 05:29:11 -0400 Subject: [PATCH 02/10] simplify and cleanup error-reporting walk code --- .../nll/region_infer/error_reporting.rs | 216 ++++++++---------- 1 file changed, 95 insertions(+), 121 deletions(-) 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 fdeb1c47ea6e6..d8258afc24f62 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 @@ -17,7 +17,7 @@ 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_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::indexed_vec::IndexVec; use std::fmt; use syntax_pos::Span; @@ -48,140 +48,107 @@ impl fmt::Display for ConstraintCategory { } impl<'tcx> RegionInferenceContext<'tcx> { - /// When reporting an error, it is useful to be able to determine which constraints influenced - /// the region being reported as an error. This function finds all of the paths from the + /// Walks the graph of constraints (where `'a: 'b` is considered + /// an edge `'b -> 'a`) to find all paths from `from_region` to + /// `to_region`. The paths are accumulated into the vector + /// `results`. The paths are stored as a series of + /// `ConstraintIndex` values -- in other words, a list of *edges*. + /// + /// # Parameters + /// + /// - `from_region` + /// When reporting an error, it is useful to be able to determine + /// which constraints influenced the region being reported as an + /// error. This function finds all of the paths from the /// constraint. - fn find_constraint_paths_from_region(&self, r0: RegionVid) -> Vec> { - let constraints = self.constraints.clone(); - - // Mapping of regions to the previous region and constraint index that led to it. - let mut previous = FxHashMap(); - // Regions yet to be visited. - let mut next = vec![r0]; - // Regions that have been visited. - let mut visited = FxHashSet(); - // Ends of paths. - let mut end_regions = FxHashSet(); - - // When we've still got points to visit... - while let Some(current) = next.pop() { - // ...take the next point... - debug!( - "find_constraint_paths_from_region: current={:?} visited={:?} next={:?}", - current, visited, next - ); - // ...but make sure not to visit this point again... - visited.insert(current); - - // ...find the edges containing it... - let mut upcoming = Vec::new(); - for (index, constraint) in constraints.iter_enumerated() { - if constraint.sub == current { - // ...add the regions that join us with to the path we've taken... - debug!( - "find_constraint_paths_from_region: index={:?} constraint={:?}", - index, constraint - ); - let next_region = constraint.sup.clone(); - - // ...unless we've visited it since this was added... - if visited.contains(&next_region) { - debug!("find_constraint_paths_from_region: skipping as visited"); - continue; - } + fn find_constraint_paths_between_regions( + &self, + from_region: RegionVid, + to_region: RegionVid, + ) -> Vec> { + let mut results = vec![]; + self.find_constraint_paths_between_regions_helper( + from_region, + from_region, + to_region, + &mut FxHashSet::default(), + &mut vec![], + &mut results, + ); + results + } - previous.insert(next_region, (index, Some(current))); - upcoming.push(next_region); - } - } + /// Helper for `find_constraint_paths_between_regions`. + fn find_constraint_paths_between_regions_helper( + &self, + from_region: RegionVid, + current_region: RegionVid, + to_region: RegionVid, + visited: &mut FxHashSet, + stack: &mut Vec, + results: &mut Vec>, + ) { + let dependency_map = self.dependency_map.as_ref().unwrap(); - if upcoming.is_empty() { - // If we didn't find any edges then this is the end of a path... - debug!( - "find_constraint_paths_from_region: new end region current={:?}", - current - ); - end_regions.insert(current); - } else { - // ...but, if we did find edges, then add these to the regions yet to visit. - debug!( - "find_constraint_paths_from_region: extend next upcoming={:?}", - upcoming - ); - next.extend(upcoming); - } + // Check if we already visited this region. + if !visited.insert(current_region) { + return; } - // Now we've visited each point, compute the final paths. - let mut paths: Vec> = Vec::new(); - debug!( - "find_constraint_paths_from_region: end_regions={:?}", - end_regions - ); - for end_region in end_regions { - debug!( - "find_constraint_paths_from_region: end_region={:?}", - end_region - ); + // Check if we reached the region we were looking for. + if current_region == to_region { + // Unless we started out searching for `'a ~> 'a`, which shouldn't have caused + // en error, then we must have traversed at least *some* constraint: + assert!(!stack.is_empty()); - // Get the constraint and region that led to this end point. - // We can unwrap as we know if end_point was in the vector that it - // must also be in our previous map. - let (mut index, mut region) = previous.get(&end_region).unwrap(); - debug!( - "find_constraint_paths_from_region: index={:?} region={:?}", - index, region - ); - - // Keep track of the indices. - let mut path: Vec = vec![index]; - - while region.is_some() && region != Some(r0) { - let p = previous.get(®ion.unwrap()).unwrap(); - index = p.0; - region = p.1; + // The first constraint should be like `X: from_region`. + assert_eq!(self.constraints[stack[0]].sub, from_region); - debug!( - "find_constraint_paths_from_region: index={:?} region={:?}", - index, region - ); - path.push(index); - } + // The last constraint should be like `to_region: Y`. + assert_eq!(self.constraints[*stack.last().unwrap()].sup, to_region); - // Add to our paths. - paths.push(path); + results.push(stack.clone()); + return; } - debug!("find_constraint_paths_from_region: paths={:?}", paths); - paths + self.constraints + .each_affected_by_dirty(dependency_map[current_region], |constraint| { + assert_eq!(self.constraints[constraint].sub, current_region); + stack.push(constraint); + self.find_constraint_paths_between_regions_helper( + from_region, + self.constraints[constraint].sup, + to_region, + visited, + stack, + results, + ); + stack.pop(); + }); } /// This function will return true if a constraint is interesting and false if a constraint /// is not. It is useful in filtering constraint paths to only interesting points. - fn constraint_is_interesting(&self, index: &ConstraintIndex) -> bool { - self.constraints - .get(*index) - .filter(|constraint| { - debug!( - "constraint_is_interesting: locations={:?} constraint={:?}", - constraint.locations, constraint - ); - if let Locations::Interesting(_) = constraint.locations { - true - } else { - false - } - }) - .is_some() + fn constraint_is_interesting(&self, index: ConstraintIndex) -> bool { + let constraint = self.constraints[index]; + debug!( + "constraint_is_interesting: locations={:?} constraint={:?}", + constraint.locations, constraint + ); + if let Locations::Interesting(_) = constraint.locations { + true + } else { + false + } } /// This function classifies a constraint from a location. fn classify_constraint( &self, - index: &ConstraintIndex, + index: ConstraintIndex, mir: &Mir<'tcx>, ) -> Option<(ConstraintCategory, Span)> { - let constraint = self.constraints.get(*index)?; + let constraint = self.constraints[index]; let span = constraint.locations.span(mir); let location = constraint.locations.from_location()?; @@ -238,7 +205,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { outlived_fr: RegionVid, blame_span: Span, ) { - // Obviously uncool error reporting. + debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr); let fr_name = self.to_error_region(fr); let outlived_fr_name = self.to_error_region(outlived_fr); @@ -261,19 +228,26 @@ impl<'tcx> RegionInferenceContext<'tcx> { None => format!("free region `{:?}`", outlived_fr), }; - let constraints = self.find_constraint_paths_from_region(fr.clone()); - let path = constraints.iter().min_by_key(|p| p.len()).unwrap(); + // Find all paths + let constraint_paths = self.find_constraint_paths_between_regions(outlived_fr, fr); + debug!("report_error: constraint_paths={:#?}", constraint_paths); + + // Find the shortest such path. + let path = constraint_paths.iter().min_by_key(|p| p.len()).unwrap(); debug!("report_error: shortest_path={:?}", path); - let mut categorized_path = path.iter() - .filter_map(|index| self.classify_constraint(index, mir)) - .collect::>(); + // Classify each of the constraints along the path. + let mut categorized_path: Vec<(ConstraintCategory, Span)> = path.iter() + .filter_map(|&index| self.classify_constraint(index, mir)) + .collect(); debug!("report_error: categorized_path={:?}", categorized_path); + // Find what appears to be the most interesting path to report to the user. categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0)); debug!("report_error: sorted_path={:?}", categorized_path); - if let Some((category, span)) = &categorized_path.first() { + // If we found something, cite that as the main cause of the problem. + if let Some((category, span)) = categorized_path.first() { let mut diag = infcx.tcx.sess.struct_span_err( *span, &format!( From dddd4075b1cdab90a3bf10f1687f3d0ed2ee5bec Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 3 Jul 2018 05:59:08 -0400 Subject: [PATCH 03/10] generalize `find_constraint_paths_between_regions` --- .../nll/region_infer/error_reporting.rs | 27 +++++++------------ 1 file changed, 10 insertions(+), 17 deletions(-) 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 d8258afc24f62..85df5ec942942 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 @@ -64,13 +64,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn find_constraint_paths_between_regions( &self, from_region: RegionVid, - to_region: RegionVid, + target_test: impl Fn(RegionVid) -> bool, ) -> Vec> { let mut results = vec![]; self.find_constraint_paths_between_regions_helper( from_region, from_region, - to_region, + &target_test, &mut FxHashSet::default(), &mut vec![], &mut results, @@ -83,7 +83,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, from_region: RegionVid, current_region: RegionVid, - to_region: RegionVid, + target_test: &impl Fn(RegionVid) -> bool, visited: &mut FxHashSet, stack: &mut Vec, results: &mut Vec>, @@ -96,18 +96,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { } // Check if we reached the region we were looking for. - if current_region == to_region { - // Unless we started out searching for `'a ~> 'a`, which shouldn't have caused - // en error, then we must have traversed at least *some* constraint: - assert!(!stack.is_empty()); - - // The first constraint should be like `X: from_region`. - assert_eq!(self.constraints[stack[0]].sub, from_region); - - // The last constraint should be like `to_region: Y`. - assert_eq!(self.constraints[*stack.last().unwrap()].sup, to_region); - - results.push(stack.clone()); + if target_test(current_region) { + if !stack.is_empty() { + assert_eq!(self.constraints[stack[0]].sub, from_region); + results.push(stack.clone()); + } return; } @@ -118,7 +111,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.find_constraint_paths_between_regions_helper( from_region, self.constraints[constraint].sup, - to_region, + target_test, visited, stack, results, @@ -229,7 +222,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }; // Find all paths - let constraint_paths = self.find_constraint_paths_between_regions(outlived_fr, fr); + let constraint_paths = self.find_constraint_paths_between_regions(outlived_fr, |r| r == fr); debug!("report_error: constraint_paths={:#?}", constraint_paths); // Find the shortest such path. From f03c0366ad3b0afa267dd617c671c852b3e2bb73 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 3 Jul 2018 06:24:45 -0400 Subject: [PATCH 04/10] add "free region helpers" --- src/librustc/ty/fold.rs | 46 ++++++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs index f55a512908499..076a19fb4ed72 100644 --- a/src/librustc/ty/fold.rs +++ b/src/librustc/ty/fold.rs @@ -253,13 +253,34 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { value.fold_with(&mut RegionFolder::new(self, skipped_regions, &mut f)) } - pub fn for_each_free_region(self, - value: &T, - callback: F) - where F: FnMut(ty::Region<'tcx>), - T: TypeFoldable<'tcx>, - { - value.visit_with(&mut RegionVisitor { + /// Invoke `callback` on every region appearing free in `value`. + pub fn for_each_free_region( + self, + value: &impl TypeFoldable<'tcx>, + mut callback: impl FnMut(ty::Region<'tcx>), + ) { + self.any_free_region_meets(value, |r| { + callback(r); + false + }); + } + + /// True if `callback` returns true for every region appearing free in `value`. + pub fn all_free_regions_meet( + self, + value: &impl TypeFoldable<'tcx>, + mut callback: impl FnMut(ty::Region<'tcx>) -> bool, + ) -> bool { + !self.any_free_region_meets(value, |r| !callback(r)) + } + + /// True if `callback` returns true for some region appearing free in `value`. + pub fn any_free_region_meets( + self, + value: &impl TypeFoldable<'tcx>, + callback: impl FnMut(ty::Region<'tcx>) -> bool, + ) -> bool { + return value.visit_with(&mut RegionVisitor { outer_index: ty::INNERMOST, callback }); @@ -287,25 +308,22 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor - where F : FnMut(ty::Region<'tcx>) + where F: FnMut(ty::Region<'tcx>) -> bool { fn visit_binder>(&mut self, t: &Binder) -> bool { self.outer_index.shift_in(1); - t.skip_binder().visit_with(self); + let result = t.skip_binder().visit_with(self); self.outer_index.shift_out(1); - - false // keep visiting + result } fn visit_region(&mut self, r: ty::Region<'tcx>) -> bool { match *r { ty::ReLateBound(debruijn, _) if debruijn < self.outer_index => { - /* ignore bound regions */ + false // ignore bound regions, keep visiting } _ => (self.callback)(r), } - - false // keep visiting } } } From 37db94d3f2e9c43bd34f09952029786178731289 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 3 Jul 2018 06:47:51 -0400 Subject: [PATCH 05/10] store the `HirId` of the upvar --- src/librustc/ich/impls_mir.rs | 2 +- src/librustc/mir/mod.rs | 5 ++++- src/librustc_mir/build/mod.rs | 1 + 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/librustc/ich/impls_mir.rs b/src/librustc/ich/impls_mir.rs index f43ac7ad0dd5a..6217f6c9fdd33 100644 --- a/src/librustc/ich/impls_mir.rs +++ b/src/librustc/ich/impls_mir.rs @@ -30,7 +30,7 @@ impl_stable_hash_for!(struct mir::LocalDecl<'tcx> { internal, is_user_variable }); -impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, by_ref, mutability }); +impl_stable_hash_for!(struct mir::UpvarDecl { debug_name, var_hir_id, by_ref, mutability }); impl_stable_hash_for!(struct mir::BasicBlockData<'tcx> { statements, terminator, is_cleanup }); impl_stable_hash_for!(struct mir::UnsafetyViolation { source_info, description, kind }); impl_stable_hash_for!(struct mir::UnsafetyCheckResult { violations, unsafe_blocks }); diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index dca0d4f442a4c..78c4966c6f9ed 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -15,7 +15,7 @@ use graphviz::IntoCow; use hir::def::CtorKind; use hir::def_id::DefId; -use hir::{self, InlineAsm}; +use hir::{self, HirId, InlineAsm}; use middle::region; use mir::interpret::{EvalErrorKind, Scalar, Value}; use mir::visit::MirVisitable; @@ -785,6 +785,9 @@ impl<'tcx> LocalDecl<'tcx> { pub struct UpvarDecl { pub debug_name: Name, + /// `HirId` of the captured variable + pub var_hir_id: ClearCrossCrate, + /// If true, the capture is behind a reference. pub by_ref: bool, diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 4db5c8e9278e5..2b18771a34f02 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -534,6 +534,7 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, }; let mut decl = UpvarDecl { debug_name: keywords::Invalid.name(), + var_hir_id: ClearCrossCrate::Set(var_hir_id), by_ref, mutability: Mutability::Not, }; From 351e78de265f1519d6d9021878fa0950985093a3 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 3 Jul 2018 06:50:54 -0400 Subject: [PATCH 06/10] add `assert_crate_local` method to `ClearCrossCrate` --- src/librustc/mir/mod.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 78c4966c6f9ed..cd4b32735e57a 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -380,6 +380,15 @@ pub enum ClearCrossCrate { Set(T), } +impl ClearCrossCrate { + pub fn assert_crate_local(self) -> T { + match self { + ClearCrossCrate::Clear => bug!("unwrapping cross-crate data"), + ClearCrossCrate::Set(v) => v, + } + } +} + impl serialize::UseSpecializedEncodable for ClearCrossCrate {} impl serialize::UseSpecializedDecodable for ClearCrossCrate {} From aae177e0054540056f788c39c20a3612d91886e5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 3 Jul 2018 08:38:44 -0400 Subject: [PATCH 07/10] promote `error-reporting` to a module --- .../region_infer/{error_reporting.rs => error_reporting/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/librustc_mir/borrow_check/nll/region_infer/{error_reporting.rs => error_reporting/mod.rs} (100%) 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/mod.rs similarity index 100% rename from src/librustc_mir/borrow_check/nll/region_infer/error_reporting.rs rename to src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs From 8b3ce9ca68a0e44caf2d46ba4025ba3c696849b4 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 3 Jul 2018 11:37:37 -0400 Subject: [PATCH 08/10] always create a category, even it is just "boring" --- .../nll/region_infer/error_reporting/mod.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 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 85df5ec942942..5a86f2432d807 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 @@ -140,13 +140,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { &self, index: ConstraintIndex, mir: &Mir<'tcx>, - ) -> Option<(ConstraintCategory, Span)> { + ) -> (ConstraintCategory, Span) { let constraint = self.constraints[index]; let span = constraint.locations.span(mir); - let location = constraint.locations.from_location()?; + let location = constraint.locations.from_location().unwrap_or(Location::START); if !self.constraint_is_interesting(index) { - return Some((ConstraintCategory::Boring, span)); + return (ConstraintCategory::Boring, span); } let data = &mir[location.block]; @@ -178,7 +178,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } }; - Some((category, span)) + (category, span) } /// Report an error because the universal region `fr` was required to outlive @@ -231,7 +231,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Classify each of the constraints along the path. let mut categorized_path: Vec<(ConstraintCategory, Span)> = path.iter() - .filter_map(|&index| self.classify_constraint(index, mir)) + .map(|&index| self.classify_constraint(index, mir)) .collect(); debug!("report_error: categorized_path={:?}", categorized_path); From fa02d68eecbb3ff253c4e6f2f7dcc171c7c25283 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 3 Jul 2018 11:45:02 -0400 Subject: [PATCH 09/10] universal_regions: rustfmt --- .../borrow_check/nll/universal_regions.rs | 44 +++++++++---------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index ec8cd386679c3..acd740e541259 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -22,15 +22,15 @@ //! The code in this file doesn't *do anything* with those results; it //! just returns them for other code to use. -use rustc::hir::{self, BodyOwnerKind, HirId}; use rustc::hir::def_id::DefId; -use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; -use rustc::infer::region_constraints::GenericKind; +use rustc::hir::{self, BodyOwnerKind, HirId}; use rustc::infer::outlives::bounds::{self, OutlivesBound}; use rustc::infer::outlives::free_region_map::FreeRegionRelations; -use rustc::ty::{self, RegionVid, Ty, TyCtxt, ClosureSubsts, GeneratorSubsts}; +use rustc::infer::region_constraints::GenericKind; +use rustc::infer::{InferCtxt, NLLRegionVariableOrigin}; use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::Substs; +use rustc::ty::{self, ClosureSubsts, GeneratorSubsts, RegionVid, Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::transitive_relation::TransitiveRelation; @@ -493,18 +493,15 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> { debug!( "build: global regions = {}..{}", - FIRST_GLOBAL_INDEX, - first_extern_index + FIRST_GLOBAL_INDEX, first_extern_index ); debug!( "build: extern regions = {}..{}", - first_extern_index, - first_local_index + first_extern_index, first_local_index ); debug!( "build: local regions = {}..{}", - first_local_index, - num_universals + first_local_index, num_universals ); let yield_ty = match defining_ty { @@ -548,7 +545,7 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> { let defining_ty = self.infcx .replace_free_regions_with_nll_infer_vars(FR, &defining_ty); - match defining_ty.sty { + match defining_ty.sty { ty::TyClosure(def_id, substs) => DefiningTy::Closure(def_id, substs), ty::TyGenerator(def_id, substs, movability) => { DefiningTy::Generator(def_id, substs, movability) @@ -587,8 +584,8 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> { let closure_base_def_id = tcx.closure_base_def_id(self.mir_def_id); let identity_substs = Substs::identity_for_item(gcx, closure_base_def_id); let fr_substs = match defining_ty { - DefiningTy::Closure(_, ClosureSubsts { ref substs }) | - DefiningTy::Generator(_, GeneratorSubsts { ref substs }, _) => { + DefiningTy::Closure(_, ClosureSubsts { ref substs }) + | DefiningTy::Generator(_, GeneratorSubsts { ref substs }, _) => { // In the case of closures, we rely on the fact that // the first N elements in the ClosureSubsts are // inherited from the `closure_base_def_id`. @@ -726,8 +723,7 @@ impl UniversalRegionRelations { fn relate_universal_regions(&mut self, fr_a: RegionVid, fr_b: RegionVid) { debug!( "relate_universal_regions: fr_a={:?} outlives fr_b={:?}", - fr_a, - fr_b + fr_a, fr_b ); self.outlives.add(fr_a, fr_b); self.inverse_outlives.add(fr_b, fr_a); @@ -780,8 +776,7 @@ impl<'cx, 'gcx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'gcx, 'tcx> { { debug!( "replace_bound_regions_with_nll_infer_vars(value={:?}, all_outlive_scope={:?})", - value, - all_outlive_scope, + value, all_outlive_scope, ); let (value, _map) = self.tcx.replace_late_bound_regions(value, |br| { let liberated_region = self.tcx.mk_region(ty::ReFree(ty::FreeRegion { @@ -790,7 +785,10 @@ impl<'cx, 'gcx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'gcx, 'tcx> { })); let region_vid = self.next_nll_region_var(origin); indices.insert_late_bound_region(liberated_region, region_vid.to_region_vid()); - debug!("liberated_region={:?} => {:?}", liberated_region, region_vid); + debug!( + "liberated_region={:?} => {:?}", + liberated_region, region_vid + ); region_vid }); value @@ -803,9 +801,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> { /// in later and instantiate the late-bound regions, and then we /// insert the `ReFree` version of those into the map as /// well. These are used for error reporting. - fn insert_late_bound_region(&mut self, r: ty::Region<'tcx>, - vid: ty::RegionVid) - { + fn insert_late_bound_region(&mut self, r: ty::Region<'tcx>, vid: ty::RegionVid) { self.indices.insert(r, vid); } @@ -821,9 +817,9 @@ impl<'tcx> UniversalRegionIndices<'tcx> { if let ty::ReVar(..) = r { r.to_region_vid() } else { - *self.indices.get(&r).unwrap_or_else(|| { - bug!("cannot convert `{:?}` to a region vid", r) - }) + *self.indices + .get(&r) + .unwrap_or_else(|| bug!("cannot convert `{:?}` to a region vid", r)) } } From 727f01700b074181bddf49caa07ac5e34455680d Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 3 Jul 2018 11:38:09 -0400 Subject: [PATCH 10/10] write code to extract region names and emit new style message --- src/librustc_mir/borrow_check/mod.rs | 10 +- .../nll/region_infer/error_reporting/mod.rs | 61 ++--- .../error_reporting/region_name.rs | 256 ++++++++++++++++++ .../borrow_check/nll/region_infer/mod.rs | 5 + .../borrow_check/nll/universal_regions.rs | 32 +++ .../borrowck/borrowck-describe-lvalue.rs | 2 +- .../compile-fail/mir_check_cast_closure.rs | 2 +- src/test/compile-fail/mir_check_cast_reify.rs | 2 +- .../compile-fail/mir_check_cast_unsafe_fn.rs | 2 +- .../compile-fail/mir_check_cast_unsize.rs | 3 +- src/test/compile-fail/regions-static-bound.rs | 2 +- src/test/ui/borrowck/issue-45983.nll.stderr | 10 +- src/test/ui/borrowck/issue-7573.nll.stderr | 10 +- .../regions-escape-bound-fn-2.nll.stderr | 10 +- .../regions-escape-bound-fn.nll.stderr | 10 +- .../regions-escape-unboxed-closure.nll.stderr | 10 +- .../expect-region-supply-region.nll.stderr | 32 ++- ...1-does-not-trigger-for-closures.nll.stderr | 8 +- .../static-return-lifetime-infered.nll.stderr | 10 +- .../impl/dyn-trait.nll.stderr | 4 +- .../escape-argument-callee.rs | 2 +- .../escape-argument-callee.stderr | 7 +- .../propagate-approximated-fail-no-postdom.rs | 3 +- ...pagate-approximated-fail-no-postdom.stderr | 16 +- ...horter-to-static-comparing-against-free.rs | 2 +- ...er-to-static-comparing-against-free.stderr | 13 +- ...approximated-shorter-to-static-no-bound.rs | 2 +- ...oximated-shorter-to-static-no-bound.stderr | 10 +- ...roximated-shorter-to-static-wrong-bound.rs | 2 +- ...mated-shorter-to-static-wrong-bound.stderr | 10 +- ...te-fail-to-approximate-longer-no-bounds.rs | 2 +- ...ail-to-approximate-longer-no-bounds.stderr | 11 +- ...fail-to-approximate-longer-wrong-bounds.rs | 2 +- ...-to-approximate-longer-wrong-bounds.stderr | 13 +- ...egion-lbr-named-does-not-outlive-static.rs | 2 +- ...n-lbr-named-does-not-outlive-static.stderr | 4 +- .../return-wrong-bound-region.rs | 2 +- .../return-wrong-bound-region.stderr | 9 +- src/test/ui/nll/issue-48238.rs | 2 +- src/test/ui/nll/issue-48238.stderr | 12 +- src/test/ui/nll/issue-50716.rs | 2 +- src/test/ui/nll/issue-50716.stderr | 6 +- .../projection-one-region-closure.rs | 6 +- .../projection-one-region-closure.stderr | 18 +- ...ojection-one-region-trait-bound-closure.rs | 6 +- ...tion-one-region-trait-bound-closure.stderr | 18 +- ...ojection-two-region-trait-bound-closure.rs | 2 +- ...tion-two-region-trait-bound-closure.stderr | 6 +- .../dyn-trait-underscore.nll.stderr | 7 +- 49 files changed, 523 insertions(+), 155 deletions(-) create mode 100644 src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs index 3aaa3378bb005..3417021640f17 100644 --- a/src/librustc_mir/borrow_check/mod.rs +++ b/src/librustc_mir/borrow_check/mod.rs @@ -128,6 +128,8 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( input_mir: &Mir<'gcx>, def_id: DefId, ) -> BorrowCheckResult<'gcx> { + debug!("do_mir_borrowck(def_id = {:?})", def_id); + let tcx = infcx.tcx; let attributes = tcx.get_attrs(def_id); let param_env = tcx.param_env(def_id); @@ -319,10 +321,14 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>( } } - BorrowCheckResult { + let result = BorrowCheckResult { closure_requirements: opt_closure_req, used_mut_upvars: mbcx.used_mut_upvars, - } + }; + + debug!("do_mir_borrowck: result = {:#?}", result); + + result } #[allow(dead_code)] 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 5a86f2432d807..786b6a77d2bdb 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 @@ -9,7 +9,6 @@ // except according to those terms. use borrow_check::nll::region_infer::values::ToElementIndex; -use borrow_check::nll::region_infer::{Cause, ConstraintIndex, RegionInferenceContext}; use borrow_check::nll::region_infer::{ConstraintIndex, RegionInferenceContext}; use borrow_check::nll::type_check::Locations; use rustc::hir::def_id::DefId; @@ -22,6 +21,8 @@ use rustc_data_structures::indexed_vec::IndexVec; use std::fmt; use syntax_pos::Span; +mod region_name; + /// Constraints that are considered interesting can be categorized to /// determine why they are interesting. Order of variants indicates /// sort order of the category, thereby influencing diagnostic output. @@ -200,10 +201,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) { debug!("report_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr); - let fr_name = self.to_error_region(fr); - let outlived_fr_name = self.to_error_region(outlived_fr); - - if let (Some(f), Some(o)) = (fr_name, outlived_fr_name) { + if let (Some(f), Some(o)) = (self.to_error_region(fr), self.to_error_region(outlived_fr)) { let tables = infcx.tcx.typeck_tables_of(mir_def_id); let nice = NiceRegionError::new_from_span(infcx.tcx, blame_span, o, f, Some(tables)); if let Some(_error_reported) = nice.try_report() { @@ -211,16 +209,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - let fr_string = match fr_name { - Some(r) => format!("free region `{}`", r), - None => format!("free region `{:?}`", fr), - }; - - let outlived_fr_string = match outlived_fr_name { - Some(r) => format!("free region `{}`", r), - None => format!("free region `{:?}`", outlived_fr), - }; - // Find all paths let constraint_paths = self.find_constraint_paths_between_regions(outlived_fr, |r| r == fr); debug!("report_error: constraint_paths={:#?}", constraint_paths); @@ -239,25 +227,34 @@ impl<'tcx> RegionInferenceContext<'tcx> { categorized_path.sort_by(|p0, p1| p0.0.cmp(&p1.0)); debug!("report_error: sorted_path={:?}", categorized_path); - // If we found something, cite that as the main cause of the problem. - if let Some((category, span)) = categorized_path.first() { - let mut diag = infcx.tcx.sess.struct_span_err( - *span, - &format!( - "{} requires that data must outlive {}", - category, outlived_fr_string - ), - ); + // Get a span + let (category, span) = categorized_path.first().unwrap(); + let diag = &mut infcx.tcx.sess.struct_span_err( + *span, + &format!("unsatisfied lifetime constraints"), // FIXME + ); - diag.emit(); - } else { - let mut diag = infcx.tcx.sess.struct_span_err( - blame_span, - &format!("{} does not outlive {}", fr_string, outlived_fr_string,), - ); + // Figure out how we can refer + let counter = &mut 1; + let fr_name = self.give_region_a_name(infcx.tcx, mir, mir_def_id, fr, counter, diag); + let outlived_fr_name = self.give_region_a_name( + infcx.tcx, + mir, + mir_def_id, + outlived_fr, + counter, + diag, + ); - diag.emit(); - } + diag.span_label( + *span, + format!( + "{} requires that `{}` must outlive `{}`", + category, fr_name, outlived_fr_name, + ), + ); + + diag.emit(); } // Find some constraint `X: Y` where: diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs new file mode 100644 index 0000000000000..bf8c9c8c3bef4 --- /dev/null +++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/region_name.rs @@ -0,0 +1,256 @@ +// Copyright 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 borrow_check::nll::region_infer::RegionInferenceContext; +use borrow_check::nll::ToRegionVid; +use rustc::hir::def_id::DefId; +use rustc::mir::{Local, Mir}; +use rustc::ty::{self, RegionVid, TyCtxt}; +use rustc_data_structures::indexed_vec::Idx; +use rustc_errors::DiagnosticBuilder; +use syntax::ast::Name; +use syntax::symbol::keywords; +use syntax_pos::symbol::InternedString; + +impl<'tcx> RegionInferenceContext<'tcx> { + /// Maps from an internal MIR region vid to something that we can + /// report to the user. In some cases, the region vids will map + /// directly to lifetimes that the user has a name for (e.g., + /// `'static`). But frequently they will not, in which case we + /// have to find some way to identify the lifetime to the user. To + /// that end, this function takes a "diagnostic" so that it can + /// create auxiliary notes as needed. + /// + /// Example (function arguments): + /// + /// Suppose we are trying to give a name to the lifetime of the + /// reference `x`: + /// + /// ``` + /// fn foo(x: &u32) { .. } + /// ``` + /// + /// This function would create a label like this: + /// + /// ``` + /// | fn foo(x: &u32) { .. } + /// ------- fully elaborated type of `x` is `&'1 u32` + /// ``` + /// + /// and then return the name `'1` for us to use. + crate fn give_region_a_name( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + mir: &Mir<'tcx>, + mir_def_id: DefId, + fr: RegionVid, + counter: &mut usize, + diag: &mut DiagnosticBuilder, + ) -> InternedString { + debug!("give_region_a_name(fr={:?}, counter={})", fr, counter); + + assert!(self.universal_regions.is_universal_region(fr)); + + self.give_name_from_error_region(tcx, mir_def_id, fr, counter, diag) + .or_else(|| { + self.give_name_if_anonymous_region_appears_in_arguments(tcx, mir, fr, counter, diag) + }) + .or_else(|| { + self.give_name_if_anonymous_region_appears_in_upvars(tcx, mir, fr, counter, diag) + }) + .or_else(|| { + self.give_name_if_anonymous_region_appears_in_output(tcx, mir, fr, counter, diag) + }) + .unwrap_or_else(|| span_bug!(mir.span, "can't make a name for free region {:?}", fr)) + } + + /// Check for the case where `fr` maps to something that the + /// *user* has a name for. In that case, we'll be able to map + /// `fr` to a `Region<'tcx>`, and that region will be one of + /// named variants. + fn give_name_from_error_region( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + mir_def_id: DefId, + fr: RegionVid, + counter: &mut usize, + diag: &mut DiagnosticBuilder<'_>, + ) -> Option { + let error_region = self.to_error_region(fr)?; + debug!("give_region_a_name: error_region = {:?}", error_region); + match error_region { + ty::ReEarlyBound(ebr) => Some(ebr.name), + + ty::ReStatic => Some(keywords::StaticLifetime.name().as_interned_str()), + + ty::ReFree(free_region) => match free_region.bound_region { + ty::BoundRegion::BrNamed(_, name) => Some(name), + + ty::BoundRegion::BrEnv => { + let closure_span = tcx.hir.span_if_local(mir_def_id).unwrap(); + let region_name = self.synthesize_region_name(counter); + diag.span_label( + closure_span, + format!("lifetime `{}` represents the closure body", region_name), + ); + Some(region_name) + } + + ty::BoundRegion::BrAnon(_) | ty::BoundRegion::BrFresh(_) => None, + }, + + ty::ReLateBound(..) + | ty::ReScope(..) + | ty::ReVar(..) + | ty::ReSkolemized(..) + | ty::ReEmpty + | ty::ReErased + | ty::ReClosureBound(..) + | ty::ReCanonical(..) => None, + } + } + + /// Find an argument that contains `fr` and label it with a fully + /// elaborated type, returning something like `'1`. Result looks + /// like: + /// + /// ``` + /// | fn foo(x: &u32) { .. } + /// ------- fully elaborated type of `x` is `&'1 u32` + /// ``` + fn give_name_if_anonymous_region_appears_in_arguments( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + mir: &Mir<'tcx>, + fr: RegionVid, + counter: &mut usize, + diag: &mut DiagnosticBuilder<'_>, + ) -> Option { + let implicit_inputs = self.universal_regions.defining_ty.implicit_inputs(); + let argument_index = self.universal_regions + .unnormalized_input_tys + .iter() + .skip(implicit_inputs) + .position(|arg_ty| { + debug!("give_name_if_anonymous_region_appears_in_arguments: arg_ty = {:?}", arg_ty); + tcx.any_free_region_meets(arg_ty, |r| r.to_region_vid() == fr) + })? + + implicit_inputs; + + debug!( + "give_name_if_anonymous_region_appears_in_arguments: \ + found {:?} in argument {} which has type {:?}", + fr, argument_index, self.universal_regions.unnormalized_input_tys[argument_index], + ); + + let region_name = self.synthesize_region_name(counter); + + let argument_local = Local::new(argument_index + 1); + let argument_span = mir.local_decls[argument_local].source_info.span; + diag.span_label( + argument_span, + format!("lifetime `{}` appears in this argument", region_name,), + ); + + Some(region_name) + } + + /// Find a closure upvar that contains `fr` and label it with a + /// fully elaborated type, returning something like `'1`. Result + /// looks like: + /// + /// ``` + /// | let x = Some(&22); + /// - fully elaborated type of `x` is `Option<&'1 u32>` + /// ``` + fn give_name_if_anonymous_region_appears_in_upvars( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + mir: &Mir<'tcx>, + fr: RegionVid, + counter: &mut usize, + diag: &mut DiagnosticBuilder<'_>, + ) -> Option { + let upvar_index = self.universal_regions + .defining_ty + .upvar_tys(tcx) + .position(|upvar_ty| { + debug!( + "give_name_if_anonymous_region_appears_in_upvars: upvar_ty = {:?}", + upvar_ty, + ); + tcx.any_free_region_meets(&upvar_ty, |r| r.to_region_vid() == fr) + })?; + + debug!( + "give_name_if_anonymous_region_appears_in_upvars: \ + found {:?} in upvar {} which has type {:?}", + fr, + upvar_index, + self.universal_regions + .defining_ty + .upvar_tys(tcx) + .nth(upvar_index), + ); + + let region_name = self.synthesize_region_name(counter); + + let upvar_hir_id = mir.upvar_decls[upvar_index].var_hir_id.assert_crate_local(); + let upvar_node_id = tcx.hir.hir_to_node_id(upvar_hir_id); + let upvar_span = tcx.hir.span(upvar_node_id); + let upvar_name = tcx.hir.name(upvar_node_id); + diag.span_label( + upvar_span, + format!( + "lifetime `{}` appears in the type of `{}`", + region_name, upvar_name, + ), + ); + + Some(region_name) + } + + /// Check for arguments appearing in the (closure) return type. It + /// must be a closure since, in a free fn, such an argument would + /// have to either also appear in an argument (if using elision) + /// or be early bound (named, not in argument). + fn give_name_if_anonymous_region_appears_in_output( + &self, + tcx: TyCtxt<'_, '_, 'tcx>, + mir: &Mir<'tcx>, + fr: RegionVid, + counter: &mut usize, + diag: &mut DiagnosticBuilder<'_>, + ) -> Option { + let return_ty = self.universal_regions + .unnormalized_output_ty; + debug!("give_name_if_anonymous_region_appears_in_output: return_ty = {:?}", return_ty); + if !tcx.any_free_region_meets(&return_ty, |r| r.to_region_vid() == fr) { + return None; + } + + let region_name = self.synthesize_region_name(counter); + diag.span_label( + mir.span, + format!("lifetime `{}` appears in return type", region_name), + ); + + Some(region_name) + } + + /// Create a synthetic region named `'1`, incrementing the + /// counter. + fn synthesize_region_name(&self, counter: &mut usize) -> InternedString { + let c = *counter; + *counter += 1; + + Name::intern(&format!("'{:?}", c)).as_interned_str() + } +} 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 13cc0c0419eab..164941203e054 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -256,6 +256,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn init_universal_regions(&mut self) { // Update the names (if any) for (external_name, variable) in self.universal_regions.named_universal_regions() { + debug!( + "init_universal_regions: region {:?} has external name {:?}", + variable, + external_name + ); self.definitions[variable].external_name = Some(external_name); } diff --git a/src/librustc_mir/borrow_check/nll/universal_regions.rs b/src/librustc_mir/borrow_check/nll/universal_regions.rs index acd740e541259..8590e3d0765f0 100644 --- a/src/librustc_mir/borrow_check/nll/universal_regions.rs +++ b/src/librustc_mir/borrow_check/nll/universal_regions.rs @@ -22,6 +22,7 @@ //! The code in this file doesn't *do anything* with those results; it //! just returns them for other code to use. +use either::Either; use rustc::hir::def_id::DefId; use rustc::hir::{self, BodyOwnerKind, HirId}; use rustc::infer::outlives::bounds::{self, OutlivesBound}; @@ -128,6 +129,34 @@ pub enum DefiningTy<'tcx> { Const(DefId, &'tcx Substs<'tcx>), } +impl<'tcx> DefiningTy<'tcx> { + /// Returns a list of all the upvar types for this MIR. If this is + /// not a closure or generator, there are no upvars, and hence it + /// will be an empty list. The order of types in this list will + /// match up with the `upvar_decls` field of `Mir`. + pub fn upvar_tys(self, tcx: TyCtxt<'_, '_, 'tcx>) -> impl Iterator> + 'tcx { + match self { + DefiningTy::Closure(def_id, substs) => Either::Left(substs.upvar_tys(def_id, tcx)), + DefiningTy::Generator(def_id, substs, _) => { + Either::Right(Either::Left(substs.upvar_tys(def_id, tcx))) + } + DefiningTy::FnDef(..) | DefiningTy::Const(..) => { + Either::Right(Either::Right(iter::empty())) + } + } + } + + /// Number of implicit inputs -- notably the "environment" + /// parameter for closures -- that appear in MIR but not in the + /// user's code. + pub fn implicit_inputs(self) -> usize { + match self { + DefiningTy::Closure(..) | DefiningTy::Generator(..) => 1, + DefiningTy::FnDef(..) | DefiningTy::Const(..) => 0, + } + } +} + #[derive(Debug)] struct UniversalRegionIndices<'tcx> { /// For those regions that may appear in the parameter environment @@ -542,6 +571,8 @@ impl<'cx, 'gcx, 'tcx> UniversalRegionsBuilder<'cx, 'gcx, 'tcx> { tables.node_id_to_type(self.mir_hir_id) }; + debug!("defining_ty (pre-replacement): {:?}", defining_ty); + let defining_ty = self.infcx .replace_free_regions_with_nll_infer_vars(FR, &defining_ty); @@ -802,6 +833,7 @@ impl<'tcx> UniversalRegionIndices<'tcx> { /// insert the `ReFree` version of those into the map as /// well. These are used for error reporting. fn insert_late_bound_region(&mut self, r: ty::Region<'tcx>, vid: ty::RegionVid) { + debug!("insert_late_bound_region({:?}, {:?})", r, vid); self.indices.insert(r, vid); } diff --git a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs index 3a7e4a13740d0..b821c7cfa34ff 100644 --- a/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs +++ b/src/test/compile-fail/borrowck/borrowck-describe-lvalue.rs @@ -302,7 +302,7 @@ fn main() { // FIXME(#49824) -- the free region error below should probably not be there let mut x = 0; || { - || { //[mir]~ ERROR free region `` does not outlive + || { //[mir]~ ERROR unsatisfied lifetime constraints 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 diff --git a/src/test/compile-fail/mir_check_cast_closure.rs b/src/test/compile-fail/mir_check_cast_closure.rs index d8f5956b58530..2200c1569e572 100644 --- a/src/test/compile-fail/mir_check_cast_closure.rs +++ b/src/test/compile-fail/mir_check_cast_closure.rs @@ -14,7 +14,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` + //~^ ERROR unsatisfied lifetime constraints g //~^ WARNING not reporting region error due to nll } diff --git a/src/test/compile-fail/mir_check_cast_reify.rs b/src/test/compile-fail/mir_check_cast_reify.rs index 1f9174b3574a7..f85104dff867f 100644 --- a/src/test/compile-fail/mir_check_cast_reify.rs +++ b/src/test/compile-fail/mir_check_cast_reify.rs @@ -45,7 +45,7 @@ fn bar<'a>(x: &'a u32) -> &'static u32 { // as part of checking the `ReifyFnPointer`. let f: fn(_) -> _ = foo; //~^ WARNING not reporting region error due to nll - //~| ERROR free region `'a` does not outlive free region `'static` + //~| ERROR unsatisfied lifetime constraints 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 27ca2728ddfd6..e90242f3f87da 100644 --- a/src/test/compile-fail/mir_check_cast_unsafe_fn.rs +++ b/src/test/compile-fail/mir_check_cast_unsafe_fn.rs @@ -17,7 +17,7 @@ fn bar<'a>(input: &'a u32, f: fn(&'a u32) -> &'a u32) -> &'static u32 { // in `g`. These are related via the `UnsafeFnPointer` cast. let g: unsafe fn(_) -> _ = f; //~^ WARNING not reporting region error due to nll - //~| ERROR free region `'a` does not outlive free region `'static` + //~| ERROR unsatisfied lifetime constraints 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 a2c840a70980b..d242186a6f7ea 100644 --- a/src/test/compile-fail/mir_check_cast_unsize.rs +++ b/src/test/compile-fail/mir_check_cast_unsize.rs @@ -15,8 +15,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 + x //~ ERROR unsatisfied lifetime constraints //~^ WARNING not reporting region error due to nll } diff --git a/src/test/compile-fail/regions-static-bound.rs b/src/test/compile-fail/regions-static-bound.rs index a0097b9f6d7df..0a37df4f0c788 100644 --- a/src/test/compile-fail/regions-static-bound.rs +++ b/src/test/compile-fail/regions-static-bound.rs @@ -18,7 +18,7 @@ fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static () fn static_id_wrong_way<'a>(t: &'a ()) -> &'static () where 'static: 'a { t //[ll]~ ERROR E0312 //[nll]~^ WARNING not reporting region error due to nll - //[nll]~| ERROR free region `'a` does not outlive free region `'static` + //[nll]~| ERROR unsatisfied lifetime constraints } fn error(u: &(), v: &()) { diff --git a/src/test/ui/borrowck/issue-45983.nll.stderr b/src/test/ui/borrowck/issue-45983.nll.stderr index a008a408d9711..68a039262c129 100644 --- a/src/test/ui/borrowck/issue-45983.nll.stderr +++ b/src/test/ui/borrowck/issue-45983.nll.stderr @@ -4,11 +4,15 @@ warning: not reporting region error due to nll LL | give_any(|y| x = Some(y)); | ^ -error: free region `` does not outlive free region `'_#2r` - --> $DIR/issue-45983.rs:17:27 +error: unsatisfied lifetime constraints + --> $DIR/issue-45983.rs:17:18 | +LL | let x = None; + | - lifetime `'2` appears in the type of `x` LL | give_any(|y| x = Some(y)); - | ^ + | - ^^^^^^^^^^^ free region requires that `'1` must outlive `'2` + | | + | lifetime `'1` appears in this argument error[E0594]: cannot assign to immutable item `x` --> $DIR/issue-45983.rs:17:18 diff --git a/src/test/ui/borrowck/issue-7573.nll.stderr b/src/test/ui/borrowck/issue-7573.nll.stderr index 84c6236eb0ae8..daa0a320b88d6 100644 --- a/src/test/ui/borrowck/issue-7573.nll.stderr +++ b/src/test/ui/borrowck/issue-7573.nll.stderr @@ -4,11 +4,17 @@ warning: not reporting region error due to nll LL | let mut lines_to_use: Vec<&CrateId> = Vec::new(); | ^ -error: free region `` does not outlive free region `'_#2r` +error: unsatisfied lifetime constraints --> $DIR/issue-7573.rs:32:9 | +LL | let mut lines_to_use: Vec<&CrateId> = Vec::new(); + | ---------------- lifetime `'2` appears in the type of `lines_to_use` +LL | //~^ NOTE cannot infer an appropriate lifetime +LL | let push_id = |installed_id: &CrateId| { + | ------------ lifetime `'1` appears in this argument +... LL | lines_to_use.push(installed_id); - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` error: aborting due to previous error diff --git a/src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr b/src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr index ee3970aa8fd8f..4f7843b72489c 100644 --- a/src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr +++ b/src/test/ui/borrowck/regions-escape-bound-fn-2.nll.stderr @@ -4,11 +4,15 @@ warning: not reporting region error due to nll LL | with_int(|y| x = Some(y)); | ^ -error: free region `` does not outlive free region `'_#2r` - --> $DIR/regions-escape-bound-fn-2.rs:18:27 +error: unsatisfied lifetime constraints + --> $DIR/regions-escape-bound-fn-2.rs:18:18 | +LL | let mut x = None; + | ----- lifetime `'2` appears in the type of `x` LL | with_int(|y| x = Some(y)); - | ^ + | - ^^^^^^^^^^^ free region requires that `'1` must outlive `'2` + | | + | lifetime `'1` appears in this argument error: aborting due to previous error diff --git a/src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr b/src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr index 07a4ab1dbb1ab..9b107ae08b477 100644 --- a/src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr +++ b/src/test/ui/borrowck/regions-escape-bound-fn.nll.stderr @@ -4,11 +4,15 @@ warning: not reporting region error due to nll LL | with_int(|y| x = Some(y)); | ^^^^^^^ -error: free region `` does not outlive free region `'_#2r` - --> $DIR/regions-escape-bound-fn.rs:18:27 +error: unsatisfied lifetime constraints + --> $DIR/regions-escape-bound-fn.rs:18:18 | +LL | let mut x: Option<&isize> = None; + | ----- lifetime `'2` appears in the type of `x` LL | with_int(|y| x = Some(y)); - | ^ + | - ^^^^^^^^^^^ free region requires that `'1` must outlive `'2` + | | + | lifetime `'1` appears in this argument error: aborting due to previous error diff --git a/src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr b/src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr index 14c255ef52778..8095330154d4c 100644 --- a/src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr +++ b/src/test/ui/borrowck/regions-escape-unboxed-closure.nll.stderr @@ -4,11 +4,15 @@ warning: not reporting region error due to nll LL | with_int(&mut |y| x = Some(y)); | ^^^^^^^ -error: free region `` does not outlive free region `'_#2r` - --> $DIR/regions-escape-unboxed-closure.rs:16:32 +error: unsatisfied lifetime constraints + --> $DIR/regions-escape-unboxed-closure.rs:16:23 | +LL | let mut x: Option<&isize> = None; + | ----- lifetime `'2` appears in the type of `x` LL | with_int(&mut |y| x = Some(y)); - | ^ + | - ^^^^^^^^^^^ free region requires that `'1` must outlive `'2` + | | + | lifetime `'1` appears in this argument error: aborting due to previous error diff --git a/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr b/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr index bbae80e16abde..5487d34813b47 100644 --- a/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr +++ b/src/test/ui/closure-expected-type/expect-region-supply-region.nll.stderr @@ -22,23 +22,37 @@ warning: not reporting region error due to nll LL | f = Some(x); | ^^^^^^^ -error: free region `` does not outlive free region `'_#2r` - --> $DIR/expect-region-supply-region.rs:28:18 +error: unsatisfied lifetime constraints + --> $DIR/expect-region-supply-region.rs:28:9 | +LL | let mut f: Option<&u32> = None; + | ----- lifetime `'2` appears in the type of `f` +LL | closure_expecting_bound(|x| { + | - lifetime `'1` appears in this argument LL | f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure - | ^ + | ^^^^^^^^^^^ free region requires that `'1` must outlive `'2` -error: free region `` does not outlive free region `'_#2r` - --> $DIR/expect-region-supply-region.rs:38:18 +error: unsatisfied lifetime constraints + --> $DIR/expect-region-supply-region.rs:38:9 | +LL | let mut f: Option<&u32> = None; + | ----- lifetime `'2` appears in the type of `f` +LL | closure_expecting_bound(|x: &u32| { + | - lifetime `'1` appears in this argument LL | f = Some(x); //~ ERROR borrowed data cannot be stored outside of its closure - | ^ + | ^^^^^^^^^^^ free region requires that `'1` must outlive `'2` -error: free region `` does not outlive free region `'_#2r` - --> $DIR/expect-region-supply-region.rs:52:18 +error: unsatisfied lifetime constraints + --> $DIR/expect-region-supply-region.rs:52:9 | +LL | let mut f: Option<&u32> = None; + | ----- lifetime `'2` appears in the type of `f` +... +LL | closure_expecting_bound(|x: &'x u32| { + | - lifetime `'1` appears in this argument +... LL | f = Some(x); - | ^ + | ^^^^^^^^^^^ free region requires that `'1` must outlive `'2` error: aborting due to 3 previous errors diff --git a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr index 5ae6afa7b17e2..9c7e3db67a611 100644 --- a/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr +++ b/src/test/ui/error-codes/E0621-does-not-trigger-for-closures.nll.stderr @@ -4,11 +4,15 @@ warning: not reporting region error due to nll LL | invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495 | ^^^^^^ -error: free region `` does not outlive free region `'_#2r` +error: unsatisfied lifetime constraints --> $DIR/E0621-does-not-trigger-for-closures.rs:25:26 | LL | invoke(&x, |a, b| if a > b { a } else { b }); //~ ERROR E0495 - | ^^^^^ + | ----------^^^^^----------------- + | | | | + | | | free region requires that `'1` must outlive `'2` + | | lifetime `'1` appears in this argument + | lifetime `'2` appears in return type error: aborting due to previous error diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr index 7099316d694a2..9aad7efdee5b2 100644 --- a/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr +++ b/src/test/ui/impl-trait/static-return-lifetime-infered.nll.stderr @@ -10,17 +10,19 @@ warning: not reporting region error due to nll LL | self.x.iter().map(|a| a.0) | ^^^^ -error: free region `` does not outlive free region `'static` +error: unsatisfied lifetime constraints --> $DIR/static-return-lifetime-infered.rs:17:9 | +LL | fn iter_values_anon(&self) -> impl Iterator { + | ----- lifetime `'1` appears in this argument LL | self.x.iter().map(|a| a.0) - | ^^^^^^^^^^^^^ + | ^^^^^^ cast requires that `'1` must outlive `'static` -error: free region `'a` does not outlive free region `'static` +error: unsatisfied lifetime constraints --> $DIR/static-return-lifetime-infered.rs:21:9 | LL | self.x.iter().map(|a| a.0) - | ^^^^^^^^^^^^^ + | ^^^^^^ cast requires that `'a` must outlive `'static` error: aborting due to 2 previous errors diff --git a/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr b/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr index 4cf7feddd4654..19e10ba6da8b9 100644 --- a/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr +++ b/src/test/ui/in-band-lifetimes/impl/dyn-trait.nll.stderr @@ -4,11 +4,11 @@ warning: not reporting region error due to nll LL | static_val(x); //~ ERROR cannot infer | ^ -error: free region `'a` does not outlive free region `'static` +error: unsatisfied lifetime constraints --> $DIR/dyn-trait.rs:32:5 | LL | static_val(x); //~ ERROR cannot infer - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ argument requires that `'a` must outlive `'static` error: aborting due to previous error 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 1e168028c7c9a..78208d6d7db7d 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.rs +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.rs @@ -34,7 +34,7 @@ fn test() { { let y = 22; let mut closure = expect_sig(|p, y| *p = y); - //~^ ERROR does not outlive free region + //~^ ERROR //~| 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 067b5ebc6c4ad..d6f542183603e 100644 --- a/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr +++ b/src/test/ui/nll/closure-requirements/escape-argument-callee.stderr @@ -4,11 +4,14 @@ warning: not reporting region error due to nll LL | let mut closure = expect_sig(|p, y| *p = y); | ^ -error: free region `ReFree(DefId(0/1:9 ~ escape_argument_callee[317d]::test[0]::{{closure}}[0]), BrAnon(3))` does not outlive free region `ReFree(DefId(0/1:9 ~ escape_argument_callee[317d]::test[0]::{{closure}}[0]), BrAnon(2))` +error: unsatisfied lifetime constraints --> $DIR/escape-argument-callee.rs:36:45 | LL | let mut closure = expect_sig(|p, y| *p = y); - | ^^^^^^ + | - - ^^^^^^ free region requires that `'1` must outlive `'2` + | | | + | | lifetime `'1` appears in this argument + | lifetime `'2` appears in this argument note: No external requirements --> $DIR/escape-argument-callee.rs:36:38 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 e7ec0b9684d2c..b879f9a33986d 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 @@ -54,8 +54,7 @@ fn supply<'a, 'b, 'c>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>, cell_c: Cell // Only works if 'x: 'y: let p = x.get(); //~^ WARN not reporting region error due to nll - //~| ERROR does not outlive free region - demand_y(x, y, p) + demand_y(x, y, p) //~ ERROR }, ); } 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 c88f0efba6f4b..a7a50a3a02981 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 @@ -4,11 +4,16 @@ warning: not reporting region error due to nll LL | let p = x.get(); | ^^^^^^^ -error: free region `ReFree(DefId(0/1:20 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]::{{closure}}[0]), BrAnon(1))` does not outlive free region `ReFree(DefId(0/1:20 ~ propagate_approximated_fail_no_postdom[317d]::supply[0]::{{closure}}[0]), BrAnon(2))` - --> $DIR/propagate-approximated-fail-no-postdom.rs:55:17 +error: unsatisfied lifetime constraints + --> $DIR/propagate-approximated-fail-no-postdom.rs:57:13 | -LL | let p = x.get(); - | ^ +LL | |_outlives1, _outlives2, _outlives3, x, y| { + | ---------- ---------- lifetime `'2` appears in this argument + | | + | lifetime `'1` appears in this argument +... +LL | demand_y(x, y, p) //~ ERROR + | ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` note: No external requirements --> $DIR/propagate-approximated-fail-no-postdom.rs:53:9 @@ -17,8 +22,7 @@ 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 nll -LL | | //~| ERROR does not outlive free region -LL | | demand_y(x, y, p) +LL | | demand_y(x, y, p) //~ ERROR 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 5a71e75d4b2cd..a8ab41cebacce 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 @@ -31,7 +31,7 @@ fn case1() { foo(cell, |cell_a, cell_x| { //~^ WARNING not reporting region error due to nll cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure - //~^ ERROR argument requires that data must outlive free region + //~^ ERROR }) } 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 656c1b46a3ce5..96f3d6a6a533a 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 @@ -4,11 +4,16 @@ warning: not reporting region error due to nll LL | foo(cell, |cell_a, cell_x| { | ^^^ -error: argument requires that data must outlive free region `'_#1r` - --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:20 +error: unsatisfied lifetime constraints + --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:33:9 | +LL | foo(cell, |cell_a, cell_x| { + | ------ ------ lifetime `'1` appears in this argument + | | + | lifetime `'2` appears in this argument +LL | //~^ WARNING not reporting region error due to nll LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure - | ^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` note: No external requirements --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:31:15 @@ -17,7 +22,7 @@ LL | foo(cell, |cell_a, cell_x| { | _______________^ LL | | //~^ WARNING not reporting region error due to nll LL | | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure -LL | | //~^ ERROR argument requires that data must outlive free region +LL | | //~^ ERROR 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 b25b0e25df211..26faccdde71ae 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 @@ -43,7 +43,7 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3 #[rustc_regions] fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { - //~^ ERROR argument requires that data must outlive free region + //~^ ERROR // Only works if 'x: 'y: 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 40f215619c689..f65e7161ca8c5 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 @@ -9,7 +9,7 @@ note: External requirements | LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { | _______________________________________________^ -LL | | //~^ ERROR argument requires that data must outlive free region +LL | | //~^ ERROR LL | | LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll @@ -23,23 +23,23 @@ LL | | }); = note: number of external vids: 2 = note: where '_#1r: '_#0r -error: argument requires that data must outlive free region `ReStatic` +error: unsatisfied lifetime constraints --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:45:5 | LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { -LL | | //~^ ERROR argument requires that data must outlive free region +LL | | //~^ ERROR LL | | LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) //~ WARNING not reporting region error due to nll LL | | }); - | |______^ + | |______^ argument requires that `'a` must outlive `'static` note: No external requirements --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:44:1 | LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { LL | | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { -LL | | //~^ ERROR argument requires that data must outlive free region +LL | | //~^ ERROR LL | | ... | 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 db9951bcc0f21..703d60371cdfc 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 @@ -46,7 +46,7 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3 #[rustc_regions] fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { - //~^ ERROR argument requires that data must outlive free region + //~^ ERROR // Only works if 'x: 'y: 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-wrong-bound.stderr b/src/test/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index d89ff028a5042..f1b2c9f198d69 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 @@ -9,7 +9,7 @@ note: External requirements | LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { | _______________________________________________^ -LL | | //~^ ERROR argument requires that data must outlive free region +LL | | //~^ ERROR LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) LL | | //~^ WARNING not reporting region error due to nll @@ -23,23 +23,23 @@ LL | | }); = note: number of external vids: 3 = note: where '_#1r: '_#0r -error: argument requires that data must outlive free region `ReStatic` +error: unsatisfied lifetime constraints --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:48:5 | LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { -LL | | //~^ ERROR argument requires that data must outlive free region +LL | | //~^ ERROR LL | | // Only works if 'x: 'y: LL | | demand_y(x, y, x.get()) LL | | //~^ WARNING not reporting region error due to nll LL | | }); - | |______^ + | |______^ argument requires that `'a` must outlive `'static` note: No external requirements --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:47:1 | LL | / fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { LL | | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { -LL | | //~^ ERROR argument requires that data must outlive free region +LL | | //~^ ERROR LL | | // Only works if 'x: 'y: ... | LL | | }); 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 316268e7e726d..4b1f5231b3e87 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 @@ -46,7 +46,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { // Only works if 'x: 'y: demand_y(x, y, x.get()) //~^ WARN not reporting region error due to nll - //~| ERROR argument requires that data must outlive free region + //~| ERROR }); } 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 74c0576e03b62..fb98c506c7d28 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 @@ -4,11 +4,16 @@ warning: not reporting region error due to nll LL | demand_y(x, y, x.get()) | ^^^^^^^^^^^^^^^^^^^^^^^ -error: argument requires that data must outlive free region `ReFree(DefId(0/1:18 ~ propagate_fail_to_approximate_longer_no_bounds[317d]::supply[0]::{{closure}}[0]), BrAnon(2))` +error: unsatisfied lifetime constraints --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:47:9 | +LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { + | --------- - lifetime `'1` appears in this argument + | | + | lifetime `'2` appears in this argument +LL | // Only works if 'x: 'y: LL | demand_y(x, y, x.get()) - | ^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` note: No external requirements --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:45:47 @@ -18,7 +23,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 nll -LL | | //~| ERROR argument requires that data must outlive free region +LL | | //~| ERROR 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 afb61b221be94..62a20c1bfe76e 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 @@ -50,7 +50,7 @@ fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { // Only works if 'x: 'y: demand_y(x, y, x.get()) //~^ WARN not reporting region error due to nll - //~| ERROR does not outlive free region + //~| ERROR }); } 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 2fd6ce50095fc..73d39a8502b64 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 @@ -4,11 +4,16 @@ warning: not reporting region error due to nll LL | demand_y(x, y, x.get()) | ^^^^^^^^^^^^^^^^^^^^^^^ -error: free region `ReFree(DefId(0/1:18 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]::{{closure}}[0]), BrAnon(2))` does not outlive free region `ReFree(DefId(0/1:18 ~ propagate_fail_to_approximate_longer_wrong_bounds[317d]::supply[0]::{{closure}}[0]), BrAnon(4))` - --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:18 +error: unsatisfied lifetime constraints + --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:51:9 | +LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { + | ---------- ---------- lifetime `'2` appears in this argument + | | + | lifetime `'1` appears in this argument +LL | // Only works if 'x: 'y: LL | demand_y(x, y, x.get()) - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` note: No external requirements --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:49:47 @@ -18,7 +23,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 nll -LL | | //~| ERROR does not outlive free region +LL | | //~| ERROR LL | | }); | |_____^ | 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 dedbd8df41b13..b5e8c95bc13b7 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 @@ -18,7 +18,7 @@ fn foo<'a>(x: &'a u32) -> &'static u32 { &*x //~^ WARN not reporting region error due to nll - //~| ERROR does not outlive free region + //~| ERROR } fn main() { } 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 9520b446303c3..d012dca25271c 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 @@ -4,11 +4,11 @@ warning: not reporting region error due to nll LL | &*x | ^^^ -error: free region `ReFree(DefId(0/0:3 ~ region_lbr_named_does_not_outlive_static[317d]::foo[0]), BrNamed(crate0:DefIndex(1:9), 'a))` does not outlive free region `ReStatic` +error: unsatisfied lifetime constraints --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5 | LL | &*x - | ^^^ + | ^^^ free region requires that `'a` must outlive `'static` error: aborting due to previous error 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 60f82ca0eefb9..d88729d04d95b 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 @@ -20,7 +20,7 @@ fn test() { expect_sig(|a, b| b); // ought to return `a` //~^ WARN not reporting region error due to nll - //~| ERROR does not outlive free region + //~| ERROR } fn expect_sig(f: F) -> F 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 04ff4aaadf875..5724cdbd8c95b 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 @@ -4,11 +4,14 @@ warning: not reporting region error due to nll LL | expect_sig(|a, b| b); // ought to return `a` | ^ -error: free region `ReFree(DefId(0/1:9 ~ return_wrong_bound_region[317d]::test[0]::{{closure}}[0]), BrAnon(2))` does not outlive free region `ReFree(DefId(0/1:9 ~ return_wrong_bound_region[317d]::test[0]::{{closure}}[0]), BrAnon(1))` +error: unsatisfied lifetime constraints --> $DIR/return-wrong-bound-region.rs:21:23 | LL | expect_sig(|a, b| b); // ought to return `a` - | ^ + | - - ^ free region requires that `'1` must outlive `'2` + | | | + | | lifetime `'1` appears in this argument + | lifetime `'2` appears in this argument note: No external requirements --> $DIR/return-wrong-bound-region.rs:21:16 @@ -27,7 +30,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 nll -LL | | //~| ERROR does not outlive free region +LL | | //~| ERROR LL | | } | |_^ | diff --git a/src/test/ui/nll/issue-48238.rs b/src/test/ui/nll/issue-48238.rs index 6f7644da3d349..7c5527ae1e7b1 100644 --- a/src/test/ui/nll/issue-48238.rs +++ b/src/test/ui/nll/issue-48238.rs @@ -18,5 +18,5 @@ fn use_val<'a>(val: &'a u8) -> &'a u8 { fn main() { let orig: u8 = 5; - move || use_val(&orig); //~ ERROR free region `` does not outlive free region `'_#1r` + move || use_val(&orig); //~ ERROR } diff --git a/src/test/ui/nll/issue-48238.stderr b/src/test/ui/nll/issue-48238.stderr index 29385d9b2430f..7bdac345e9047 100644 --- a/src/test/ui/nll/issue-48238.stderr +++ b/src/test/ui/nll/issue-48238.stderr @@ -1,8 +1,12 @@ -error: free region `` does not outlive free region `'_#1r` - --> $DIR/issue-48238.rs:21:21 +error: unsatisfied lifetime constraints + --> $DIR/issue-48238.rs:21:13 | -LL | move || use_val(&orig); //~ ERROR free region `` does not outlive free region `'_#1r` - | ^^^^^ +LL | move || use_val(&orig); //~ ERROR + | --------^^^^^^^^^^^^^^ + | | | + | | argument requires that `'1` must outlive `'2` + | lifetime `'1` represents the closure body + | lifetime `'2` appears in return type error: aborting due to previous error diff --git a/src/test/ui/nll/issue-50716.rs b/src/test/ui/nll/issue-50716.rs index a41af168c3e4e..beb2ff79e902b 100644 --- a/src/test/ui/nll/issue-50716.rs +++ b/src/test/ui/nll/issue-50716.rs @@ -22,7 +22,7 @@ where for<'b> &'b T: A, <&'static T as A>::X: Sized { - let _x = *s; //~ ERROR assignment requires that data must outlive free region `'static` + let _x = *s; //~ ERROR } fn main() {} diff --git a/src/test/ui/nll/issue-50716.stderr b/src/test/ui/nll/issue-50716.stderr index de69f8cfbcb6e..48862166f897f 100644 --- a/src/test/ui/nll/issue-50716.stderr +++ b/src/test/ui/nll/issue-50716.stderr @@ -1,8 +1,8 @@ -error: assignment requires that data must outlive free region `'static` +error: unsatisfied lifetime constraints --> $DIR/issue-50716.rs:25:14 | -LL | let _x = *s; //~ ERROR assignment requires that data must outlive free region `'static` - | ^^ +LL | let _x = *s; //~ ERROR + | ^^ assignment requires that `'a` must outlive `'static` error: aborting due to previous error 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 3832be6288aef..0a8801a3c4d6d 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 @@ -55,7 +55,7 @@ where with_signature(cell, t, |cell, t| require(cell, t)); //~^ WARNING not reporting region error due to nll //~| ERROR the parameter type `T` may not live long enough - //~| ERROR argument requires that data must outlive free region + //~| ERROR } #[rustc_regions] @@ -67,7 +67,7 @@ where with_signature(cell, t, |cell, t| require(cell, t)); //~^ WARNING not reporting region error due to nll //~| ERROR the parameter type `T` may not live long enough - //~| ERROR argument requires that data must outlive free region + //~| ERROR } #[rustc_regions] @@ -89,7 +89,7 @@ where with_signature(cell, t, |cell, t| require(cell, t)); //~^ WARNING not reporting region error due to nll //~| ERROR the parameter type `T` may not live long enough - //~| ERROR argument requires that data must outlive free region + //~| ERROR } #[rustc_regions] 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 898c995e09b9d..b84ee4de5a3cc 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 @@ -40,11 +40,11 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); | = help: consider adding an explicit lifetime bound `T: ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))`... -error: argument requires that data must outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))` +error: unsatisfied lifetime constraints --> $DIR/projection-one-region-closure.rs:55:5 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` note: No external requirements --> $DIR/projection-one-region-closure.rs:51:1 @@ -54,7 +54,7 @@ LL | | where LL | | T: Anything<'b>, LL | | { ... | -LL | | //~| ERROR argument requires that data must outlive free region +LL | | //~| ERROR LL | | } | |_^ | @@ -88,11 +88,11 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); | = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... -error: argument requires that data must outlive free region `ReEarlyBound(0, 'a)` +error: unsatisfied lifetime constraints --> $DIR/projection-one-region-closure.rs:67:5 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` note: No external requirements --> $DIR/projection-one-region-closure.rs:62:1 @@ -102,7 +102,7 @@ LL | | where LL | | T: Anything<'b>, LL | | 'a: 'a, ... | -LL | | //~| ERROR argument requires that data must outlive free region +LL | | //~| ERROR LL | | } | |_^ | @@ -137,11 +137,11 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); | = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... -error: argument requires that data must outlive free region `ReEarlyBound(0, 'a)` +error: unsatisfied lifetime constraints --> $DIR/projection-one-region-closure.rs:89:5 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` note: No external requirements --> $DIR/projection-one-region-closure.rs:74:1 @@ -151,7 +151,7 @@ LL | | where LL | | T: Anything<'b>, LL | | T::AssocType: 'a, ... | -LL | | //~| ERROR argument requires that data must outlive free region +LL | | //~| ERROR LL | | } | |_^ | 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 da76193459b30..6317d6eca1f1d 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 @@ -46,7 +46,7 @@ where { with_signature(cell, t, |cell, t| require(cell, t)); //~^ WARNING not reporting region error due to nll - //~| ERROR argument requires that data must outlive free region + //~| ERROR } #[rustc_regions] @@ -57,7 +57,7 @@ where { with_signature(cell, t, |cell, t| require(cell, t)); //~^ WARNING not reporting region error due to nll - //~| ERROR argument requires that data must outlive free region + //~| ERROR } #[rustc_regions] @@ -78,7 +78,7 @@ where with_signature(cell, t, |cell, t| require(cell, t)); //~^ WARNING not reporting region error due to nll - //~| ERROR argument requires that data must outlive free region + //~| ERROR } #[rustc_regions] 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 be11c6249f0ba..42ecd6f986075 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 @@ -31,11 +31,11 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: number of external vids: 3 = note: where '_#1r: '_#2r -error: argument requires that data must outlive free region `ReFree(DefId(0/0:8 ~ projection_one_region_trait_bound_closure[317d]::no_relationships_late[0]), BrNamed(crate0:DefIndex(1:16), 'a))` +error: unsatisfied lifetime constraints --> $DIR/projection-one-region-trait-bound-closure.rs:47:5 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` note: No external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:43:1 @@ -45,7 +45,7 @@ LL | | where LL | | T: Anything<'b>, LL | | { ... | -LL | | //~| ERROR argument requires that data must outlive free region +LL | | //~| ERROR LL | | } | |_^ | @@ -70,11 +70,11 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: number of external vids: 4 = note: where '_#2r: '_#3r -error: argument requires that data must outlive free region `ReEarlyBound(0, 'a)` +error: unsatisfied lifetime constraints --> $DIR/projection-one-region-trait-bound-closure.rs:58:5 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` note: No external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:53:1 @@ -84,7 +84,7 @@ LL | | where LL | | T: Anything<'b>, LL | | 'a: 'a, ... | -LL | | //~| ERROR argument requires that data must outlive free region +LL | | //~| ERROR LL | | } | |_^ | @@ -110,11 +110,11 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: number of external vids: 4 = note: where '_#2r: '_#3r -error: argument requires that data must outlive free region `ReEarlyBound(0, 'a)` +error: unsatisfied lifetime constraints --> $DIR/projection-one-region-trait-bound-closure.rs:79:5 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` note: No external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:64:1 @@ -124,7 +124,7 @@ LL | | where LL | | T: Anything<'b>, LL | | T::AssocType: 'a, ... | -LL | | //~| ERROR argument requires that data must outlive free region +LL | | //~| ERROR LL | | } | |_^ | 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 5e481a9626f08..2552054fd5f42 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 @@ -107,7 +107,7 @@ where { with_signature(cell, t, |cell, t| require(cell, t)); //~^ WARNING not reporting region error due to nll - //~| ERROR argument requires that data must outlive free region + //~| ERROR } #[rustc_regions] 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 546384e8545e3..b0f823ad3d56b 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 @@ -239,11 +239,11 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); = note: number of external vids: 3 = note: where >::AssocType: '_#2r -error: argument requires that data must outlive free region `ReFree(DefId(0/0:13 ~ projection_two_region_trait_bound_closure[317d]::two_regions[0]), BrNamed(crate0:DefIndex(1:43), 'a))` +error: unsatisfied lifetime constraints --> $DIR/projection-two-region-trait-bound-closure.rs:108:5 | LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` note: No external requirements --> $DIR/projection-two-region-trait-bound-closure.rs:104:1 @@ -253,7 +253,7 @@ LL | | where LL | | T: Anything<'b, 'b>, LL | | { ... | -LL | | //~| ERROR argument requires that data must outlive free region +LL | | //~| ERROR LL | | } | |_^ | diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr index 49f9044b19b24..04c3ed2d6ee19 100644 --- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr +++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.nll.stderr @@ -22,11 +22,14 @@ warning: not reporting region error due to nll LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime | ^^^^^^^^^^^^^^^^^^^^^^ -error: cast requires that data must outlive free region `'static` +error: unsatisfied lifetime constraints --> $DIR/dyn-trait-underscore.rs:18:5 | +LL | fn a(items: &[T]) -> Box> { + | ----- lifetime `'1` appears in this argument +LL | // ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static` LL | Box::new(items.iter()) //~ ERROR cannot infer an appropriate lifetime - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static` error: aborting due to previous error