diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index a94e5e793b470..6f117d6073d93 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -188,6 +188,15 @@ impl<'tcx> Mir<'tcx> { (&mut self.basic_blocks, &mut self.local_decls) } + pub fn terminator_location(&self, block: BasicBlock) -> Location { + let num_statements = self.basic_blocks[block].statements.len(); + Location { block, statement_index: num_statements } + } + + pub fn visitable(&self, location: Location) -> &dyn MirVisitable<'tcx> { + self.basic_blocks[location.block].visitable(location.statement_index) + } + #[inline] pub fn predecessors(&self) -> ReadGuard>> { self.cache.predecessors(self) diff --git a/src/librustc_mir/borrow_check/nll/constraint_generation.rs b/src/librustc_mir/borrow_check/nll/constraint_generation.rs index 4f87a2b30ae84..9a80f69e6707d 100644 --- a/src/librustc_mir/borrow_check/nll/constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/constraint_generation.rs @@ -276,7 +276,6 @@ impl<'cx, 'cg, 'gcx, 'tcx> ConstraintGeneration<'cx, 'cg, 'gcx, 'tcx> { span, ref_region.to_region_vid(), borrow_region.to_region_vid(), - location.successor_within_block(), ); if let Some(all_facts) = self.all_facts { diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs index 2807a4e8857e0..5f2c471aa4da1 100644 --- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs +++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs @@ -12,7 +12,8 @@ use borrow_check::nll::region_infer::{Cause, RegionInferenceContext}; use borrow_check::{Context, MirBorrowckCtxt}; use borrow_check::borrow_set::BorrowData; use rustc::mir::visit::{MirVisitable, PlaceContext, Visitor}; -use rustc::mir::{Local, Location, Mir}; +use rustc::mir::{BasicBlock, Local, Location, Mir, Statement, Terminator, TerminatorKind}; +use rustc::mir::RETURN_PLACE; use rustc_data_structures::fx::FxHashSet; use rustc_errors::DiagnosticBuilder; use util::liveness::{self, DefUse, LivenessMode}; @@ -38,9 +39,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> { Cause::LiveVar(local, location) => { match find_regular_use(mir, regioncx, borrow, location, local) { Some(p) => { - err.span_label( - mir.source_info(p).span, - format!("borrow later used here"), + mir.visitable(p).apply( + p, + &mut LaterUsedReporter { err, mir }, ); } @@ -232,4 +233,61 @@ impl<'tcx> Visitor<'tcx> for DefUseVisitor { } } } + + fn visit_terminator( + &mut self, + block: BasicBlock, + terminator: &Terminator<'tcx>, + location: Location, + ) { + if let TerminatorKind::Return = terminator.kind { + if self.local == RETURN_PLACE { + self.used = true; + } + } + self.super_terminator(block, terminator, location); + } +} + +struct LaterUsedReporter<'cx, 'diag: 'cx, 'tcx: 'cx> { + err: &'cx mut DiagnosticBuilder<'diag>, + mir: &'cx Mir<'tcx>, +} + +impl<'cx, 'diag, 'tcx> LaterUsedReporter<'cx, 'diag, 'tcx> { + fn base_report(&mut self, location: Location) { + self.err.span_label( + self.mir.source_info(location).span, + format!("borrow later used here"), + ); + } +} + +impl<'cx, 'diag, 'tcx> Visitor<'tcx> for LaterUsedReporter<'cx, 'diag, 'tcx> { + fn visit_statement( + &mut self, + _block: BasicBlock, + _statement: &Statement<'tcx>, + location: Location + ) { + self.base_report(location); + } + + fn visit_terminator( + &mut self, + _block: BasicBlock, + terminator: &Terminator<'tcx>, + location: Location, + ) { + match terminator.kind { + TerminatorKind::Return => { + // If the last use is the `Return` terminator + // then for now we don't add any label, as it's + // not clear what to say that is helpful. + } + _ => { + self.base_report(location); + } + } + } } diff --git a/src/librustc_mir/borrow_check/nll/mod.rs b/src/librustc_mir/borrow_check/nll/mod.rs index ec1f3dbaeebf5..e0357413fb6f0 100644 --- a/src/librustc_mir/borrow_check/nll/mod.rs +++ b/src/librustc_mir/borrow_check/nll/mod.rs @@ -111,9 +111,14 @@ pub(in borrow_check) fn compute_regions<'cx, 'gcx, 'tcx>( }; if let Some(all_facts) = &mut all_facts { - all_facts - .universal_region - .extend(universal_regions.universal_regions()); + // Declare that each universal region is live at every point. + for ur in universal_regions.universal_regions() { + all_facts.region_live_at.extend( + location_table + .all_points() + .map(|p| (ur, p)) + ); + } } // Create the region inference context, taking ownership of the region inference diff --git a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs index b0346abee5a5f..c13be367a2574 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/dump_mir.rs @@ -82,15 +82,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { let Constraint { sup, sub, - point, span, next: _, } = constraint; with_msg(&format!( - "{:?}: {:?} @ {:?} due to {:?}", + "{:?}: {:?} due to {:?}", sup, sub, - point, span ))?; } diff --git a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs index 6c4c02a36a0d7..c5f8fd278023c 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/graphviz.rs @@ -41,9 +41,6 @@ impl<'this, 'tcx> dot::Labeller<'this> for RegionInferenceContext<'tcx> { fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> { dot::LabelText::LabelStr(format!("{:?}", n).into_cow()) } - fn edge_label(&'this self, e: &Constraint) -> dot::LabelText<'this> { - dot::LabelText::LabelStr(format!("{:?}", e.point).into_cow()) - } } impl<'this, 'tcx> dot::GraphWalk<'this> for RegionInferenceContext<'tcx> { 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 dea2683789bdf..8d737b9886bb4 100644 --- a/src/librustc_mir/borrow_check/nll/region_infer/mod.rs +++ b/src/librustc_mir/borrow_check/nll/region_infer/mod.rs @@ -9,6 +9,7 @@ // except according to those terms. use super::universal_regions::UniversalRegions; +use borrow_check::nll::type_check::Locations; use borrow_check::nll::region_infer::values::ToElementIndex; use rustc::hir::def_id::DefId; use rustc::infer::error_reporting::nice_region_error::NiceRegionError; @@ -129,9 +130,6 @@ pub struct Constraint { /// Region that must be outlived. sub: RegionVid, - /// At this location. - point: Location, - /// Later on, we thread the constraints onto a linked list /// grouped by their `sub` field. So if you had: /// @@ -188,8 +186,8 @@ pub struct TypeTest<'tcx> { /// The region `'x` that the type must outlive. pub lower_bound: RegionVid, - /// The point where the outlives relation must hold. - pub point: Location, + /// Where does this type-test have to hold? + pub locations: Locations, /// Where did this constraint arise? pub span: Span, @@ -383,15 +381,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { span: Span, sup: RegionVid, sub: RegionVid, - point: Location, ) { - debug!("add_outlives({:?}: {:?} @ {:?}", sup, sub, point); + debug!("add_outlives({:?}: {:?})", sup, sub); assert!(self.inferred_values.is_none(), "values already inferred"); self.constraints.push(Constraint { span, sup, sub, - point, next: None, }); } @@ -546,7 +542,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { for type_test in &self.type_tests { debug!("check_type_test: {:?}", type_test); - if self.eval_region_test(mir, type_test.point, type_test.lower_bound, &type_test.test) { + if self.eval_region_test(mir, type_test.lower_bound, &type_test.test) { continue; } @@ -618,9 +614,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { let TypeTest { generic_kind, lower_bound, - point: _, span, test: _, + locations: _, } = type_test; let generic_ty = generic_kind.to_ty(tcx); @@ -803,31 +799,30 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn eval_region_test( &self, mir: &Mir<'tcx>, - point: Location, lower_bound: RegionVid, test: &RegionTest, ) -> bool { debug!( - "eval_region_test(point={:?}, lower_bound={:?}, test={:?})", - point, lower_bound, test + "eval_region_test(lower_bound={:?}, test={:?})", + lower_bound, test ); match test { RegionTest::IsOutlivedByAllRegionsIn(regions) => regions .iter() - .all(|&r| self.eval_outlives(mir, r, lower_bound, point)), + .all(|&r| self.eval_outlives(mir, r, lower_bound)), RegionTest::IsOutlivedByAnyRegionIn(regions) => regions .iter() - .any(|&r| self.eval_outlives(mir, r, lower_bound, point)), + .any(|&r| self.eval_outlives(mir, r, lower_bound)), RegionTest::Any(tests) => tests .iter() - .any(|test| self.eval_region_test(mir, point, lower_bound, test)), + .any(|test| self.eval_region_test(mir, lower_bound, test)), RegionTest::All(tests) => tests .iter() - .all(|test| self.eval_region_test(mir, point, lower_bound, test)), + .all(|test| self.eval_region_test(mir, lower_bound, test)), } } @@ -837,11 +832,10 @@ impl<'tcx> RegionInferenceContext<'tcx> { _mir: &Mir<'tcx>, sup_region: RegionVid, sub_region: RegionVid, - point: Location, ) -> bool { debug!( - "eval_outlives({:?}: {:?} @ {:?})", - sup_region, sub_region, point + "eval_outlives({:?}: {:?})", + sup_region, sub_region ); let inferred_values = self.inferred_values @@ -1143,8 +1137,8 @@ impl fmt::Debug for Constraint { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { write!( formatter, - "({:?}: {:?} @ {:?}) due to {:?}", - self.sup, self.sub, self.point, self.span + "({:?}: {:?}) due to {:?}", + self.sup, self.sub, self.span ) } } diff --git a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs index 9db19085a3965..3f1f5d5c33081 100644 --- a/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs +++ b/src/librustc_mir/borrow_check/nll/subtype_constraint_generation.rs @@ -13,7 +13,7 @@ use borrow_check::nll::facts::AllFacts; use rustc::infer::region_constraints::Constraint; use rustc::infer::region_constraints::RegionConstraintData; use rustc::infer::region_constraints::{Verify, VerifyBound}; -use rustc::mir::{Location, Mir}; +use rustc::mir::Mir; use rustc::ty; use std::iter; use syntax::codemap::Span; @@ -90,11 +90,7 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { givens, } = data; - let span = self.mir - .source_info(locations.from_location().unwrap_or(Location::START)) - .span; - - let at_location = locations.at_location().unwrap_or(Location::START); + let span = locations.span(self.mir); for constraint in constraints.keys() { debug!("generate: constraint: {:?}", constraint); @@ -112,23 +108,19 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { // reverse direction, because `regioncx` talks about // "outlives" (`>=`) whereas the region constraints // talk about `<=`. - self.regioncx.add_outlives(span, b_vid, a_vid, at_location); + self.regioncx.add_outlives(span, b_vid, a_vid); - // In the new analysis, all outlives relations etc - // "take effect" at the mid point of the statement - // that requires them, so ignore the `at_location`. if let Some(all_facts) = all_facts { - if let Some(from_location) = locations.from_location() { + locations.each_point(self.mir, |location| { + // In the new analysis, all outlives relations etc + // "take effect" at the mid point of the + // statement(s) that require them. all_facts.outlives.push(( b_vid, a_vid, - self.location_table.mid_index(from_location), + self.location_table.mid_index(location), )); - } else { - for location in self.location_table.all_points() { - all_facts.outlives.push((b_vid, a_vid, location)); - } - } + }); } } @@ -154,14 +146,12 @@ impl<'cx, 'tcx> SubtypeConstraintGenerator<'cx, 'tcx> { let lower_bound = self.to_region_vid(verify.region); - let point = locations.at_location().unwrap_or(Location::START); - let test = self.verify_bound_to_region_test(&verify.bound); TypeTest { generic_kind, lower_bound, - point, + locations: *locations, span, test, } diff --git a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs index 2b1878c33e90b..599f5bb8271f7 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/input_output.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/input_output.rs @@ -21,11 +21,11 @@ use borrow_check::nll::renumber; use borrow_check::nll::universal_regions::UniversalRegions; use rustc::hir::def_id::DefId; use rustc::infer::InferOk; -use rustc::ty::Ty; -use rustc::ty::subst::Subst; -use rustc::mir::*; use rustc::mir::visit::TyContext; +use rustc::mir::*; use rustc::traits::PredicateObligations; +use rustc::ty::subst::Subst; +use rustc::ty::Ty; use rustc_data_structures::indexed_vec::Idx; @@ -50,18 +50,18 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { // Equate expected input tys with those in the MIR. let argument_locals = (1..).map(Local::new); for (&unnormalized_input_ty, local) in unnormalized_input_tys.iter().zip(argument_locals) { - let input_ty = self.normalize(&unnormalized_input_ty, Locations::All); + let input_ty = self.normalize(&unnormalized_input_ty, Locations::Entry); let mir_input_ty = mir.local_decls[local].ty; - self.equate_normalized_input_or_output(input_ty, mir_input_ty); + self.equate_normalized_input_or_output(Locations::Entry, input_ty, mir_input_ty); } assert!( - mir.yield_ty.is_some() && universal_regions.yield_ty.is_some() || - mir.yield_ty.is_none() && universal_regions.yield_ty.is_none() + mir.yield_ty.is_some() && universal_regions.yield_ty.is_some() + || mir.yield_ty.is_none() && universal_regions.yield_ty.is_none() ); if let Some(mir_yield_ty) = mir.yield_ty { let ur_yield_ty = universal_regions.yield_ty.unwrap(); - self.equate_normalized_input_or_output(ur_yield_ty, mir_yield_ty); + self.equate_normalized_input_or_output(Locations::Yield, ur_yield_ty, mir_yield_ty); } // Return types are a bit more complex. They may contain existential `impl Trait` @@ -70,13 +70,13 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { "equate_inputs_and_outputs: unnormalized_output_ty={:?}", unnormalized_output_ty ); - let output_ty = self.normalize(&unnormalized_output_ty, Locations::All); + let output_ty = self.normalize(&unnormalized_output_ty, Locations::Return); debug!( "equate_inputs_and_outputs: normalized output_ty={:?}", output_ty ); let mir_output_ty = mir.local_decls[RETURN_PLACE].ty; - let anon_type_map = self.fully_perform_op(Locations::All, |cx| { + let anon_type_map = self.fully_perform_op(Locations::Return, |cx| { let mut obligations = ObligationAccumulator::default(); let (output_ty, anon_type_map) = obligations.add(infcx.instantiate_anon_types( @@ -127,23 +127,23 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { obligations: obligations.into_vec(), }) }).unwrap_or_else(|terr| { - span_mirbug!( - self, - Location::START, - "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`", - output_ty, - mir_output_ty, - terr - ); - None - }); + span_mirbug!( + self, + Location::START, + "equate_inputs_and_outputs: `{:?}=={:?}` failed with `{:?}`", + output_ty, + mir_output_ty, + terr + ); + None + }); // Finally, if we instantiated the anon types successfully, we // have to solve any bounds (e.g., `-> impl Iterator` needs to // prove that `T: Iterator` where `T` is the type we // instantiated it with). if let Some(anon_type_map) = anon_type_map { - self.fully_perform_op(Locations::All, |_cx| { + self.fully_perform_op(Locations::Return, |_cx| { infcx.constrain_anon_types(&anon_type_map, universal_regions); Ok(InferOk { value: (), @@ -153,10 +153,15 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { } } - fn equate_normalized_input_or_output(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) { + fn equate_normalized_input_or_output( + &mut self, + locations: Locations, + a: Ty<'tcx>, + b: Ty<'tcx>, + ) { debug!("equate_normalized_input_or_output(a={:?}, b={:?})", a, b); - if let Err(terr) = self.eq_types(a, b, Locations::All) { + if let Err(terr) = self.eq_types(a, b, locations) { span_mirbug!( self, Location::START, diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index 04f5024b76946..ee4c7a5ac84a8 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -624,38 +624,18 @@ pub struct OutlivesSet<'tcx> { /// want the constraint to hold at all points. #[derive(Copy, Clone, Debug)] pub enum Locations { - /// Indicates that a type constraint should always be true. This - /// is particularly important in the new borrowck analysis for - /// things like the type of the return slot. Consider this - /// example: - /// - /// ``` - /// fn foo<'a>(x: &'a u32) -> &'a u32 { - /// let y = 22; - /// return &y; // error - /// } - /// ``` - /// - /// Here, we wind up with the signature from the return type being - /// something like `&'1 u32` where `'1` is a universal region. But - /// the type of the return slot `_0` is something like `&'2 u32` - /// where `'2` is an existential region variable. The type checker - /// requires that `&'2 u32 = &'1 u32` -- but at what point? In the - /// older NLL analysis, we required this only at the entry point - /// to the function. By the nature of the constraints, this wound - /// up propagating to all points reachable from start (because - /// `'1` -- as a universal region -- is live everywhere). In the - /// newer analysis, though, this doesn't work: `_0` is considered - /// dead at the start (it has no usable value) and hence this type - /// equality is basically a no-op. Then, later on, when we do `_0 - /// = &'3 y`, that region `'3` never winds up related to the - /// universal region `'1` and hence no error occurs. Therefore, we - /// use Locations::All instead, which ensures that the `'1` and - /// `'2` are equal everything. We also use this for other - /// user-given type annotations; e.g., if the user wrote `let mut - /// x: &'static u32 = ...`, we would ensure that all values - /// assigned to `x` are of `'static` lifetime. - All, + /// At the location of every Yield terminator -- this occurs when + /// we are unifiying the "internal" view of the yield type with + /// the external view. + Yield, + + /// At the location of every Return terminator -- this occurs when + /// we are unifiying the "internal" view of the return type with + /// the external view. + Return, + + /// At the start location + Entry, Pair { /// The location in the MIR that generated these constraints. @@ -671,17 +651,35 @@ pub enum Locations { } impl Locations { - pub fn from_location(&self) -> Option { + crate fn span(&self, mir: &Mir<'_>) -> Span { match self { - Locations::All => None, - Locations::Pair { from_location, .. } => Some(*from_location), + Locations::Entry => mir.source_info(Location::START).span, + Locations::Return | Locations::Yield => mir.span, // FIXME + Locations::Pair { from_location, .. } => mir.source_info(*from_location).span, } } - pub fn at_location(&self) -> Option { + crate fn each_point(&self, mir: &Mir<'_>, mut op: impl FnMut(Location)) { + let mut want_yield = false; + let mut want_return = false; + match self { - Locations::All => None, - Locations::Pair { at_location, .. } => Some(*at_location), + Locations::Pair { from_location, .. } => return op(*from_location), + Locations::Entry => return op(Location::START), + Locations::Yield => want_yield = true, + Locations::Return => want_return = true, + } + + for (block, block_data) in mir.basic_blocks().iter_enumerated() { + let want_term = match block_data.terminator().kind { + TerminatorKind::Return => want_return, + TerminatorKind::Yield { .. } => want_yield, + _ => false, + }; + + if want_term { + op(mir.terminator_location(block)); + } } } } @@ -825,7 +823,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { "check_stmt: user_assert_ty ty={:?} local_ty={:?}", ty, local_ty ); - if let Err(terr) = self.eq_types(ty, local_ty, Locations::All) { + if let Err(terr) = self.eq_types(ty, local_ty, location.at_self()) { span_mirbug!( self, stmt, diff --git a/src/librustc_mir/util/liveness.rs b/src/librustc_mir/util/liveness.rs index cfb1a2cd28bcc..0e00d6383d345 100644 --- a/src/librustc_mir/util/liveness.rs +++ b/src/librustc_mir/util/liveness.rs @@ -355,6 +355,18 @@ impl<'tcx> Visitor<'tcx> for DefsUsesVisitor { None => {} } } + + fn visit_terminator( + &mut self, + block: BasicBlock, + terminator: &Terminator<'tcx>, + location: Location, + ) { + if let TerminatorKind::Return = terminator.kind { + self.defs_uses.add_use(RETURN_PLACE); + } + self.super_terminator(block, terminator, location); + } } fn block<'tcx>(mode: LivenessMode, b: &BasicBlockData<'tcx>, locals: usize) -> DefsUses { diff --git a/src/test/ui/borrowck/mut-borrow-in-loop.nll.stderr b/src/test/ui/borrowck/mut-borrow-in-loop.nll.stderr index 2284f0784c545..fc288e6b1d614 100644 --- a/src/test/ui/borrowck/mut-borrow-in-loop.nll.stderr +++ b/src/test/ui/borrowck/mut-borrow-in-loop.nll.stderr @@ -2,28 +2,19 @@ error[E0499]: cannot borrow `*arg` as mutable more than once at a time --> $DIR/mut-borrow-in-loop.rs:20:25 | LL | (self.func)(arg) //~ ERROR cannot borrow - | ------------^^^- - | | | - | | mutable borrow starts here in previous iteration of loop - | borrow later used here + | ^^^ mutable borrow starts here in previous iteration of loop error[E0499]: cannot borrow `*arg` as mutable more than once at a time --> $DIR/mut-borrow-in-loop.rs:26:25 | LL | (self.func)(arg) //~ ERROR cannot borrow - | ------------^^^- - | | | - | | mutable borrow starts here in previous iteration of loop - | borrow later used here + | ^^^ mutable borrow starts here in previous iteration of loop error[E0499]: cannot borrow `*arg` as mutable more than once at a time --> $DIR/mut-borrow-in-loop.rs:33:25 | LL | (self.func)(arg) //~ ERROR cannot borrow - | ------------^^^- - | | | - | | mutable borrow starts here in previous iteration of loop - | borrow later used here + | ^^^ mutable borrow starts here in previous iteration of loop error: aborting due to 3 previous errors diff --git a/src/test/ui/issue-46471.stderr b/src/test/ui/issue-46471.stderr index ac974afa13a1e..d446a9580ccf4 100644 --- a/src/test/ui/issue-46471.stderr +++ b/src/test/ui/issue-46471.stderr @@ -17,8 +17,6 @@ LL | &x ... LL | } | - borrowed value only lives until here - | - = note: borrowed value must be valid for the static lifetime... error: aborting due to 2 previous errors diff --git a/src/test/ui/issue-46472.stderr b/src/test/ui/issue-46472.stderr index 9b55b78b43d57..1dd4c356e5062 100644 --- a/src/test/ui/issue-46472.stderr +++ b/src/test/ui/issue-46472.stderr @@ -21,12 +21,6 @@ LL | &mut 4 ... LL | } | - temporary value only lives until here - | -note: borrowed value must be valid for the lifetime 'a as defined on the function body at 13:1... - --> $DIR/issue-46472.rs:13:1 - | -LL | fn bar<'a>() -> &'a mut u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/issue-46983.rs b/src/test/ui/issue-46983.rs index ebbd474b1c2b2..5fc25407b4ef3 100644 --- a/src/test/ui/issue-46983.rs +++ b/src/test/ui/issue-46983.rs @@ -11,8 +11,8 @@ #![feature(nll)] fn foo(x: &u32) -> &'static u32 { - &*x //~^ ERROR explicit lifetime required in the type of `x` [E0621] + &*x } fn main() {} diff --git a/src/test/ui/issue-46983.stderr b/src/test/ui/issue-46983.stderr index 31aeebd5a721e..8e4888859054a 100644 --- a/src/test/ui/issue-46983.stderr +++ b/src/test/ui/issue-46983.stderr @@ -1,10 +1,14 @@ error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/issue-46983.rs:14:5 + --> $DIR/issue-46983.rs:13:1 | -LL | fn foo(x: &u32) -> &'static u32 { - | - consider changing the type of `x` to `&'static u32` -LL | &*x - | ^^^ lifetime `'static` required +LL | fn foo(x: &u32) -> &'static u32 { + | ^ - consider changing the type of `x` to `&'static u32` + | _| + | | +LL | | //~^ ERROR explicit lifetime required in the type of `x` [E0621] +LL | | &*x +LL | | } + | |_^ lifetime `'static` required error: aborting due to previous error diff --git a/src/test/ui/nll/borrowed-universal-error-2.stderr b/src/test/ui/nll/borrowed-universal-error-2.stderr index 467b02d207dd2..b309dbf4f5578 100644 --- a/src/test/ui/nll/borrowed-universal-error-2.stderr +++ b/src/test/ui/nll/borrowed-universal-error-2.stderr @@ -6,12 +6,6 @@ LL | &v LL | //~^ ERROR `v` does not live long enough [E0597] LL | } | - borrowed value only lives until here - | -note: borrowed value must be valid for the lifetime 'a as defined on the function body at 14:1... - --> $DIR/borrowed-universal-error-2.rs:14:1 - | -LL | fn foo<'a>(x: &'a (u32,)) -> &'a u32 { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs index a6b2e531ac28f..79e8401ed1263 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs +++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.rs @@ -16,9 +16,9 @@ // compile-flags:-Zborrowck=mir -Zverbose fn foo(x: &u32) -> &'static u32 { + //~^ ERROR explicit lifetime required in the type of `x` &*x //~^ WARN not reporting region error due to nll - //~| ERROR explicit lifetime required in the type of `x` } fn main() { } diff --git a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr index a823e62d3b843..8f633147b0f92 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr +++ b/src/test/ui/nll/closure-requirements/region-lbr-anon-does-not-outlive-static.stderr @@ -1,16 +1,21 @@ warning: not reporting region error due to nll - --> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5 + --> $DIR/region-lbr-anon-does-not-outlive-static.rs:20:5 | LL | &*x | ^^^ error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/region-lbr-anon-does-not-outlive-static.rs:19:5 + --> $DIR/region-lbr-anon-does-not-outlive-static.rs:18:1 | -LL | fn foo(x: &u32) -> &'static u32 { - | - consider changing the type of `x` to `&ReStatic u32` -LL | &*x - | ^^^ lifetime `ReStatic` required +LL | fn foo(x: &u32) -> &'static u32 { + | ^ - consider changing the type of `x` to `&ReStatic u32` + | _| + | | +LL | | //~^ ERROR explicit lifetime required in the type of `x` +LL | | &*x +LL | | //~^ WARN not reporting region error due to nll +LL | | } + | |_^ lifetime `ReStatic` required error: aborting due to previous error 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..08cf538936047 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 @@ -16,9 +16,9 @@ // compile-flags:-Zborrowck=mir -Zverbose fn foo<'a>(x: &'a u32) -> &'static u32 { + //~^ ERROR does not outlive free region &*x //~^ WARN not reporting region error due to nll - //~| ERROR does not outlive free region } 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..99018ce7619f5 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 @@ -1,14 +1,18 @@ warning: not reporting region error due to nll - --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5 + --> $DIR/region-lbr-named-does-not-outlive-static.rs:20:5 | 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` - --> $DIR/region-lbr-named-does-not-outlive-static.rs:19:5 + --> $DIR/region-lbr-named-does-not-outlive-static.rs:18:1 | -LL | &*x - | ^^^ +LL | / fn foo<'a>(x: &'a u32) -> &'static u32 { +LL | | //~^ ERROR does not outlive free region +LL | | &*x +LL | | //~^ WARN not reporting region error due to nll +LL | | } + | |_^ error: aborting due to previous error diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs index 8598668bef50e..48a6383a6bdce 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs +++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.rs @@ -16,9 +16,9 @@ // compile-flags:-Zborrowck=mir -Zverbose fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 { + //~^ ERROR lifetime mismatch &*x //~^ WARN not reporting region error due to nll - //~| ERROR lifetime mismatch } fn main() { } diff --git a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr index 415aefdeee947..5154595da6320 100644 --- a/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr +++ b/src/test/ui/nll/closure-requirements/region-lbr1-does-not-outlive-ebr2.stderr @@ -1,18 +1,22 @@ warning: not reporting region error due to nll - --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:19:5 + --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:20:5 | LL | &*x | ^^^ error[E0623]: lifetime mismatch - --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:19:5 + --> $DIR/region-lbr1-does-not-outlive-ebr2.rs:18:1 | -LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 { - | ------- ------- - | | - | this parameter and the return type are declared with different lifetimes... -LL | &*x - | ^^^ ...but data from `x` is returned here +LL | fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> &'b u32 { + | ^ ------- ------- + | | | + | _| this parameter and the return type are declared with different lifetimes... + | | +LL | | //~^ ERROR lifetime mismatch +LL | | &*x +LL | | //~^ WARN not reporting region error due to nll +LL | | } + | |_^ ...but data from `x` is returned here error: aborting due to previous error 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 9e6fd28565e69..a9f4429b27316 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 @@ -5,10 +5,10 @@ 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))` - --> $DIR/return-wrong-bound-region.rs:21:23 + --> $DIR/return-wrong-bound-region.rs:21:16 | LL | expect_sig(|a, b| b); // ought to return `a` - | ^ + | ^^^^^^^^ note: No external requirements --> $DIR/return-wrong-bound-region.rs:21:16 diff --git a/src/test/ui/nll/guarantor-issue-46974.rs b/src/test/ui/nll/guarantor-issue-46974.rs index 09ce42ce1b551..e139e34213fac 100644 --- a/src/test/ui/nll/guarantor-issue-46974.rs +++ b/src/test/ui/nll/guarantor-issue-46974.rs @@ -20,9 +20,9 @@ fn foo(s: &mut (i32,)) -> i32 { *x } -fn bar(s: &Box<(i32,)>) -> &'static i32 { +fn bar(s: &Box<(i32,)>) -> &'static i32 { //~ ERROR explicit lifetime required // FIXME(#46983): error message should be better - &s.0 //~ ERROR explicit lifetime required in the type of `s` [E0621] + &s.0 } fn main() { diff --git a/src/test/ui/nll/guarantor-issue-46974.stderr b/src/test/ui/nll/guarantor-issue-46974.stderr index 3cb20cc975f4d..6b32b579b03e5 100644 --- a/src/test/ui/nll/guarantor-issue-46974.stderr +++ b/src/test/ui/nll/guarantor-issue-46974.stderr @@ -10,13 +10,16 @@ LL | *x | -- borrow later used here error[E0621]: explicit lifetime required in the type of `s` - --> $DIR/guarantor-issue-46974.rs:25:5 + --> $DIR/guarantor-issue-46974.rs:23:1 | -LL | fn bar(s: &Box<(i32,)>) -> &'static i32 { - | - consider changing the type of `s` to `&'static std::boxed::Box<(i32,)>` -LL | // FIXME(#46983): error message should be better -LL | &s.0 //~ ERROR explicit lifetime required in the type of `s` [E0621] - | ^^^^ lifetime `'static` required +LL | fn bar(s: &Box<(i32,)>) -> &'static i32 { //~ ERROR explicit lifetime required + | ^ - consider changing the type of `s` to `&'static std::boxed::Box<(i32,)>` + | _| + | | +LL | | // FIXME(#46983): error message should be better +LL | | &s.0 +LL | | } + | |_^ lifetime `'static` required error: aborting due to 2 previous errors diff --git a/src/test/ui/nll/issue-47470.stderr b/src/test/ui/nll/issue-47470.stderr index f84a68d85b95f..184f5d3483447 100644 --- a/src/test/ui/nll/issue-47470.stderr +++ b/src/test/ui/nll/issue-47470.stderr @@ -5,12 +5,6 @@ LL | &local //~ ERROR `local` does not live long enough | ^^^^^^ borrowed value does not live long enough LL | } | - borrowed value only lives until here - | -note: borrowed value must be valid for the lifetime 'a as defined on the impl at 23:1... - --> $DIR/issue-47470.rs:23:1 - | -LL | impl<'a> Bar for Foo<'a> { - | ^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/nll/issue-48238.stderr b/src/test/ui/nll/issue-48238.stderr index 29385d9b2430f..dcc7a679b7ff8 100644 --- a/src/test/ui/nll/issue-48238.stderr +++ b/src/test/ui/nll/issue-48238.stderr @@ -1,8 +1,8 @@ error: free region `` does not outlive free region `'_#1r` - --> $DIR/issue-48238.rs:21:21 + --> $DIR/issue-48238.rs:21:5 | LL | move || use_val(&orig); //~ ERROR free region `` does not outlive free region `'_#1r` - | ^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs index f21127064d4c2..9985b53281069 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.rs +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.rs @@ -18,9 +18,9 @@ trait Foo<'a> { impl<'a, T> Foo<'a> for T { } fn foo<'a, T>(x: &T) -> impl Foo<'a> { + //~^ ERROR explicit lifetime required in the type of `x` [E0621] x //~^ WARNING not reporting region error due to nll - //~| ERROR explicit lifetime required in the type of `x` [E0621] } fn main() {} diff --git a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr index f836960a28cf3..feab04c802c26 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-captures.stderr @@ -1,16 +1,21 @@ warning: not reporting region error due to nll - --> $DIR/impl-trait-captures.rs:21:5 + --> $DIR/impl-trait-captures.rs:22:5 | LL | x | ^ error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/impl-trait-captures.rs:21:5 + --> $DIR/impl-trait-captures.rs:20:1 | -LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { - | - consider changing the type of `x` to `&ReEarlyBound(0, 'a) T` -LL | x - | ^ lifetime `ReEarlyBound(0, 'a)` required +LL | fn foo<'a, T>(x: &T) -> impl Foo<'a> { + | ^ - consider changing the type of `x` to `&ReEarlyBound(0, 'a) T` + | _| + | | +LL | | //~^ ERROR explicit lifetime required in the type of `x` [E0621] +LL | | x +LL | | //~^ WARNING not reporting region error due to nll +LL | | } + | |_^ lifetime `ReEarlyBound(0, 'a)` required error: aborting due to previous error diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs index 182e11da082f8..a639791bc6b4c 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.rs @@ -16,11 +16,11 @@ use std::fmt::Debug; fn no_region<'a, T>(x: Box) -> impl Debug + 'a //~^ WARNING not reporting region error due to nll + //~| ERROR the parameter type `T` may not live long enough [E0309] where T: Debug, { x - //~^ ERROR the parameter type `T` may not live long enough [E0309] } fn correct_region<'a, T>(x: Box) -> impl Debug + 'a @@ -32,11 +32,11 @@ where fn wrong_region<'a, 'b, T>(x: Box) -> impl Debug + 'a //~^ WARNING not reporting region error due to nll + //~| ERROR the parameter type `T` may not live long enough [E0309] where T: 'b + Debug, { x - //~^ ERROR the parameter type `T` may not live long enough [E0309] } fn outlives_region<'a, 'b, T>(x: Box) -> impl Debug + 'a diff --git a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr index 50b80282e6241..84cf2b56d422f 100644 --- a/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr +++ b/src/test/ui/nll/ty-outlives/impl-trait-outlives.stderr @@ -11,18 +11,30 @@ LL | fn wrong_region<'a, 'b, T>(x: Box) -> impl Debug + 'a | ^^^^^^^^^^^^^^^ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/impl-trait-outlives.rs:22:5 + --> $DIR/impl-trait-outlives.rs:17:1 | -LL | x - | ^ +LL | / fn no_region<'a, T>(x: Box) -> impl Debug + 'a +LL | | //~^ WARNING not reporting region error due to nll +LL | | //~| ERROR the parameter type `T` may not live long enough [E0309] +LL | | where +... | +LL | | x +LL | | } + | |_^ | = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`... error[E0309]: the parameter type `T` may not live long enough - --> $DIR/impl-trait-outlives.rs:38:5 + --> $DIR/impl-trait-outlives.rs:33:1 | -LL | x - | ^ +LL | / fn wrong_region<'a, 'b, T>(x: Box) -> impl Debug + 'a +LL | | //~^ WARNING not reporting region error due to nll +LL | | //~| ERROR the parameter type `T` may not live long enough [E0309] +LL | | where +... | +LL | | x +LL | | } + | |_^ | = help: consider adding an explicit lifetime bound `T: ReEarlyBound(0, 'a)`...