From aa8d5bff4c0fe9e7c1d50a0827b2c734406c3896 Mon Sep 17 00:00:00 2001 From: dianne Date: Thu, 12 Dec 2024 01:20:26 -0800 Subject: [PATCH 01/12] cleanup: remove `ExtraConstraintInfo` `ExtraConstraintInfo` was used only for a single subdiagnostic, so this moves the logic for that to its own function and eliminates the indirection. In order to do so cleanly, this also changes the arguments to `BorrowExplanation::add_explanation_to_diagnostic`, which happens to simplify its call sites. --- .../src/diagnostics/conflict_errors.rs | 75 +++---------------- .../src/diagnostics/explain_borrow.rs | 37 +++++---- .../rustc_borrowck/src/diagnostics/mod.rs | 36 ++++++++- .../src/diagnostics/region_errors.rs | 17 ++--- .../rustc_borrowck/src/region_infer/mod.rs | 34 ++------- 5 files changed, 68 insertions(+), 131 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 8e5944d6cf45e..2d993a3fd16f7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1516,15 +1516,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { }); self.explain_why_borrow_contains_point(location, borrow, None) - .add_explanation_to_diagnostic( - self.infcx.tcx, - self.body, - &self.local_names, - &mut err, - "", - Some(borrow_span), - None, - ); + .add_explanation_to_diagnostic(&self, &mut err, "", Some(borrow_span), None); self.suggest_copy_for_type_in_cloned_ref(&mut err, place); let typeck_results = self.infcx.tcx.typeck(self.mir_def_id()); if let Some(expr) = self.find_expr(borrow_span) { @@ -1591,15 +1583,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { }); self.explain_why_borrow_contains_point(location, borrow, None) - .add_explanation_to_diagnostic( - self.infcx.tcx, - self.body, - &self.local_names, - &mut err, - "", - None, - None, - ); + .add_explanation_to_diagnostic(&self, &mut err, "", None, None); err } @@ -1886,9 +1870,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } explanation.add_explanation_to_diagnostic( - self.infcx.tcx, - self.body, - &self.local_names, + &self, &mut err, first_borrow_desc, None, @@ -3046,15 +3028,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { if let BorrowExplanation::MustBeValidFor { .. } = explanation { } else { - explanation.add_explanation_to_diagnostic( - self.infcx.tcx, - self.body, - &self.local_names, - &mut err, - "", - None, - None, - ); + explanation.add_explanation_to_diagnostic(&self, &mut err, "", None, None); } } else { err.span_label(borrow_span, "borrowed value does not live long enough"); @@ -3067,15 +3041,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } }); - explanation.add_explanation_to_diagnostic( - self.infcx.tcx, - self.body, - &self.local_names, - &mut err, - "", - Some(borrow_span), - None, - ); + explanation.add_explanation_to_diagnostic(&self, &mut err, "", Some(borrow_span), None); } err @@ -3128,15 +3094,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { _ => {} } - explanation.add_explanation_to_diagnostic( - self.infcx.tcx, - self.body, - &self.local_names, - &mut err, - "", - None, - None, - ); + explanation.add_explanation_to_diagnostic(&self, &mut err, "", None, None); self.buffer_error(err); } @@ -3309,15 +3267,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } _ => {} } - explanation.add_explanation_to_diagnostic( - self.infcx.tcx, - self.body, - &self.local_names, - &mut err, - "", - None, - None, - ); + explanation.add_explanation_to_diagnostic(&self, &mut err, "", None, None); borrow_spans.args_subdiag(&mut err, |args_span| { crate::session_diagnostics::CaptureArgLabel::Capture { @@ -3808,15 +3758,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } }); - self.explain_why_borrow_contains_point(location, loan, None).add_explanation_to_diagnostic( - self.infcx.tcx, - self.body, - &self.local_names, - &mut err, - "", - None, - None, - ); + self.explain_why_borrow_contains_point(location, loan, None) + .add_explanation_to_diagnostic(&self, &mut err, "", None, None); self.explain_deref_coercion(loan, &mut err); diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 87017460e8ec3..860d6338a0284 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -8,7 +8,6 @@ use std::assert_matches::assert_matches; use rustc_errors::{Applicability, Diag}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; -use rustc_index::IndexSlice; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::mir::{ @@ -18,14 +17,15 @@ use rustc_middle::mir::{ use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt}; use rustc_middle::util::CallKind; -use rustc_span::{DesugaringKind, Span, Symbol, kw, sym}; +use rustc_span::{DesugaringKind, Span, kw, sym}; use rustc_trait_selection::error_reporting::traits::FindExprBySpan; use tracing::{debug, instrument}; use super::{RegionName, UseSpans, find_use}; use crate::borrow_set::BorrowData; +use crate::constraints::OutlivesConstraint; use crate::nll::ConstraintDescription; -use crate::region_infer::{BlameConstraint, Cause, ExtraConstraintInfo}; +use crate::region_infer::{BlameConstraint, Cause}; use crate::{MirBorrowckCtxt, WriteKind}; #[derive(Debug)] @@ -43,7 +43,7 @@ pub(crate) enum BorrowExplanation<'tcx> { span: Span, region_name: RegionName, opt_place_desc: Option, - extra_info: Vec, + path: Vec>, }, Unexplained, } @@ -63,14 +63,16 @@ impl<'tcx> BorrowExplanation<'tcx> { } pub(crate) fn add_explanation_to_diagnostic( &self, - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, - local_names: &IndexSlice>, + cx: &MirBorrowckCtxt<'_, '_, 'tcx>, err: &mut Diag<'_>, borrow_desc: &str, borrow_span: Option, multiple_borrow_span: Option<(Span, Span)>, ) { + let tcx = cx.infcx.tcx; + let body = cx.body; + let local_names = &cx.local_names; + if let Some(span) = borrow_span { let def_id = body.source.def_id(); if let Some(node) = tcx.hir().get_if_local(def_id) @@ -306,7 +308,7 @@ impl<'tcx> BorrowExplanation<'tcx> { ref region_name, ref opt_place_desc, from_closure: _, - ref extra_info, + ref path, } => { region_name.highlight_region_name(err); @@ -328,13 +330,7 @@ impl<'tcx> BorrowExplanation<'tcx> { ); }; - for extra in extra_info { - match extra { - ExtraConstraintInfo::PlaceholderFromPredicate(span) => { - err.span_note(*span, "due to current limitations in the borrow checker, this implies a `'static` lifetime"); - } - } - } + cx.add_placeholder_from_predicate_note(err, &path); if let ConstraintCategory::Cast { is_implicit_coercion: true, @@ -487,8 +483,9 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { &self, borrow_region: RegionVid, outlived_region: RegionVid, - ) -> (ConstraintCategory<'tcx>, bool, Span, Option, Vec) { - let (blame_constraint, extra_info) = self.regioncx.best_blame_constraint( + ) -> (ConstraintCategory<'tcx>, bool, Span, Option, Vec>) + { + let (blame_constraint, path) = self.regioncx.best_blame_constraint( borrow_region, NllRegionVariableOrigin::FreeRegion, |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region), @@ -497,7 +494,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { let outlived_fr_name = self.give_region_a_name(outlived_region); - (category, from_closure, cause.span, outlived_fr_name, extra_info) + (category, from_closure, cause.span, outlived_fr_name, path) } /// Returns structured explanation for *why* the borrow contains the @@ -596,7 +593,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { None => { if let Some(region) = self.to_error_region_vid(borrow_region_vid) { - let (category, from_closure, span, region_name, extra_info) = + let (category, from_closure, span, region_name, path) = self.free_region_constraint_info(borrow_region_vid, region); if let Some(region_name) = region_name { let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref()); @@ -606,7 +603,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { span, region_name, opt_place_desc, - extra_info, + path, } } else { debug!("Could not generate a region name"); diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index ebbdfea302cd3..c9100f23e12e7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -8,14 +8,16 @@ use rustc_errors::{Applicability, Diag, MultiSpan}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::{self as hir, CoroutineKind, LangItem}; use rustc_index::IndexSlice; -use rustc_infer::infer::BoundRegionConversionTime; +use rustc_infer::infer::{ + BoundRegionConversionTime, NllRegionVariableOrigin, RegionVariableOrigin, +}; use rustc_infer::traits::SelectionError; use rustc_middle::bug; use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::{ - AggregateKind, CallSource, ConstOperand, FakeReadCause, Local, LocalInfo, LocalKind, Location, - Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, - TerminatorKind, + AggregateKind, CallSource, ConstOperand, ConstraintCategory, FakeReadCause, Local, LocalInfo, + LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, + StatementKind, Terminator, TerminatorKind, }; use rustc_middle::ty::print::Print; use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; @@ -33,6 +35,7 @@ use tracing::debug; use super::MirBorrowckCtxt; use super::borrow_set::BorrowData; +use crate::constraints::OutlivesConstraint; use crate::fluent_generated as fluent; use crate::session_diagnostics::{ CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause, @@ -619,6 +622,31 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { region.print(&mut printer).unwrap(); printer.into_buffer() } + + /// Add a note to region errors and borrow explanations when higher-ranked regions in predicates + /// implicitly introduce an "outlives `'static`" constraint. + fn add_placeholder_from_predicate_note( + &self, + err: &mut Diag<'_>, + path: &[OutlivesConstraint<'tcx>], + ) { + let predicate_span = path.iter().find_map(|constraint| { + let outlived = constraint.sub; + if let Some(origin) = self.regioncx.var_infos.get(outlived) + && let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(_)) = + origin.origin + && let ConstraintCategory::Predicate(span) = constraint.category + { + Some(span) + } else { + None + } + }); + + if let Some(span) = predicate_span { + err.span_note(span, "due to current limitations in the borrow checker, this implies a `'static` lifetime"); + } + } } /// The span(s) associated to a use of a place. diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 3555009c63f4a..481b8d41f10cd 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -29,7 +29,7 @@ use tracing::{debug, instrument, trace}; use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource}; use crate::nll::ConstraintDescription; use crate::region_infer::values::RegionElement; -use crate::region_infer::{BlameConstraint, ExtraConstraintInfo, TypeTest}; +use crate::region_infer::{BlameConstraint, TypeTest}; use crate::session_diagnostics::{ FnMutError, FnMutReturnTypeErr, GenericDoesNotLiveLongEnough, LifetimeOutliveErr, LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote, @@ -440,10 +440,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ) { debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr); - let (blame_constraint, extra_info) = - self.regioncx.best_blame_constraint(fr, fr_origin, |r| { - self.regioncx.provides_universal_region(r, fr, outlived_fr) - }); + let (blame_constraint, path) = self.regioncx.best_blame_constraint(fr, fr_origin, |r| { + self.regioncx.provides_universal_region(r, fr, outlived_fr) + }); let BlameConstraint { category, cause, variance_info, .. } = blame_constraint; debug!("report_region_error: category={:?} {:?} {:?}", category, cause, variance_info); @@ -554,13 +553,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } } - for extra in extra_info { - match extra { - ExtraConstraintInfo::PlaceholderFromPredicate(span) => { - diag.span_note(span, "due to current limitations in the borrow checker, this implies a `'static` lifetime"); - } - } - } + self.add_placeholder_from_predicate_note(&mut diag, &path); self.buffer_error(diag); } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 2150759d329ea..b49fa463a4f9e 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -315,11 +315,6 @@ enum Trace<'tcx> { NotVisited, } -#[derive(Clone, PartialEq, Eq, Debug)] -pub(crate) enum ExtraConstraintInfo { - PlaceholderFromPredicate(Span), -} - #[instrument(skip(infcx, sccs), level = "debug")] fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) { use crate::renumber::RegionCtxt; @@ -1948,7 +1943,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { from_region: RegionVid, from_region_origin: NllRegionVariableOrigin, target_test: impl Fn(RegionVid) -> bool, - ) -> (BlameConstraint<'tcx>, Vec) { + ) -> (BlameConstraint<'tcx>, Vec>) { // Find all paths let (path, target_region) = self .find_constraint_paths_between_regions(from_region, target_test) @@ -1970,25 +1965,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { .collect::>() ); - let mut extra_info = vec![]; - for constraint in path.iter() { - let outlived = constraint.sub; - let Some(origin) = self.var_infos.get(outlived) else { - continue; - }; - let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(p)) = origin.origin - else { - continue; - }; - debug!(?constraint, ?p); - let ConstraintCategory::Predicate(span) = constraint.category else { - continue; - }; - extra_info.push(ExtraConstraintInfo::PlaceholderFromPredicate(span)); - // We only want to point to one - break; - } - // We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint. // Instead, we use it to produce an improved `ObligationCauseCode`. // FIXME - determine what we should do if we encounter multiple @@ -2115,7 +2091,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { let best_choice = if blame_source { range.rev().find(find_region) } else { range.find(find_region) }; - debug!(?best_choice, ?blame_source, ?extra_info); + debug!(?best_choice, ?blame_source); if let Some(i) = best_choice { if let Some(next) = categorized_path.get(i + 1) { @@ -2124,7 +2100,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { { // The return expression is being influenced by the return type being // impl Trait, point at the return type and not the return expr. - return (next.clone(), extra_info); + return (next.clone(), path); } } @@ -2144,7 +2120,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } - return (categorized_path[i].clone(), extra_info); + return (categorized_path[i].clone(), path); } // If that search fails, that is.. unusual. Maybe everything @@ -2154,7 +2130,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { categorized_path.sort_by_key(|p| p.category); debug!("sorted_path={:#?}", categorized_path); - (categorized_path.remove(0), extra_info) + (categorized_path.remove(0), path) } pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { From 2249232ad8886089221fbd68016dbee0ee2484bc Mon Sep 17 00:00:00 2001 From: dianne Date: Thu, 12 Dec 2024 02:00:07 -0800 Subject: [PATCH 02/12] further clean up `best_blame_constraint` This gets rid of `categorized_path`, as it was redundant given the `OutlivesConstraint`s in `path` already have a category field. --- compiler/rustc_borrowck/src/lib.rs | 1 + .../rustc_borrowck/src/region_infer/mod.rs | 95 +++++++++---------- 2 files changed, 46 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index b061a450c83f7..f0eda61d93682 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -6,6 +6,7 @@ #![feature(assert_matches)] #![feature(box_patterns)] #![feature(file_buffered)] +#![feature(if_let_guard)] #![feature(let_chains)] #![feature(never_type)] #![feature(rustc_attrs)] diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index b49fa463a4f9e..058aec58e7876 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1983,18 +1983,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) .unwrap_or_else(|| ObligationCauseCode::Misc); - // Classify each of the constraints along the path. - let mut categorized_path: Vec> = path - .iter() - .map(|constraint| BlameConstraint { - category: constraint.category, - from_closure: constraint.from_closure, - cause: ObligationCause::new(constraint.span, CRATE_DEF_ID, cause_code.clone()), - variance_info: constraint.variance_info, - }) - .collect(); - debug!("categorized_path={:#?}", categorized_path); - // To find the best span to cite, we first try to look for the // final constraint that is interesting and where the `sup` is // not unified with the ultimate target region. The reason @@ -2015,7 +2003,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { // we still want to screen for an "interesting" point to // highlight (e.g., a call site or something). let target_scc = self.constraint_sccs.scc(target_region); - let mut range = 0..path.len(); // As noted above, when reporting an error, there is typically a chain of constraints // leading from some "source" region which must outlive some "target" region. @@ -2059,13 +2046,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { | NllRegionVariableOrigin::Existential { from_forall: true } => false, }; - let find_region = |i: &usize| { - let constraint = &path[*i]; - + let interesting_to_blame = |constraint: &OutlivesConstraint<'tcx>| { let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup); if blame_source { - match categorized_path[*i].category { + match constraint.category { ConstraintCategory::OpaqueType | ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation @@ -2078,7 +2063,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } else { !matches!( - categorized_path[*i].category, + constraint.category, ConstraintCategory::OpaqueType | ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation @@ -2088,49 +2073,59 @@ impl<'tcx> RegionInferenceContext<'tcx> { } }; - let best_choice = - if blame_source { range.rev().find(find_region) } else { range.find(find_region) }; + let best_choice = if blame_source { + path.iter().rposition(interesting_to_blame) + } else { + path.iter().position(interesting_to_blame) + }; debug!(?best_choice, ?blame_source); - if let Some(i) = best_choice { - if let Some(next) = categorized_path.get(i + 1) { - if matches!(categorized_path[i].category, ConstraintCategory::Return(_)) - && next.category == ConstraintCategory::OpaqueType - { - // The return expression is being influenced by the return type being - // impl Trait, point at the return type and not the return expr. - return (next.clone(), path); - } + let best_constraint = match best_choice { + Some(i) + if let Some(next) = path.get(i + 1) + && matches!(path[i].category, ConstraintCategory::Return(_)) + && next.category == ConstraintCategory::OpaqueType => + { + // The return expression is being influenced by the return type being + // impl Trait, point at the return type and not the return expr. + *next } - if categorized_path[i].category == ConstraintCategory::Return(ReturnConstraint::Normal) + Some(i) + if path[i].category == ConstraintCategory::Return(ReturnConstraint::Normal) + && let Some(field) = path.iter().find_map(|p| { + if let ConstraintCategory::ClosureUpvar(f) = p.category { + Some(f) + } else { + None + } + }) => { - let field = categorized_path.iter().find_map(|p| { - if let ConstraintCategory::ClosureUpvar(f) = p.category { - Some(f) - } else { - None - } - }); - - if let Some(field) = field { - categorized_path[i].category = - ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field)); + OutlivesConstraint { + category: ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field)), + ..path[i] } } - return (categorized_path[i].clone(), path); - } + Some(i) => path[i], - // If that search fails, that is.. unusual. Maybe everything - // is in the same SCC or something. In that case, find what - // appears to be the most interesting point to report to the - // user via an even more ad-hoc guess. - categorized_path.sort_by_key(|p| p.category); - debug!("sorted_path={:#?}", categorized_path); + None => { + // If that search fails, that is.. unusual. Maybe everything + // is in the same SCC or something. In that case, find what + // appears to be the most interesting point to report to the + // user via an even more ad-hoc guess. + *path.iter().min_by_key(|p| p.category).unwrap() + } + }; - (categorized_path.remove(0), path) + let blame_constraint = BlameConstraint { + category: best_constraint.category, + from_closure: best_constraint.from_closure, + cause: ObligationCause::new(best_constraint.span, CRATE_DEF_ID, cause_code.clone()), + variance_info: best_constraint.variance_info, + }; + (blame_constraint, path) } pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { From ac922245f0c86657a56d3ca5eff4a1d1b1fcb0a1 Mon Sep 17 00:00:00 2001 From: dianne Date: Wed, 4 Dec 2024 03:19:03 -0800 Subject: [PATCH 03/12] `best_blame_constraint`: don't filter constraints by sup SCC The SCCs of the region graph are not a reliable heuristic to use for blaming an interesting constraint for diagnostics. For region errors, if the outlived region is `'static`, or the involved types are invariant in their lifetiems, there will be cycles in the constraint graph containing both the target region and the most interesting constraints to blame. To get better diagnostics in these cases, this commit removes that heuristic. --- .../rustc_borrowck/src/region_infer/mod.rs | 60 +++------------ ...-types-project-from-hrtb-in-fn-body.stderr | 8 +- .../project-fn-ret-invariant.oneuse.stderr | 8 +- ...t-precise-captures-we-are-powerless.stderr | 48 ++++++------ tests/ui/async-await/issue-76547.rs | 4 +- tests/ui/async-await/issue-76547.stderr | 22 +++--- .../borrowck/fn-item-check-type-params.stderr | 4 +- ...ation-not-general-enough-ice-133252.stderr | 8 +- tests/ui/borrowck/issue-7573.rs | 2 + tests/ui/borrowck/issue-7573.stderr | 4 + .../two-phase-surprise-no-conflict.stderr | 22 +++--- tests/ui/c-variadic/variadic-ffi-4.stderr | 6 +- ...-trait-obj-different-regions-lt-ext.stderr | 2 +- ...ptr-to-trait-obj-different-regions-misc.rs | 2 +- ...to-trait-obj-different-regions-misc.stderr | 38 +++++----- tests/ui/coroutine/resume-arg-outlives-2.rs | 2 +- .../ui/coroutine/resume-arg-outlives-2.stderr | 24 +++--- .../dropck/dropck_trait_cycle_checked.stderr | 42 ++++++----- tests/ui/fn/fn_def_coercion.rs | 4 +- tests/ui/fn/fn_def_coercion.stderr | 41 ++++++----- .../precise-capturing/migration-note.rs | 4 +- .../precise-capturing/migration-note.stderr | 16 ++-- .../const-expr-lifetime-err.stderr | 7 +- .../const-match-pat-lifetime-err.stderr | 2 +- tests/ui/issues/issue-15034.stderr | 4 +- .../ui/kindck/kindck-impl-type-params.stderr | 4 +- tests/ui/lifetimes/copy_modulo_regions.stderr | 6 +- .../issue-90170-elision-mismatch.stderr | 9 +++ ...e-90600-expected-return-static-indirect.rs | 2 +- ...600-expected-return-static-indirect.stderr | 28 ++++--- .../ex2b-push-no-existing-names.stderr | 3 + .../ex2c-push-inference-variable.stderr | 3 + .../ex2d-push-inference-variable-2.rs | 2 +- .../ex2d-push-inference-variable-2.stderr | 10 ++- .../ex2e-push-inference-variable-3.rs | 2 +- .../ex2e-push-inference-variable-3.stderr | 10 ++- .../ex3-both-anon-regions-2.rs | 2 +- .../ex3-both-anon-regions-2.stderr | 14 ++-- .../ex3-both-anon-regions-3.stderr | 6 ++ ...both-are-structs-earlybound-regions.stderr | 3 + ...-both-are-structs-latebound-regions.stderr | 3 + ...-both-anon-regions-both-are-structs.stderr | 3 + ...both-anon-regions-latebound-regions.stderr | 3 + ...x3-both-anon-regions-using-fn-items.stderr | 3 + ...-both-anon-regions-using-impl-items.stderr | 3 + ...th-anon-regions-using-trait-objects.stderr | 3 + .../ex3-both-anon-regions.stderr | 3 + .../ui/match/match-ref-mut-invariance.stderr | 4 +- .../ui/match/match-ref-mut-let-invariance.rs | 2 +- .../match/match-ref-mut-let-invariance.stderr | 5 +- ...pagate-approximated-fail-no-postdom.stderr | 4 + .../propagate-approximated-ref.rs | 3 +- .../propagate-approximated-ref.stderr | 20 +++-- ...er-to-static-comparing-against-free.stderr | 12 ++- ...approximated-shorter-to-static-no-bound.rs | 3 +- ...oximated-shorter-to-static-no-bound.stderr | 27 +++---- ...roximated-shorter-to-static-wrong-bound.rs | 3 +- ...mated-shorter-to-static-wrong-bound.stderr | 27 +++---- .../propagate-approximated-val.rs | 3 +- .../propagate-approximated-val.stderr | 20 +++-- ...ail-to-approximate-longer-no-bounds.stderr | 4 + ...-to-approximate-longer-wrong-bounds.stderr | 4 + .../nll/issue-54779-anon-static-lifetime.rs | 2 +- .../issue-54779-anon-static-lifetime.stderr | 14 +++- .../nll/issue-62007-assign-const-index.stderr | 7 +- ...issue-62007-assign-differing-fields.stderr | 7 +- tests/ui/nll/issue-67007-escaping-data.rs | 4 +- tests/ui/nll/issue-67007-escaping-data.stderr | 8 +- tests/ui/nll/issue-95272.rs | 2 +- tests/ui/nll/issue-95272.stderr | 9 ++- .../ui/nll/outlives-suggestion-simple.stderr | 4 + .../assignment-to-differing-field.stderr | 16 ++-- ...insensitive-scopes-issue-117146.nll.stderr | 35 ++++----- ...sitive-scopes-issue-117146.polonius.stderr | 35 ++++----- ...ocation-insensitive-scopes-issue-117146.rs | 4 +- .../nll/relate_tys/var-appears-twice.stderr | 7 +- .../projection-one-region-closure.stderr | 58 ++++++++------- ...tion-one-region-trait-bound-closure.stderr | 14 +++- ...tion-two-region-trait-bound-closure.stderr | 2 +- .../user-annotations/adt-nullary-enums.stderr | 73 +++++++++---------- .../adt-tuple-struct-calls.stderr | 18 ++--- .../nll/user-annotations/method-ufcs-1.stderr | 7 +- .../nll/user-annotations/method-ufcs-2.stderr | 7 +- tests/ui/nll/where_clauses_in_structs.stderr | 4 +- ...er-blame-constraint-for-outlives-static.rs | 13 ++++ ...lame-constraint-for-outlives-static.stderr | 11 +++ ...h-suggestion-regression-test-124563.stderr | 4 + ...region-invariant-static-error-reporting.rs | 6 +- ...on-invariant-static-error-reporting.stderr | 18 ++--- ...t-static-bound-needing-more-suggestions.rs | 2 +- ...atic-bound-needing-more-suggestions.stderr | 25 ++++--- .../ui/traits/coercion-generic-regions.stderr | 6 +- .../trait-object-lifetime-default-note.rs | 3 +- .../trait-object-lifetime-default-note.stderr | 6 +- .../type-checking-test-3.stderr | 4 +- .../type-checking-test-4.stderr | 4 +- ...-argument-types-two-region-pointers.stderr | 4 + ...underscore-lifetime-elison-mismatch.stderr | 3 + .../variance-associated-types2.stderr | 4 +- .../variance-contravariant-arg-object.stderr | 2 +- .../variance-covariant-arg-object.stderr | 2 +- .../variance-invariant-arg-object.stderr | 2 +- 102 files changed, 592 insertions(+), 514 deletions(-) create mode 100644 tests/ui/regions/better-blame-constraint-for-outlives-static.rs create mode 100644 tests/ui/regions/better-blame-constraint-for-outlives-static.stderr diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 058aec58e7876..4c2aeace67ed9 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1945,7 +1945,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { target_test: impl Fn(RegionVid) -> bool, ) -> (BlameConstraint<'tcx>, Vec>) { // Find all paths - let (path, target_region) = self + let (path, _) = self .find_constraint_paths_between_regions(from_region, target_test) .or_else(|| { self.find_constraint_paths_between_regions(from_region, |r| { @@ -1983,29 +1983,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) .unwrap_or_else(|| ObligationCauseCode::Misc); - // To find the best span to cite, we first try to look for the - // final constraint that is interesting and where the `sup` is - // not unified with the ultimate target region. The reason - // for this is that we have a chain of constraints that lead - // from the source to the target region, something like: - // - // '0: '1 ('0 is the source) - // '1: '2 - // '2: '3 - // '3: '4 - // '4: '5 - // '5: '6 ('6 is the target) - // - // Some of those regions are unified with `'6` (in the same - // SCC). We want to screen those out. After that point, the - // "closest" constraint we have to the end is going to be the - // most likely to be the point where the value escapes -- but - // we still want to screen for an "interesting" point to - // highlight (e.g., a call site or something). - let target_scc = self.constraint_sccs.scc(target_region); - - // As noted above, when reporting an error, there is typically a chain of constraints - // leading from some "source" region which must outlive some "target" region. + // When reporting an error, there is typically a chain of constraints leading from some + // "source" region which must outlive some "target" region. // In most cases, we prefer to "blame" the constraints closer to the target -- // but there is one exception. When constraints arise from higher-ranked subtyping, // we generally prefer to blame the source value, @@ -2047,30 +2026,14 @@ impl<'tcx> RegionInferenceContext<'tcx> { }; let interesting_to_blame = |constraint: &OutlivesConstraint<'tcx>| { - let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup); - - if blame_source { - match constraint.category { - ConstraintCategory::OpaqueType + !matches!( + constraint.category, + ConstraintCategory::OpaqueType | ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal - | ConstraintCategory::Predicate(_) => false, - ConstraintCategory::TypeAnnotation - | ConstraintCategory::Return(_) - | ConstraintCategory::Yield => true, - _ => constraint_sup_scc != target_scc, - } - } else { - !matches!( - constraint.category, - ConstraintCategory::OpaqueType - | ConstraintCategory::Boring - | ConstraintCategory::BoringNoLocation - | ConstraintCategory::Internal - | ConstraintCategory::Predicate(_) - ) - } + | ConstraintCategory::Predicate(_) + ) }; let best_choice = if blame_source { @@ -2111,10 +2074,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { Some(i) => path[i], None => { - // If that search fails, that is.. unusual. Maybe everything - // is in the same SCC or something. In that case, find what - // appears to be the most interesting point to report to the - // user via an even more ad-hoc guess. + // If that search fails, the only constraints on the path are those that we try not + // to blame. In that case, find what appears to be the most interesting point to + // report to the user via an even more ad-hoc guess. *path.iter().min_by_key(|p| p.category).unwrap() } }; diff --git a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr index e12d42e5ed0cc..42d83fca6ca83 100644 --- a/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr +++ b/tests/ui/associated-types/associated-types-project-from-hrtb-in-fn-body.stderr @@ -7,9 +7,9 @@ LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>( | lifetime `'a` defined here ... LL | let z: I::A = if cond { x } else { y }; - | ^ assignment requires that `'a` must outlive `'b` + | ^ assignment requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` error: lifetime may not live long enough --> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:22:40 @@ -20,9 +20,9 @@ LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>( | lifetime `'a` defined here ... LL | let z: I::A = if cond { x } else { y }; - | ^ assignment requires that `'b` must outlive `'a` + | ^ assignment requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` help: `'a` and `'b` must be the same: replace one with the other diff --git a/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr b/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr index 77841780f6216..3ef6b85c407af 100644 --- a/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr +++ b/tests/ui/associated-types/cache/project-fn-ret-invariant.oneuse.stderr @@ -7,9 +7,9 @@ LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { | lifetime `'a` defined here LL | let f = foo; // <-- No consistent type can be inferred for `f` here. LL | let a = bar(f, x); - | ^^^^^^^^^ argument requires that `'a` must outlive `'b` + | ^^^^^^^^^ argument requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant = note: the struct `Type<'a>` is invariant over the parameter `'a` = help: see for more information about variance @@ -23,9 +23,9 @@ LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) { | lifetime `'a` defined here ... LL | let b = bar(f, y); - | ^^^^^^^^^ argument requires that `'b` must outlive `'a` + | ^^^^^^^^^ argument requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant = note: the struct `Type<'a>` is invariant over the parameter `'a` = help: see for more information about variance diff --git a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr index be39dbf313bf0..329cec6dad3a3 100644 --- a/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr +++ b/tests/ui/async-await/async-closures/without-precise-captures-we-are-powerless.stderr @@ -7,7 +7,7 @@ LL | let c = async || { println!("{}", *x); }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough LL | outlives::<'a>(c()); LL | outlives::<'a>(call_once(c)); - | ------------ argument requires that `x` is borrowed for `'a` + | ---------------------------- argument requires that `x` is borrowed for `'a` ... LL | } | - `x` dropped here while still borrowed @@ -21,10 +21,10 @@ LL | fn simple<'a>(x: &'a i32) { LL | let c = async move || { println!("{}", *x); }; | - binding `c` declared here LL | outlives::<'a>(c()); - | ^-- - | | - | borrowed value does not live long enough - | argument requires that `c` is borrowed for `'a` + | ---------------^--- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` LL | outlives::<'a>(call_once(c)); LL | } | - `c` dropped here while still borrowed @@ -38,7 +38,7 @@ LL | let c = async || { println!("{}", *x.0); }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough LL | outlives::<'a>(c()); LL | outlives::<'a>(call_once(c)); - | ------------ argument requires that `x` is borrowed for `'a` + | ---------------------------- argument requires that `x` is borrowed for `'a` ... LL | } | - `x` dropped here while still borrowed @@ -52,7 +52,7 @@ LL | let c = async || { println!("{}", *x.0); }; | ---------------------------------- borrow of `x` occurs here LL | outlives::<'a>(c()); LL | outlives::<'a>(call_once(c)); - | ------------ argument requires that `x` is borrowed for `'a` + | ---------------------------- argument requires that `x` is borrowed for `'a` LL | LL | let c = async move || { println!("{}", *x.0); }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move out of `x` occurs here @@ -66,10 +66,10 @@ LL | fn through_field<'a>(x: S<'a>) { LL | let c = async move || { println!("{}", *x.0); }; | - binding `c` declared here LL | outlives::<'a>(c()); - | ^-- - | | - | borrowed value does not live long enough - | argument requires that `c` is borrowed for `'a` + | ---------------^--- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` LL | outlives::<'a>(call_once(c)); LL | } | - `c` dropped here while still borrowed @@ -83,10 +83,10 @@ LL | fn through_field<'a>(x: S<'a>) { LL | let c = async move || { println!("{}", *x.0); }; | - binding `c` declared here LL | outlives::<'a>(c()); - | --- - | | - | borrow of `c` occurs here - | argument requires that `c` is borrowed for `'a` + | ------------------- + | | | + | | borrow of `c` occurs here + | argument requires that `c` is borrowed for `'a` LL | outlives::<'a>(call_once(c)); | ^ move out of `c` occurs here @@ -99,18 +99,18 @@ LL | let c = async || { println!("{}", *x.0); }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough LL | outlives::<'a>(c()); LL | outlives::<'a>(call_once(c)); - | ------------ argument requires that `x` is borrowed for `'a` + | ---------------------------- argument requires that `x` is borrowed for `'a` LL | } | - `x` dropped here while still borrowed error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/without-precise-captures-we-are-powerless.rs:38:20 + --> $DIR/without-precise-captures-we-are-powerless.rs:38:5 | LL | fn through_field_and_ref<'a>(x: &S<'a>) { | ------ help: add explicit lifetime `'a` to the type of `x`: `&'a S<'a>` ... LL | outlives::<'a>(call_once(c)); - | ^^^^^^^^^^^^ lifetime `'a` required + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required error[E0597]: `c` does not live long enough --> $DIR/without-precise-captures-we-are-powerless.rs:43:20 @@ -120,22 +120,22 @@ LL | fn through_field_and_ref_move<'a>(x: &S<'a>) { LL | let c = async move || { println!("{}", *x.0); }; | - binding `c` declared here LL | outlives::<'a>(c()); - | ^-- - | | - | borrowed value does not live long enough - | argument requires that `c` is borrowed for `'a` + | ---------------^--- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` LL | outlives::<'a>(call_once(c)); LL | } | - `c` dropped here while still borrowed error[E0621]: explicit lifetime required in the type of `x` - --> $DIR/without-precise-captures-we-are-powerless.rs:44:20 + --> $DIR/without-precise-captures-we-are-powerless.rs:44:5 | LL | fn through_field_and_ref_move<'a>(x: &S<'a>) { | ------ help: add explicit lifetime `'a` to the type of `x`: `&'a S<'a>` ... LL | outlives::<'a>(call_once(c)); - | ^^^^^^^^^^^^ lifetime `'a` required + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required error: aborting due to 10 previous errors diff --git a/tests/ui/async-await/issue-76547.rs b/tests/ui/async-await/issue-76547.rs index 30a39c8943789..24decf9b5f77e 100644 --- a/tests/ui/async-await/issue-76547.rs +++ b/tests/ui/async-await/issue-76547.rs @@ -17,8 +17,8 @@ impl<'a> Future for ListFut<'a> { } async fn fut(bufs: &mut [&mut [u8]]) { - ListFut(bufs).await //~^ ERROR lifetime may not live long enough + ListFut(bufs).await } pub struct ListFut2<'a>(&'a mut [&'a mut [u8]]); @@ -31,8 +31,8 @@ impl<'a> Future for ListFut2<'a> { } async fn fut2(bufs: &mut [&mut [u8]]) -> i32 { - ListFut2(bufs).await //~^ ERROR lifetime may not live long enough + ListFut2(bufs).await } fn main() {} diff --git a/tests/ui/async-await/issue-76547.stderr b/tests/ui/async-await/issue-76547.stderr index 4d96cce824b91..73803a14e7a5e 100644 --- a/tests/ui/async-await/issue-76547.stderr +++ b/tests/ui/async-await/issue-76547.stderr @@ -1,12 +1,11 @@ error: lifetime may not live long enough - --> $DIR/issue-76547.rs:20:13 + --> $DIR/issue-76547.rs:19:14 | LL | async fn fut(bufs: &mut [&mut [u8]]) { - | - - let's call the lifetime of this reference `'2` - | | - | let's call the lifetime of this reference `'1` -LL | ListFut(bufs).await - | ^^^^ this usage requires that `'1` must outlive `'2` + | ^^^^ - - let's call the lifetime of this reference `'2` + | | | + | | let's call the lifetime of this reference `'1` + | assignment requires that `'1` must outlive `'2` | help: consider introducing a named lifetime parameter | @@ -14,14 +13,13 @@ LL | async fn fut<'a>(bufs: &'a mut [&'a mut [u8]]) { | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/issue-76547.rs:34:14 + --> $DIR/issue-76547.rs:33:15 | LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 { - | - - let's call the lifetime of this reference `'2` - | | - | let's call the lifetime of this reference `'1` -LL | ListFut2(bufs).await - | ^^^^ this usage requires that `'1` must outlive `'2` + | ^^^^ - - let's call the lifetime of this reference `'2` + | | | + | | let's call the lifetime of this reference `'1` + | assignment requires that `'1` must outlive `'2` | help: consider introducing a named lifetime parameter | diff --git a/tests/ui/borrowck/fn-item-check-type-params.stderr b/tests/ui/borrowck/fn-item-check-type-params.stderr index 3a29edc55c54f..aafb7e66ef55f 100644 --- a/tests/ui/borrowck/fn-item-check-type-params.stderr +++ b/tests/ui/borrowck/fn-item-check-type-params.stderr @@ -12,12 +12,12 @@ LL | extend_lt(val); | argument requires that `'a` must outlive `'static` error: lifetime may not live long enough - --> $DIR/fn-item-check-type-params.rs:39:12 + --> $DIR/fn-item-check-type-params.rs:39:31 | LL | pub fn test_coercion<'a>() { | -- lifetime `'a` defined here LL | let _: fn(&'a str) -> _ = extend_lt; - | ^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | ^^^^^^^^^ coercion requires that `'a` must outlive `'static` error[E0716]: temporary value dropped while borrowed --> $DIR/fn-item-check-type-params.rs:48:11 diff --git a/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr b/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr index 13c768dcbf636..4ec4d2138db60 100644 --- a/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr +++ b/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr @@ -15,10 +15,10 @@ LL | async { LL | let not_static = 0; | ---------- binding `not_static` declared here LL | force_send(async_load(¬_static)); - | -----------^^^^^^^^^^^- - | | | - | | borrowed value does not live long enough - | argument requires that `not_static` is borrowed for `'1` + | ----------------------^^^^^^^^^^^-- + | | | + | | borrowed value does not live long enough + | argument requires that `not_static` is borrowed for `'1` ... LL | } | - `not_static` dropped here while still borrowed diff --git a/tests/ui/borrowck/issue-7573.rs b/tests/ui/borrowck/issue-7573.rs index 7c07411533ff0..f94cd75ab6e2e 100644 --- a/tests/ui/borrowck/issue-7573.rs +++ b/tests/ui/borrowck/issue-7573.rs @@ -17,6 +17,8 @@ pub fn remove_package_from_database() { lines_to_use.push(installed_id); //~^ ERROR borrowed data escapes outside of closure //~| NOTE `installed_id` escapes the closure body here + //~| NOTE requirement occurs because of a mutable reference to `Vec<&CrateId>` + //~| NOTE mutable references are invariant over their type parameter }; list_database(push_id); diff --git a/tests/ui/borrowck/issue-7573.stderr b/tests/ui/borrowck/issue-7573.stderr index 07a67474c8310..d0121f4ec174f 100644 --- a/tests/ui/borrowck/issue-7573.stderr +++ b/tests/ui/borrowck/issue-7573.stderr @@ -9,6 +9,10 @@ LL | let push_id = |installed_id: &CrateId| { LL | LL | lines_to_use.push(installed_id); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `installed_id` escapes the closure body here + | + = note: requirement occurs because of a mutable reference to `Vec<&CrateId>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr b/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr index 89b15a7a659dd..4d1d7ffd29353 100644 --- a/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr +++ b/tests/ui/borrowck/two-phase-surprise-no-conflict.stderr @@ -71,14 +71,13 @@ error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as imm LL | fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) { | -- lifetime `'a` defined here ... +LL | let reg = mk_reg(); + | -------- assignment requires that `reg.sess_mut` is borrowed for `'a` LL | reg.register_univ(Box::new(CapturePass::new(®.sess_mut))); - | ^^^^^^^^^^^^^^^^^^-----------------------------------------^ - | | | | - | | | immutable borrow occurs here - | | coercion requires that `reg.sess_mut` is borrowed for `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^ + | | | + | | immutable borrow occurs here | mutable borrow occurs here - | - = note: due to object lifetime defaults, `Box LateLintPass<'b>>` actually means `Box<(dyn for<'b> LateLintPass<'b> + 'static)>` error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable --> $DIR/two-phase-surprise-no-conflict.rs:144:5 @@ -115,14 +114,13 @@ error[E0499]: cannot borrow `*reg` as mutable more than once at a time LL | fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) { | -- lifetime `'a` defined here ... +LL | let reg = mk_reg(); + | -------- assignment requires that `reg.sess_mut` is borrowed for `'a` LL | reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut))); - | ^^^^^^^^^^^^^^^^^^-------------------------------------------------^ - | | | | - | | | first mutable borrow occurs here - | | coercion requires that `reg.sess_mut` is borrowed for `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^ + | | | + | | first mutable borrow occurs here | second mutable borrow occurs here - | - = note: due to object lifetime defaults, `Box LateLintPass<'b>>` actually means `Box<(dyn for<'b> LateLintPass<'b> + 'static)>` error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time --> $DIR/two-phase-surprise-no-conflict.rs:158:53 diff --git a/tests/ui/c-variadic/variadic-ffi-4.stderr b/tests/ui/c-variadic/variadic-ffi-4.stderr index c9d90d73dea31..fc9f8036083a6 100644 --- a/tests/ui/c-variadic/variadic-ffi-4.stderr +++ b/tests/ui/c-variadic/variadic-ffi-4.stderr @@ -120,14 +120,14 @@ LL | } | - `ap1` dropped here while still borrowed error: lifetime may not live long enough - --> $DIR/variadic-ffi-4.rs:35:12 + --> $DIR/variadic-ffi-4.rs:35:5 | LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) { | ------- ------- has type `VaListImpl<'2>` | | | has type `&mut VaListImpl<'1>` LL | *ap0 = ap1.clone(); - | ^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + | ^^^^ assignment requires that `'2` must outlive `'1` | = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` @@ -141,7 +141,7 @@ LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut | | | has type `&mut VaListImpl<'1>` LL | *ap0 = ap1.clone(); - | ^^^^^^^^^^^ argument requires that `'2` must outlive `'1` + | ^^^^^^^^^^^ argument requires that `'1` must outlive `'2` | = note: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr index b7319e3356bd0..ed9ebce4832c2 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr @@ -4,7 +4,7 @@ error: lifetime may not live long enough LL | fn bad_cast<'a>(x: *const dyn Static<'static>) -> *const dyn Static<'a> { | -- lifetime `'a` defined here LL | x as _ - | ^^^^^^ returning this value requires that `'a` must outlive `'static` + | ^^^^^^ cast requires that `'a` must outlive `'static` error: aborting due to 1 previous error diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs index 18566acc07fe4..f8910c944c61e 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.rs @@ -42,7 +42,7 @@ fn change_assoc_1<'a, 'b>( // This tests the default borrow check error, without the special casing for return values. fn require_static(_: *const dyn Trait<'static>) {} fn extend_to_static<'a>(ptr: *const dyn Trait<'a>) { - require_static(ptr as _) //~ error: lifetime may not live long enough + require_static(ptr as _) //~ error: borrowed data escapes outside of function } fn main() {} diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr index 6f590585c4a46..6eeaeb120a729 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr @@ -6,12 +6,9 @@ LL | fn change_lt<'a, 'b>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> { | | | lifetime `'a` defined here LL | x as _ - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | ^^^^^^ cast requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of a mutable pointer to `dyn Trait<'_>` - = note: mutable pointers are invariant over their type parameter - = help: see for more information about variance error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:6:5 @@ -38,12 +35,9 @@ LL | fn change_lt_ab<'a: 'b, 'b>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> { | | | lifetime `'a` defined here LL | x as _ - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | ^^^^^^ cast requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of a mutable pointer to `dyn Trait<'_>` - = note: mutable pointers are invariant over their type parameter - = help: see for more information about variance error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:15:5 @@ -91,12 +85,9 @@ LL | fn change_assoc_0<'a, 'b>( | lifetime `'a` defined here ... LL | x as _ - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | ^^^^^^ cast requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of a mutable pointer to `dyn Assocked` - = note: mutable pointers are invariant over their type parameter - = help: see for more information about variance error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:31:5 @@ -127,12 +118,9 @@ LL | fn change_assoc_1<'a, 'b>( | lifetime `'a` defined here ... LL | x as _ - | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` + | ^^^^^^ cast requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of a mutable pointer to `dyn Assocked>` - = note: mutable pointers are invariant over their type parameter - = help: see for more information about variance error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:38:5 @@ -154,14 +142,22 @@ help: `'b` and `'a` must be the same: replace one with the other | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error: lifetime may not live long enough - --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:45:20 +error[E0521]: borrowed data escapes outside of function + --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:45:5 | LL | fn extend_to_static<'a>(ptr: *const dyn Trait<'a>) { - | -- lifetime `'a` defined here + | -- --- + | | | + | | `ptr` declared here, outside of the function body + | | `ptr` is a reference that is only valid in the function body + | lifetime `'a` defined here LL | require_static(ptr as _) - | ^^^^^^^^ cast requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `ptr` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to 11 previous errors -For more information about this error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0308, E0521. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/coroutine/resume-arg-outlives-2.rs b/tests/ui/coroutine/resume-arg-outlives-2.rs index 387b143ea279e..a805cea9b7ea4 100644 --- a/tests/ui/coroutine/resume-arg-outlives-2.rs +++ b/tests/ui/coroutine/resume-arg-outlives-2.rs @@ -18,8 +18,8 @@ fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> { // exploit: generator.as_mut().resume(""); generator.as_mut().resume(s); // <- generator hoards it as `let ctx`. - //~^ ERROR borrowed data escapes outside of function thread::spawn(move || { + //~^ ERROR borrowed data escapes outside of function thread::sleep(time::Duration::from_millis(200)); generator.as_mut().resume(""); // <- resumes from the last `yield`, running `dbg!(ctx)`. }) diff --git a/tests/ui/coroutine/resume-arg-outlives-2.stderr b/tests/ui/coroutine/resume-arg-outlives-2.stderr index 3d630d7e7e483..92192d9a55721 100644 --- a/tests/ui/coroutine/resume-arg-outlives-2.stderr +++ b/tests/ui/coroutine/resume-arg-outlives-2.stderr @@ -1,16 +1,20 @@ error[E0521]: borrowed data escapes outside of function - --> $DIR/resume-arg-outlives-2.rs:20:5 + --> $DIR/resume-arg-outlives-2.rs:21:5 | -LL | fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> { - | ----------- - `s` is a reference that is only valid in the function body - | | - | lifetime `'not_static` defined here +LL | fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> { + | ----------- - `s` is a reference that is only valid in the function body + | | + | lifetime `'not_static` defined here ... -LL | generator.as_mut().resume(s); // <- generator hoards it as `let ctx`. - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | | - | `s` escapes the function body here - | argument requires that `'not_static` must outlive `'static` +LL | / thread::spawn(move || { +LL | | +LL | | thread::sleep(time::Duration::from_millis(200)); +LL | | generator.as_mut().resume(""); // <- resumes from the last `yield`, running `dbg!(ctx)`. +LL | | }) + | | ^ + | | | + | |______`s` escapes the function body here + | argument requires that `'not_static` must outlive `'static` error: aborting due to 1 previous error diff --git a/tests/ui/dropck/dropck_trait_cycle_checked.stderr b/tests/ui/dropck/dropck_trait_cycle_checked.stderr index f32736f1a674c..e595e98fa2e43 100644 --- a/tests/ui/dropck/dropck_trait_cycle_checked.stderr +++ b/tests/ui/dropck/dropck_trait_cycle_checked.stderr @@ -2,83 +2,87 @@ error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:111:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -- binding `o2` declared here -------- coercion requires that `o2` is borrowed for `'static` + | -- binding `o2` declared here LL | o1.set0(&o2); | ^^^ borrowed value does not live long enough ... +LL | o3.set0(&o1); + | ------------ argument requires that `o2` is borrowed for `'static` +LL | o3.set1(&o2); LL | } | - `o2` dropped here while still borrowed - | - = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o3` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:112:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -- binding `o3` declared here -------- coercion requires that `o3` is borrowed for `'static` + | -- binding `o3` declared here LL | o1.set0(&o2); LL | o1.set1(&o3); | ^^^ borrowed value does not live long enough ... +LL | o3.set0(&o1); + | ------------ argument requires that `o3` is borrowed for `'static` +LL | o3.set1(&o2); LL | } | - `o3` dropped here while still borrowed - | - = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:113:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -- binding `o2` declared here -------- coercion requires that `o2` is borrowed for `'static` -... + | -- binding `o2` declared here +LL | o1.set0(&o2); + | ------------ argument requires that `o2` is borrowed for `'static` +LL | o1.set1(&o3); LL | o2.set0(&o2); | ^^^ borrowed value does not live long enough ... LL | } | - `o2` dropped here while still borrowed - | - = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o3` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:114:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -- binding `o3` declared here -------- coercion requires that `o3` is borrowed for `'static` + | -- binding `o3` declared here +LL | o1.set0(&o2); + | ------------ argument requires that `o3` is borrowed for `'static` ... LL | o2.set1(&o3); | ^^^ borrowed value does not live long enough ... LL | } | - `o3` dropped here while still borrowed - | - = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o1` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:115:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -- binding `o1` declared here -------- coercion requires that `o1` is borrowed for `'static` + | -- binding `o1` declared here +LL | o1.set0(&o2); +LL | o1.set1(&o3); + | ------------ argument requires that `o1` is borrowed for `'static` ... LL | o3.set0(&o1); | ^^^ borrowed value does not live long enough LL | o3.set1(&o2); LL | } | - `o1` dropped here while still borrowed - | - = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:116:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -- binding `o2` declared here -------- coercion requires that `o2` is borrowed for `'static` + | -- binding `o2` declared here +LL | o1.set0(&o2); +LL | o1.set1(&o3); + | ------------ argument requires that `o2` is borrowed for `'static` ... LL | o3.set1(&o2); | ^^^ borrowed value does not live long enough LL | } | - `o2` dropped here while still borrowed - | - = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error: aborting due to 6 previous errors diff --git a/tests/ui/fn/fn_def_coercion.rs b/tests/ui/fn/fn_def_coercion.rs index 313be6f28cdcc..31c8fa41de17c 100644 --- a/tests/ui/fn/fn_def_coercion.rs +++ b/tests/ui/fn/fn_def_coercion.rs @@ -46,12 +46,12 @@ fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { let x = match true { - true => foo::<&'c ()>, + true => foo::<&'c ()>, //~ ERROR lifetime may not live long enough false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough }; x(a); - x(b); //~ ERROR lifetime may not live long enough + x(b); x(c); } diff --git a/tests/ui/fn/fn_def_coercion.stderr b/tests/ui/fn/fn_def_coercion.stderr index ec4a1bde7fd61..c2776887b79d4 100644 --- a/tests/ui/fn/fn_def_coercion.stderr +++ b/tests/ui/fn/fn_def_coercion.stderr @@ -6,9 +6,9 @@ LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | | | lifetime `'a` defined here LL | let mut x = foo::<&'a ()>; - | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -22,9 +22,9 @@ LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here LL | let mut x = foo::<&'a ()>; LL | x = foo::<&'b ()>; - | ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -53,9 +53,9 @@ LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here LL | let mut x = foo::<&'c ()>; LL | x = foo::<&'b ()>; - | ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -69,9 +69,9 @@ LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here ... LL | x = foo::<&'a ()>; - | ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -89,9 +89,9 @@ LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here LL | let x = match true { LL | true => foo::<&'b ()>, - | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -105,9 +105,9 @@ LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here ... LL | false => foo::<&'a ()>, - | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -117,15 +117,15 @@ help: `'a` and `'b` must be the same: replace one with the other = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: lifetime may not live long enough - --> $DIR/fn_def_coercion.rs:50:18 + --> $DIR/fn_def_coercion.rs:49:17 | LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | -- -- lifetime `'c` defined here | | | lifetime `'a` defined here -... -LL | false => foo::<&'a ()>, - | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c` +LL | let x = match true { +LL | true => foo::<&'c ()>, + | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c` | = help: consider adding the following bound: `'a: 'c` = note: requirement occurs because of a function pointer to `foo` @@ -133,17 +133,20 @@ LL | false => foo::<&'a ()>, = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/fn_def_coercion.rs:54:5 + --> $DIR/fn_def_coercion.rs:50:18 | LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here ... -LL | x(b); - | ^^^^ argument requires that `'b` must outlive `'a` +LL | false => foo::<&'a ()>, + | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a function pointer to `foo` + = note: the function `foo` is invariant over the parameter `T` + = help: see for more information about variance help: the following changes may resolve your lifetime errors | diff --git a/tests/ui/impl-trait/precise-capturing/migration-note.rs b/tests/ui/impl-trait/precise-capturing/migration-note.rs index 36db07e5764f5..7587e89409aaa 100644 --- a/tests/ui/impl-trait/precise-capturing/migration-note.rs +++ b/tests/ui/impl-trait/precise-capturing/migration-note.rs @@ -29,11 +29,11 @@ fn needs_static() { let a = display_len(&x); //~^ ERROR `x` does not live long enough //~| NOTE this call may capture more lifetimes than intended - //~| NOTE argument requires that `x` is borrowed for `'static` //~| NOTE borrowed value does not live long enoug fn needs_static(_: impl Sized + 'static) {} needs_static(a); + //~^ NOTE argument requires that `x` is borrowed for `'static` } //~^ NOTE `x` dropped here while still borrowed @@ -76,11 +76,11 @@ fn needs_static_mut() { let a = display_len_mut(&mut x); //~^ ERROR `x` does not live long enough //~| NOTE this call may capture more lifetimes than intended - //~| NOTE argument requires that `x` is borrowed for `'static` //~| NOTE borrowed value does not live long enough fn needs_static(_: impl Sized + 'static) {} needs_static(a); + //~^ NOTE argument requires that `x` is borrowed for `'static` } //~^ NOTE `x` dropped here while still borrowed diff --git a/tests/ui/impl-trait/precise-capturing/migration-note.stderr b/tests/ui/impl-trait/precise-capturing/migration-note.stderr index c9403532dfa35..9caf7a201ef8a 100644 --- a/tests/ui/impl-trait/precise-capturing/migration-note.stderr +++ b/tests/ui/impl-trait/precise-capturing/migration-note.stderr @@ -42,11 +42,11 @@ LL | let x = vec![1]; | - binding `x` declared here LL | LL | let a = display_len(&x); - | ------------^^- - | | | - | | borrowed value does not live long enough - | argument requires that `x` is borrowed for `'static` + | ^^ borrowed value does not live long enough ... +LL | needs_static(a); + | --------------- argument requires that `x` is borrowed for `'static` +LL | LL | } | - `x` dropped here while still borrowed | @@ -118,11 +118,11 @@ LL | let mut x = vec![1]; | ----- binding `x` declared here LL | LL | let a = display_len_mut(&mut x); - | ----------------^^^^^^- - | | | - | | borrowed value does not live long enough - | argument requires that `x` is borrowed for `'static` + | ^^^^^^ borrowed value does not live long enough ... +LL | needs_static(a); + | --------------- argument requires that `x` is borrowed for `'static` +LL | LL | } | - `x` dropped here while still borrowed | diff --git a/tests/ui/inline-const/const-expr-lifetime-err.stderr b/tests/ui/inline-const/const-expr-lifetime-err.stderr index be3fc8d28c51e..031bf98262a87 100644 --- a/tests/ui/inline-const/const-expr-lifetime-err.stderr +++ b/tests/ui/inline-const/const-expr-lifetime-err.stderr @@ -6,10 +6,9 @@ LL | fn foo<'a>() { LL | let y = (); | - binding `y` declared here LL | equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW }); - | ------------------^^- - | | | - | | borrowed value does not live long enough - | argument requires that `y` is borrowed for `'a` + | ^^ ----------------------- using this value as a constant requires that `y` is borrowed for `'a` + | | + | borrowed value does not live long enough LL | LL | } | - `y` dropped here while still borrowed diff --git a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr index 95fe7085e5027..7eea1846057af 100644 --- a/tests/ui/inline-const/const-match-pat-lifetime-err.stderr +++ b/tests/ui/inline-const/const-match-pat-lifetime-err.stderr @@ -9,7 +9,7 @@ LL | match InvariantRef::new(&y) { | ^^ borrowed value does not live long enough LL | LL | const { InvariantRef::<'a>::NEW } => (), - | --------------------------------- type annotation requires that `y` is borrowed for `'a` + | ----------------------- using this value as a constant requires that `y` is borrowed for `'a` LL | } LL | } | - `y` dropped here while still borrowed diff --git a/tests/ui/issues/issue-15034.stderr b/tests/ui/issues/issue-15034.stderr index 587a5c85e924a..c5bc31f94d981 100644 --- a/tests/ui/issues/issue-15034.stderr +++ b/tests/ui/issues/issue-15034.stderr @@ -1,10 +1,10 @@ error[E0621]: explicit lifetime required in the type of `lexer` - --> $DIR/issue-15034.rs:17:9 + --> $DIR/issue-15034.rs:17:25 | LL | pub fn new(lexer: &'a mut Lexer) -> Parser<'a> { | ------------- help: add explicit lifetime `'a` to the type of `lexer`: `&'a mut Lexer<'a>` LL | Parser { lexer: lexer } - | ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required + | ^^^^^ lifetime `'a` required error: aborting due to 1 previous error diff --git a/tests/ui/kindck/kindck-impl-type-params.stderr b/tests/ui/kindck/kindck-impl-type-params.stderr index a0a4ef09216f6..d375aa9cb5961 100644 --- a/tests/ui/kindck/kindck-impl-type-params.stderr +++ b/tests/ui/kindck/kindck-impl-type-params.stderr @@ -112,13 +112,13 @@ LL | struct Foo; // does not impl Copy | error: lifetime may not live long enough - --> $DIR/kindck-impl-type-params.rs:30:19 + --> $DIR/kindck-impl-type-params.rs:30:13 | LL | fn foo<'a>() { | -- lifetime `'a` defined here LL | let t: S<&'a isize> = S(marker::PhantomData); LL | let a = &t as &dyn Gettable<&'a isize>; - | ^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'a` must outlive `'static` error: aborting due to 7 previous errors diff --git a/tests/ui/lifetimes/copy_modulo_regions.stderr b/tests/ui/lifetimes/copy_modulo_regions.stderr index 310ddb21647f6..920fec09103b2 100644 --- a/tests/ui/lifetimes/copy_modulo_regions.stderr +++ b/tests/ui/lifetimes/copy_modulo_regions.stderr @@ -4,11 +4,7 @@ error: lifetime may not live long enough LL | fn foo<'a>() -> [Foo<'a>; 100] { | -- lifetime `'a` defined here LL | [mk_foo::<'a>(); 100] - | ^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` - | - = note: requirement occurs because of the type `Foo<'_>`, which makes the generic argument `'_` invariant - = note: the struct `Foo<'a>` is invariant over the parameter `'a` - = help: see for more information about variance + | ^^^^^^^^^^^^^^^^^^^^^ copying this value requires that `'a` must outlive `'static` error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/issue-90170-elision-mismatch.stderr b/tests/ui/lifetimes/issue-90170-elision-mismatch.stderr index 82511d07b0efc..5e16c57a618ff 100644 --- a/tests/ui/lifetimes/issue-90170-elision-mismatch.stderr +++ b/tests/ui/lifetimes/issue-90170-elision-mismatch.stderr @@ -7,6 +7,9 @@ LL | pub fn foo(x: &mut Vec<&u8>, y: &u8) { x.push(y); } | | let's call the lifetime of this reference `'1` | let's call the lifetime of this reference `'2` | + = note: requirement occurs because of a mutable reference to `Vec<&u8>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance help: consider introducing a named lifetime parameter | LL | pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } @@ -21,6 +24,9 @@ LL | pub fn foo2(x: &mut Vec<&'_ u8>, y: &u8) { x.push(y); } | | let's call the lifetime of this reference `'1` | let's call the lifetime of this reference `'2` | + = note: requirement occurs because of a mutable reference to `Vec<&u8>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance help: consider introducing a named lifetime parameter | LL | pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } @@ -35,6 +41,9 @@ LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&u8>, y: &u8) { x.push(y); } | | let's call the lifetime of this reference `'1` | let's call the lifetime of this reference `'2` | + = note: requirement occurs because of a mutable reference to `Vec<&u8>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance help: consider reusing a named lifetime parameter | LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } diff --git a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.rs b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.rs index ce4cddc9b39b3..30a1811fee547 100644 --- a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.rs +++ b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.rs @@ -7,9 +7,9 @@ fn inner(mut foo: &[u8]) { let refcell = RefCell::new(&mut foo); //~^ ERROR `foo` does not live long enough let read = &refcell as &RefCell; - //~^ ERROR lifetime may not live long enough read_thing(read); + //~^ ERROR borrowed data escapes outside of function } fn read_thing(refcell: &RefCell) {} diff --git a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr index e4cd54ac33741..4df2e906e222f 100644 --- a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr +++ b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr @@ -5,22 +5,32 @@ LL | fn inner(mut foo: &[u8]) { | ------- binding `foo` declared here LL | let refcell = RefCell::new(&mut foo); | ^^^^^^^^ borrowed value does not live long enough -LL | -LL | let read = &refcell as &RefCell; - | ------------------------------ cast requires that `foo` is borrowed for `'static` ... +LL | read_thing(read); + | ---------------- argument requires that `foo` is borrowed for `'static` +LL | LL | } | - `foo` dropped here while still borrowed -error: lifetime may not live long enough - --> $DIR/issue-90600-expected-return-static-indirect.rs:9:16 +error[E0521]: borrowed data escapes outside of function + --> $DIR/issue-90600-expected-return-static-indirect.rs:11:5 | LL | fn inner(mut foo: &[u8]) { - | - let's call the lifetime of this reference `'1` + | ------- - let's call the lifetime of this reference `'1` + | | + | `foo` is a reference that is only valid in the function body ... -LL | let read = &refcell as &RefCell; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static` +LL | read_thing(read); + | ^^^^^^^^^^^^^^^^ + | | + | `foo` escapes the function body here + | argument requires that `'1` must outlive `'static` + | + = note: requirement occurs because of the type `RefCell<(dyn std::io::Read + 'static)>`, which makes the generic argument `(dyn std::io::Read + 'static)` invariant + = note: the struct `RefCell` is invariant over the parameter `T` + = help: see for more information about variance error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0597`. +Some errors have detailed explanations: E0521, E0597. +For more information about an error, try `rustc --explain E0521`. diff --git a/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr b/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr index 6f7127d4c4c4e..a187cb755dd56 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2b-push-no-existing-names.stderr @@ -8,6 +8,9 @@ LL | fn foo(x: &mut Vec>, y: Ref) { LL | x.push(y); | ^^^^^^^^^ argument requires that `'1` must outlive `'2` | + = note: requirement occurs because of a mutable reference to `Vec>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x: &mut Vec>, y: Ref<'a, i32>) { diff --git a/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr b/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr index cace80272f5b5..610a669cdedd3 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2c-push-inference-variable.stderr @@ -10,6 +10,9 @@ LL | x.push(z); | ^^^^^^^^^ argument requires that `'c` must outlive `'b` | = help: consider adding the following bound: `'c: 'b` + = note: requirement occurs because of a mutable reference to `Vec>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs b/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs index f573230293eef..4cd06e1c02b2a 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs +++ b/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.rs @@ -4,9 +4,9 @@ struct Ref<'a, T: 'a> { fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { let a: &mut Vec> = x; + //~^ ERROR lifetime may not live long enough let b = Ref { data: y.data }; a.push(b); - //~^ ERROR lifetime may not live long enough } fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr index 4a981e4de604d..0da32aacdb3d4 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2d-push-inference-variable-2.stderr @@ -1,15 +1,17 @@ error: lifetime may not live long enough - --> $DIR/ex2d-push-inference-variable-2.rs:8:5 + --> $DIR/ex2d-push-inference-variable-2.rs:6:33 | LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { | -- -- lifetime `'c` defined here | | | lifetime `'b` defined here -... -LL | a.push(b); - | ^^^^^^^^^ argument requires that `'c` must outlive `'b` +LL | let a: &mut Vec> = x; + | ^ assignment requires that `'c` must outlive `'b` | = help: consider adding the following bound: `'c: 'b` + = note: requirement occurs because of a mutable reference to `Vec>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs b/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs index 4a934bbf080d5..498cea3682473 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs +++ b/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.rs @@ -4,9 +4,9 @@ struct Ref<'a, T: 'a> { fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { let a: &mut Vec> = x; + //~^ ERROR lifetime may not live long enough let b = Ref { data: y.data }; Vec::push(a, b); - //~^ ERROR lifetime may not live long enough } fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr index 2bd047113bca0..4474a898fdc65 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex2e-push-inference-variable-3.stderr @@ -1,15 +1,17 @@ error: lifetime may not live long enough - --> $DIR/ex2e-push-inference-variable-3.rs:8:5 + --> $DIR/ex2e-push-inference-variable-3.rs:6:33 | LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec>, y: Ref<'c, i32>) { | -- -- lifetime `'c` defined here | | | lifetime `'b` defined here -... -LL | Vec::push(a, b); - | ^^^^^^^^^^^^^^^ argument requires that `'c` must outlive `'b` +LL | let a: &mut Vec> = x; + | ^ assignment requires that `'c` must outlive `'b` | = help: consider adding the following bound: `'c: 'b` + = note: requirement occurs because of a mutable reference to `Vec>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs index 09ee9accccd2f..66e6eb91a22e3 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs @@ -1,6 +1,6 @@ fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) { - *v = x; //~^ ERROR lifetime may not live long enough + *v = x; } fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr index 30083b5ef5462..e7cab52084ddd 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr @@ -1,13 +1,15 @@ error: lifetime may not live long enough - --> $DIR/ex3-both-anon-regions-2.rs:2:5 + --> $DIR/ex3-both-anon-regions-2.rs:1:14 | LL | fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) { - | - - let's call the lifetime of this reference `'1` - | | - | let's call the lifetime of this reference `'2` -LL | *v = x; - | ^^^^^^ assignment requires that `'1` must outlive `'2` + | ^^^^^^^^^ - - let's call the lifetime of this reference `'1` + | | | + | | let's call the lifetime of this reference `'2` + | assignment requires that `'1` must outlive `'2` | + = note: requirement occurs because of a mutable reference to `&u8` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance help: consider introducing a named lifetime parameter | LL | fn foo<'a>(&mut (ref mut v, w): &mut (&'a u8, &u8), x: &'a u8) { diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr index 6ba130308a33a..c67ea19effc07 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-3.stderr @@ -8,6 +8,9 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { LL | z.push((x,y)); | ^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` | + = note: requirement occurs because of a mutable reference to `Vec<(&u8, &u8)>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance help: consider introducing a named lifetime parameter | LL | fn foo<'a>(z: &mut Vec<(&'a u8,&u8)>, (x, y): (&'a u8, &u8)) { @@ -23,6 +26,9 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) { LL | z.push((x,y)); | ^^^^^^^^^^^^^ argument requires that `'3` must outlive `'4` | + = note: requirement occurs because of a mutable reference to `Vec<(&u8, &u8)>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance help: consider introducing a named lifetime parameter | LL | fn foo<'a>(z: &mut Vec<(&u8,&'a u8)>, (x, y): (&u8, &'a u8)) { diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr index 352619c0ffc3f..0980b37e535a1 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-earlybound-regions.stderr @@ -10,6 +10,9 @@ LL | x.push(y); | ^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `Vec>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr index 16cf009ee48bc..16cd47420a58e 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs-latebound-regions.stderr @@ -9,6 +9,9 @@ LL | x.push(y); | ^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `Vec>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr index 017bfa7146317..264673ff3e82c 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-both-are-structs.stderr @@ -8,6 +8,9 @@ LL | fn foo(mut x: Vec, y: Ref) { LL | x.push(y); | ^^^^^^^^^ argument requires that `'1` must outlive `'2` | + = note: requirement occurs because of a mutable reference to `Vec>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance help: consider introducing a named lifetime parameter | LL | fn foo<'a>(mut x: Vec>, y: Ref<'a>) { diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr index 080eb43cecbc4..8552755d16852 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-latebound-regions.stderr @@ -9,6 +9,9 @@ LL | x.push(y); | ^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable reference to `Vec<&u8>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr index cb629d2e3d3fc..2a2cf6508fdb7 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-fn-items.stderr @@ -19,6 +19,9 @@ LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) { LL | y.push(z); | ^^^^^^^^^ argument requires that `'1` must outlive `'2` | + = note: requirement occurs because of a mutable reference to `Vec<&u8>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) { diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr index 420cfa6b569b6..01bfe7829206d 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-impl-items.stderr @@ -8,6 +8,9 @@ LL | fn foo(x: &mut Vec<&u8>, y: &u8) { LL | x.push(y); | ^^^^^^^^^ argument requires that `'1` must outlive `'2` | + = note: requirement occurs because of a mutable reference to `Vec<&u8>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance help: consider introducing a named lifetime parameter and update trait if needed | LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr index 05f9308124b1e..41154755b5d88 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-using-trait-objects.stderr @@ -19,6 +19,9 @@ LL | fn foo(x:Box , y: Vec<&u8>, z: &u8) { LL | y.push(z); | ^^^^^^^^^ argument requires that `'1` must outlive `'2` | + = note: requirement occurs because of a mutable reference to `Vec<&u8>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x:Box , y: Vec<&'a u8>, z: &'a u8) { diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr index 875d22576e58c..10e8ca852f0f7 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions.stderr @@ -8,6 +8,9 @@ LL | fn foo(x: &mut Vec<&u8>, y: &u8) { LL | x.push(y); | ^^^^^^^^^ argument requires that `'1` must outlive `'2` | + = note: requirement occurs because of a mutable reference to `Vec<&u8>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { diff --git a/tests/ui/match/match-ref-mut-invariance.stderr b/tests/ui/match/match-ref-mut-invariance.stderr index b9878a1953242..93844d34b414b 100644 --- a/tests/ui/match/match-ref-mut-invariance.stderr +++ b/tests/ui/match/match-ref-mut-invariance.stderr @@ -1,12 +1,12 @@ error: lifetime may not live long enough - --> $DIR/match-ref-mut-invariance.rs:10:9 + --> $DIR/match-ref-mut-invariance.rs:10:24 | LL | impl<'b> S<'b> { | -- lifetime `'b` defined here LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { | -- lifetime `'a` defined here LL | match self.0 { ref mut x => x } - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | ^^^^^^^^^ assignment requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a mutable reference to `&i32` diff --git a/tests/ui/match/match-ref-mut-let-invariance.rs b/tests/ui/match/match-ref-mut-let-invariance.rs index a33be09ac8be2..2c1f865b6d750 100644 --- a/tests/ui/match/match-ref-mut-let-invariance.rs +++ b/tests/ui/match/match-ref-mut-let-invariance.rs @@ -8,8 +8,8 @@ struct S<'b>(&'b i32); impl<'b> S<'b> { fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { let ref mut x = self.0; - x //~^ ERROR lifetime may not live long enough + x } } diff --git a/tests/ui/match/match-ref-mut-let-invariance.stderr b/tests/ui/match/match-ref-mut-let-invariance.stderr index 27968239a8e54..3c5d73bb4f724 100644 --- a/tests/ui/match/match-ref-mut-let-invariance.stderr +++ b/tests/ui/match/match-ref-mut-let-invariance.stderr @@ -1,13 +1,12 @@ error: lifetime may not live long enough - --> $DIR/match-ref-mut-let-invariance.rs:11:9 + --> $DIR/match-ref-mut-let-invariance.rs:10:13 | LL | impl<'b> S<'b> { | -- lifetime `'b` defined here LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { | -- lifetime `'a` defined here LL | let ref mut x = self.0; -LL | x - | ^ method was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` + | ^^^^^^^^^ assignment requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a mutable reference to `&i32` diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr index f37ce967a1ba3..60087ec992bd6 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-fail-no-postdom.stderr @@ -23,6 +23,10 @@ LL | |_outlives1, _outlives2, _outlives3, x, y| { ... LL | demand_y(x, y, p) | ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + | + = note: requirement occurs because of the type `Cell<&'?34 u32>`, which makes the generic argument `&'?34 u32` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance note: no external requirements --> $DIR/propagate-approximated-fail-no-postdom.rs:38:1 diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.rs b/tests/ui/nll/closure-requirements/propagate-approximated-ref.rs index 1c27e38f83214..f4db723704cb8 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-ref.rs +++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.rs @@ -41,9 +41,10 @@ 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 lifetime may not live long enough + // Only works if 'x: 'y: demand_y(x, y, x.get()) - //~^ ERROR lifetime may not live long enough }); } diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr index e2d0b105ab14d..7325a9de8b294 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-ref.stderr @@ -23,17 +23,21 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { = note: defining type: supply error: lifetime may not live long enough - --> $DIR/propagate-approximated-ref.rs:45:9 + --> $DIR/propagate-approximated-ref.rs:43:5 | -LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -... -LL | demand_y(x, y, x.get()) - | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b` +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { +... | +LL | | }); + | |______^ argument requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of the type `Cell<&'?11 u32>`, which makes the generic argument `&'?11 u32` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance error: aborting due to 1 previous error diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index d7933a39eaacf..0094d7a50d369 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -19,6 +19,10 @@ LL | foo(cell, |cell_a, cell_x| { | `cell_a` declared here, outside of the closure body LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure | ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here + | + = note: requirement occurs because of the type `Cell<&'?8 u32>`, which makes the generic argument `&'?8 u32` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance note: no external requirements --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:18:1 @@ -56,11 +60,11 @@ error[E0597]: `a` does not live long enough LL | let a = 0; | - binding `a` declared here LL | let cell = Cell::new(&a); - | ----------^^- - | | | - | | borrowed value does not live long enough - | argument requires that `a` is borrowed for `'static` + | ^^ borrowed value does not live long enough ... +LL | cell_x.set(cell_a.get()); // forces 'a: 'x, implies 'a = 'static -> borrow error + | ------------------------ argument requires that `a` is borrowed for `'static` +LL | }) LL | } | - `a` dropped here while still borrowed diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs index 25e212a722568..afabb69ec4cd0 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.rs @@ -30,10 +30,9 @@ 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 borrowed data escapes outside of function - // Only works if 'x: 'y: demand_y(x, y, x.get()) + //~^ ERROR borrowed data escapes outside of function }); } diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index 3c04cf300ad43..b9365c94a1bed 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -23,23 +23,18 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { = note: defining type: supply error[E0521]: borrowed data escapes outside of function - --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:32:5 + --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:34:9 | -LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | -- ------ `cell_a` is a reference that is only valid in the function body - | | - | lifetime `'a` defined here -LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { -... | -LL | | }); - | | ^ - | | | - | |______`cell_a` escapes the function body here - | argument requires that `'a` must outlive `'static` - | - = note: requirement occurs because of the type `Cell<&'?9 u32>`, which makes the generic argument `&'?9 u32` invariant - = note: the struct `Cell` is invariant over the parameter `T` - = help: see for more information about variance +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | -- ------ `cell_a` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +... +LL | demand_y(x, y, x.get()) + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `cell_a` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to 1 previous error diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs index cda7b22362f3e..9f3e80d3db669 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.rs @@ -33,10 +33,9 @@ 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 borrowed data escapes outside of function - // Only works if 'x: 'y: demand_y(x, y, x.get()) + //~^ ERROR borrowed data escapes outside of function }); } diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 9f5762ccbfa68..e5d2867103cfc 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -23,23 +23,18 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { = note: defining type: supply error[E0521]: borrowed data escapes outside of function - --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:35:5 + --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:37:9 | -LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | -- ------ `cell_a` is a reference that is only valid in the function body - | | - | lifetime `'a` defined here -LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { -... | -LL | | }); - | | ^ - | | | - | |______`cell_a` escapes the function body here - | argument requires that `'a` must outlive `'static` - | - = note: requirement occurs because of the type `Cell<&'?10 u32>`, which makes the generic argument `&'?10 u32` invariant - = note: the struct `Cell` is invariant over the parameter `T` - = help: see for more information about variance +LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | -- ------ `cell_a` is a reference that is only valid in the function body + | | + | lifetime `'a` defined here +... +LL | demand_y(x, y, x.get()) + | ^^^^^^^^^^^^^^^^^^^^^^^ + | | + | `cell_a` escapes the function body here + | argument requires that `'a` must outlive `'static` error: aborting due to 1 previous error diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.rs b/tests/ui/nll/closure-requirements/propagate-approximated-val.rs index e7e2f157604be..4d663c53d27a1 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-val.rs +++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.rs @@ -34,9 +34,10 @@ fn demand_y<'x, 'y>(_outlives1: Cell<&&'x u32>, _outlives2: Cell<&'y &u32>, _y: #[rustc_regions] fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { + //~^ ERROR lifetime may not live long enough + // Only works if 'x: 'y: demand_y(outlives1, outlives2, x.get()) - //~^ ERROR lifetime may not live long enough }); } diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr index 4787577a6e1a6..a14bfb06e831e 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-val.stderr @@ -23,17 +23,21 @@ LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { = note: defining type: test error: lifetime may not live long enough - --> $DIR/propagate-approximated-val.rs:38:9 + --> $DIR/propagate-approximated-val.rs:36:5 | -LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -... -LL | demand_y(outlives1, outlives2, x.get()) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b` +LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +LL | / establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { +... | +LL | | }); + | |______^ argument requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` + = note: requirement occurs because of the type `Cell<&'?7 u32>`, which makes the generic argument `&'?7 u32` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance error: aborting due to 1 previous error diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr index 669b56a0be70c..4558ff50674f8 100644 --- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-no-bounds.stderr @@ -22,6 +22,10 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { LL | // Only works if 'x: 'y: LL | demand_y(x, y, x.get()) | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + | + = note: requirement occurs because of the type `Cell<&'?37 u32>`, which makes the generic argument `&'?37 u32` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance note: no external requirements --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:34:1 diff --git a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr index 75f476ac5f188..83173ae80c00d 100644 --- a/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr +++ b/tests/ui/nll/closure-requirements/propagate-fail-to-approximate-longer-wrong-bounds.stderr @@ -22,6 +22,10 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y LL | // Only works if 'x: 'y: LL | demand_y(x, y, x.get()) | ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` + | + = note: requirement occurs because of the type `Cell<&'?43 u32>`, which makes the generic argument `&'?43 u32` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance note: no external requirements --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:38:1 diff --git a/tests/ui/nll/issue-54779-anon-static-lifetime.rs b/tests/ui/nll/issue-54779-anon-static-lifetime.rs index 260b6b109ca9b..3a92b9709a1d3 100644 --- a/tests/ui/nll/issue-54779-anon-static-lifetime.rs +++ b/tests/ui/nll/issue-54779-anon-static-lifetime.rs @@ -29,7 +29,7 @@ impl DebugWith for Foo { fmt: &mut std::fmt::Formatter<'_>, ) -> std::fmt::Result { let Foo { bar } = self; - bar.debug_with(cx); //~ ERROR: lifetime may not live long enough + bar.debug_with(cx); //~ ERROR borrowed data escapes outside of method [E0521] Ok(()) } } diff --git a/tests/ui/nll/issue-54779-anon-static-lifetime.stderr b/tests/ui/nll/issue-54779-anon-static-lifetime.stderr index a454ed265685c..03a5590661422 100644 --- a/tests/ui/nll/issue-54779-anon-static-lifetime.stderr +++ b/tests/ui/nll/issue-54779-anon-static-lifetime.stderr @@ -1,11 +1,17 @@ -error: lifetime may not live long enough - --> $DIR/issue-54779-anon-static-lifetime.rs:32:24 +error[E0521]: borrowed data escapes outside of method + --> $DIR/issue-54779-anon-static-lifetime.rs:32:9 | LL | cx: &dyn DebugContext, - | - let's call the lifetime of this reference `'1` + | -- - let's call the lifetime of this reference `'1` + | | + | `cx` is a reference that is only valid in the method body ... LL | bar.debug_with(cx); - | ^^ coercion requires that `'1` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^ + | | + | `cx` escapes the method body here + | argument requires that `'1` must outlive `'static` error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/nll/issue-62007-assign-const-index.stderr b/tests/ui/nll/issue-62007-assign-const-index.stderr index 0db9fe62c3869..32716c47cd4d8 100644 --- a/tests/ui/nll/issue-62007-assign-const-index.stderr +++ b/tests/ui/nll/issue-62007-assign-const-index.stderr @@ -17,10 +17,9 @@ LL | fn to_refs(mut list: [&mut List; 2]) -> Vec<&mut T> { | - let's call the lifetime of this reference `'1` ... LL | if let Some(n) = list[0].next.as_mut() { - | ^^^^^^^^^^^^--------- - | | - | `list[_].next` was mutably borrowed here in the previous iteration of the loop - | argument requires that `list[_].next` is borrowed for `'1` + | ^^^^^^^^^^^^ `list[_].next` was mutably borrowed here in the previous iteration of the loop +LL | list[0] = n; + | ----------- assignment requires that `list[_].next` is borrowed for `'1` error: aborting due to 2 previous errors diff --git a/tests/ui/nll/issue-62007-assign-differing-fields.stderr b/tests/ui/nll/issue-62007-assign-differing-fields.stderr index f1af2e855afe6..d51fd7a1389a0 100644 --- a/tests/ui/nll/issue-62007-assign-differing-fields.stderr +++ b/tests/ui/nll/issue-62007-assign-differing-fields.stderr @@ -17,10 +17,9 @@ LL | fn to_refs<'a, T>(mut list: (&'a mut List, &'a mut List)) -> Vec<&'a | -- lifetime `'a` defined here ... LL | if let Some(n) = (list.0).next.as_mut() { - | ^^^^^^^^^^^^^--------- - | | - | `list.0.next` was mutably borrowed here in the previous iteration of the loop - | argument requires that `list.0.next` is borrowed for `'a` + | ^^^^^^^^^^^^^ `list.0.next` was mutably borrowed here in the previous iteration of the loop +LL | list.1 = n; + | ---------- assignment requires that `list.0.next` is borrowed for `'a` error: aborting due to 2 previous errors diff --git a/tests/ui/nll/issue-67007-escaping-data.rs b/tests/ui/nll/issue-67007-escaping-data.rs index 49ea2e5964fa2..92a47f7884308 100644 --- a/tests/ui/nll/issue-67007-escaping-data.rs +++ b/tests/ui/nll/issue-67007-escaping-data.rs @@ -12,8 +12,8 @@ struct Consumer<'tcx>(&'tcx ()); impl<'tcx> Consumer<'tcx> { fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) { - let other = self.use_fcx(fcx); //~ ERROR lifetime may not live long enough - fcx.use_it(other); + let other = self.use_fcx(fcx); + fcx.use_it(other); //~ ERROR lifetime may not live long enough } fn use_fcx<'a>(&self, _: &FnCtxt<'a, 'tcx>) -> &'a () { diff --git a/tests/ui/nll/issue-67007-escaping-data.stderr b/tests/ui/nll/issue-67007-escaping-data.stderr index eb7b57c7e998a..3b9ed24685180 100644 --- a/tests/ui/nll/issue-67007-escaping-data.stderr +++ b/tests/ui/nll/issue-67007-escaping-data.stderr @@ -1,14 +1,18 @@ error: lifetime may not live long enough - --> $DIR/issue-67007-escaping-data.rs:15:21 + --> $DIR/issue-67007-escaping-data.rs:16:9 | LL | impl<'tcx> Consumer<'tcx> { | ---- lifetime `'tcx` defined here LL | fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) { | -- lifetime `'a` defined here LL | let other = self.use_fcx(fcx); - | ^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'tcx` +LL | fcx.use_it(other); + | ^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'tcx` | = help: consider adding the following bound: `'a: 'tcx` + = note: requirement occurs because of the type `FnCtxt<'_, '_>`, which makes the generic argument `'_` invariant + = note: the struct `FnCtxt<'a, 'tcx>` is invariant over the parameter `'tcx` + = help: see for more information about variance error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-95272.rs b/tests/ui/nll/issue-95272.rs index 958cbde37882d..b3325a05e5c07 100644 --- a/tests/ui/nll/issue-95272.rs +++ b/tests/ui/nll/issue-95272.rs @@ -8,8 +8,8 @@ where fn test<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) { let f = check; - //~^ ERROR lifetime may not live long enough f(x, y); + //~^ ERROR lifetime may not live long enough } fn main() {} diff --git a/tests/ui/nll/issue-95272.stderr b/tests/ui/nll/issue-95272.stderr index 0453ef8e53ea3..3d1720239e9a0 100644 --- a/tests/ui/nll/issue-95272.stderr +++ b/tests/ui/nll/issue-95272.stderr @@ -1,16 +1,17 @@ error: lifetime may not live long enough - --> $DIR/issue-95272.rs:10:13 + --> $DIR/issue-95272.rs:11:5 | LL | fn test<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here LL | let f = check; - | ^^^^^ assignment requires that `'a` must outlive `'b` +LL | f(x, y); + | ^^^^^^^ argument requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` - = note: requirement occurs because of a function pointer to `check` - = note: the function `check` is invariant over the parameter `'a` + = note: requirement occurs because of the type `Cell<&()>`, which makes the generic argument `&()` invariant + = note: the struct `Cell` is invariant over the parameter `T` = help: see for more information about variance error: aborting due to 1 previous error diff --git a/tests/ui/nll/outlives-suggestion-simple.stderr b/tests/ui/nll/outlives-suggestion-simple.stderr index bcffd575aed48..669532005b292 100644 --- a/tests/ui/nll/outlives-suggestion-simple.stderr +++ b/tests/ui/nll/outlives-suggestion-simple.stderr @@ -99,6 +99,10 @@ LL | fn get_bar(&self) -> Bar2 { | - let's call the lifetime of this reference `'1` LL | Bar2::new(&self) | ^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a` + | + = note: requirement occurs because of the type `Foo2<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Foo2<'a>` is invariant over the parameter `'a` + = help: see for more information about variance error: aborting due to 9 previous errors diff --git a/tests/ui/nll/polonius/assignment-to-differing-field.stderr b/tests/ui/nll/polonius/assignment-to-differing-field.stderr index acac47eac4f0e..c46d010e4f576 100644 --- a/tests/ui/nll/polonius/assignment-to-differing-field.stderr +++ b/tests/ui/nll/polonius/assignment-to-differing-field.stderr @@ -17,10 +17,10 @@ LL | fn assignment_to_field_projection<'a, T>( | -- lifetime `'a` defined here ... LL | if let Some(n) = (list.0).next.as_mut() { - | ^^^^^^^^^^^^^--------- - | | - | `list.0.next` was mutably borrowed here in the previous iteration of the loop - | argument requires that `list.0.next` is borrowed for `'a` + | ^^^^^^^^^^^^^ `list.0.next` was mutably borrowed here in the previous iteration of the loop +LL | +LL | list.1 = n; + | ---------- assignment requires that `list.0.next` is borrowed for `'a` error[E0499]: cannot borrow `list.0.0.0.0.0.value` as mutable more than once at a time --> $DIR/assignment-to-differing-field.rs:37:21 @@ -41,10 +41,10 @@ LL | fn assignment_through_projection_chain<'a, T>( | -- lifetime `'a` defined here ... LL | if let Some(n) = ((((list.0).0).0).0).0.next.as_mut() { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^--------- - | | - | `list.0.0.0.0.0.next` was mutably borrowed here in the previous iteration of the loop - | argument requires that `list.0.0.0.0.0.next` is borrowed for `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `list.0.0.0.0.0.next` was mutably borrowed here in the previous iteration of the loop +LL | +LL | *((((list.0).0).0).0).1 = n; + | --------------------------- assignment requires that `list.0.0.0.0.0.next` is borrowed for `'a` error: aborting due to 4 previous errors diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr index 1d086c658dfcd..e4b323bc2b6ac 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr @@ -1,23 +1,20 @@ -error[E0597]: `a` does not live long enough - --> $DIR/location-insensitive-scopes-issue-117146.rs:10:18 +error[E0373]: closure may outlive the current function, but it borrows `a`, which is owned by the current function + --> $DIR/location-insensitive-scopes-issue-117146.rs:10:13 | -LL | let a = (); - | - binding `a` declared here LL | let b = |_| &a; - | --- -^ - | | || - | | |borrowed value does not live long enough - | | returning this value requires that `a` is borrowed for `'static` - | value captured here -... -LL | } - | - `a` dropped here while still borrowed - | -note: due to current limitations in the borrow checker, this implies a `'static` lifetime - --> $DIR/location-insensitive-scopes-issue-117146.rs:20:22 - | -LL | fn bad &()>(_: F) {} - | ^^^ + | ^^^ - `a` is borrowed here + | | + | may outlive borrowed value `a` + | +note: function requires argument type to outlive `'static` + --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 + | +LL | bad(&b); + | ^^^^^^^ +help: to force the closure to take ownership of `a` (and any other referenced variables), use the `move` keyword + | +LL | let b = move |_| &a; + | ++++ error: implementation of `Fn` is not general enough --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 @@ -39,4 +36,4 @@ LL | bad(&b); error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0597`. +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr index 1d086c658dfcd..e4b323bc2b6ac 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr @@ -1,23 +1,20 @@ -error[E0597]: `a` does not live long enough - --> $DIR/location-insensitive-scopes-issue-117146.rs:10:18 +error[E0373]: closure may outlive the current function, but it borrows `a`, which is owned by the current function + --> $DIR/location-insensitive-scopes-issue-117146.rs:10:13 | -LL | let a = (); - | - binding `a` declared here LL | let b = |_| &a; - | --- -^ - | | || - | | |borrowed value does not live long enough - | | returning this value requires that `a` is borrowed for `'static` - | value captured here -... -LL | } - | - `a` dropped here while still borrowed - | -note: due to current limitations in the borrow checker, this implies a `'static` lifetime - --> $DIR/location-insensitive-scopes-issue-117146.rs:20:22 - | -LL | fn bad &()>(_: F) {} - | ^^^ + | ^^^ - `a` is borrowed here + | | + | may outlive borrowed value `a` + | +note: function requires argument type to outlive `'static` + --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 + | +LL | bad(&b); + | ^^^^^^^ +help: to force the closure to take ownership of `a` (and any other referenced variables), use the `move` keyword + | +LL | let b = move |_| &a; + | ++++ error: implementation of `Fn` is not general enough --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 @@ -39,4 +36,4 @@ LL | bad(&b); error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0597`. +For more information about this error, try `rustc --explain E0373`. diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs index c828a37521e0e..bd26af5bee25c 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs @@ -8,8 +8,8 @@ fn main() { let a = (); let b = |_| &a; - //[nll]~^ ERROR `a` does not live long enough - //[polonius]~^^ ERROR `a` does not live long enough + //[nll]~^ ERROR closure may outlive the current function, but it borrows `a` + //[polonius]~^^ ERROR closure may outlive the current function, but it borrows `a` bad(&b); //[nll]~^ ERROR implementation of `Fn` //[nll]~| ERROR implementation of `FnOnce` diff --git a/tests/ui/nll/relate_tys/var-appears-twice.stderr b/tests/ui/nll/relate_tys/var-appears-twice.stderr index 3f9a6cec0d2e5..2b2ec88ba8e07 100644 --- a/tests/ui/nll/relate_tys/var-appears-twice.stderr +++ b/tests/ui/nll/relate_tys/var-appears-twice.stderr @@ -5,9 +5,10 @@ LL | let b = 44; | - binding `b` declared here ... LL | let x: DoubleCell<_> = make_cell(&b); - | ------------- ^^ borrowed value does not live long enough - | | - | type annotation requires that `b` is borrowed for `'static` + | ----------^^- + | | | + | | borrowed value does not live long enough + | assignment requires that `b` is borrowed for `'static` ... LL | } | - `b` dropped here while still borrowed diff --git a/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr b/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr index dda60398198e7..408c57a31eea8 100644 --- a/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr +++ b/tests/ui/nll/ty-outlives/projection-one-region-closure.stderr @@ -24,6 +24,22 @@ LL | | T: Anything<'b>, | = note: defining type: no_relationships_late::<'?1, T> +error: lifetime may not live long enough + --> $DIR/projection-one-region-closure.rs:45:5 + | +LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of the type `Cell<&'?6 ()>`, which makes the generic argument `&'?6 ()` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance + error[E0309]: the parameter type `T` may not live long enough --> $DIR/projection-one-region-closure.rs:45:39 | @@ -38,19 +54,6 @@ help: consider adding an explicit lifetime bound LL | T: Anything<'b> + 'a, | ++++ -error: lifetime may not live long enough - --> $DIR/projection-one-region-closure.rs:45:39 - | -LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -... -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` - | - = help: consider adding the following bound: `'b: 'a` - note: external requirements --> $DIR/projection-one-region-closure.rs:56:29 | @@ -77,6 +80,22 @@ LL | | 'a: 'a, | = note: defining type: no_relationships_early::<'?1, '?2, T> +error: lifetime may not live long enough + --> $DIR/projection-one-region-closure.rs:56:5 + | +LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) + | -- -- lifetime `'b` defined here + | | + | lifetime `'a` defined here +... +LL | with_signature(cell, t, |cell, t| require(cell, t)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | + = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of the type `Cell<&'?7 ()>`, which makes the generic argument `&'?7 ()` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance + error[E0309]: the parameter type `T` may not live long enough --> $DIR/projection-one-region-closure.rs:56:39 | @@ -91,19 +110,6 @@ help: consider adding an explicit lifetime bound LL | T: Anything<'b> + 'a, | ++++ -error: lifetime may not live long enough - --> $DIR/projection-one-region-closure.rs:56:39 - | -LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) - | -- -- lifetime `'b` defined here - | | - | lifetime `'a` defined here -... -LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` - | - = help: consider adding the following bound: `'b: 'a` - note: external requirements --> $DIR/projection-one-region-closure.rs:70:29 | diff --git a/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr index 52040663e005c..4ebdf10c5bf3d 100644 --- a/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr +++ b/tests/ui/nll/ty-outlives/projection-one-region-trait-bound-closure.stderr @@ -24,7 +24,7 @@ LL | | T: Anything<'b>, = note: defining type: no_relationships_late::<'?1, T> error: lifetime may not live long enough - --> $DIR/projection-one-region-trait-bound-closure.rs:37:39 + --> $DIR/projection-one-region-trait-bound-closure.rs:37:5 | LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | -- -- lifetime `'b` defined here @@ -32,9 +32,12 @@ LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | lifetime `'a` defined here ... LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of the type `Cell<&'?6 ()>`, which makes the generic argument `&'?6 ()` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance note: external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:47:29 @@ -62,7 +65,7 @@ LL | | 'a: 'a, = note: defining type: no_relationships_early::<'?1, '?2, T> error: lifetime may not live long enough - --> $DIR/projection-one-region-trait-bound-closure.rs:47:39 + --> $DIR/projection-one-region-trait-bound-closure.rs:47:5 | LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | -- -- lifetime `'b` defined here @@ -70,9 +73,12 @@ LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T) | lifetime `'a` defined here ... LL | with_signature(cell, t, |cell, t| require(cell, t)); - | ^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of the type `Cell<&'?7 ()>`, which makes the generic argument `&'?7 ()` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance note: external requirements --> $DIR/projection-one-region-trait-bound-closure.rs:60:29 diff --git a/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr b/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr index c157e89ff8f31..f8dbe08af6166 100644 --- a/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr +++ b/tests/ui/nll/ty-outlives/projection-two-region-trait-bound-closure.stderr @@ -182,7 +182,7 @@ LL | with_signature(cell, t, |cell, t| require(cell, t)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of the type `Cell<&'?8 ()>`, which makes the generic argument `&'?8 ()` invariant + = note: requirement occurs because of the type `Cell<&'?6 ()>`, which makes the generic argument `&'?6 ()` invariant = note: the struct `Cell` is invariant over the parameter `T` = help: see for more information about variance diff --git a/tests/ui/nll/user-annotations/adt-nullary-enums.stderr b/tests/ui/nll/user-annotations/adt-nullary-enums.stderr index 644fc94f73087..cdaa934122ce0 100644 --- a/tests/ui/nll/user-annotations/adt-nullary-enums.stderr +++ b/tests/ui/nll/user-annotations/adt-nullary-enums.stderr @@ -1,52 +1,49 @@ error[E0597]: `c` does not live long enough --> $DIR/adt-nullary-enums.rs:33:41 | -LL | let c = 66; - | - binding `c` declared here -LL | combine( -LL | SomeEnum::SomeVariant(Cell::new(&c)), - | ----------^^- - | | | - | | borrowed value does not live long enough - | argument requires that `c` is borrowed for `'static` -... -LL | } - | - `c` dropped here while still borrowed +LL | let c = 66; + | - binding `c` declared here +LL | / combine( +LL | | SomeEnum::SomeVariant(Cell::new(&c)), + | | ^^ borrowed value does not live long enough +LL | | SomeEnum::SomeOtherVariant::>, +LL | | ); + | |_____- argument requires that `c` is borrowed for `'static` +LL | } + | - `c` dropped here while still borrowed error[E0597]: `c` does not live long enough --> $DIR/adt-nullary-enums.rs:41:41 | -LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { - | -- lifetime `'a` defined here -LL | let c = 66; - | - binding `c` declared here -LL | combine( -LL | SomeEnum::SomeVariant(Cell::new(&c)), - | ----------^^- - | | | - | | borrowed value does not live long enough - | argument requires that `c` is borrowed for `'a` -... -LL | } - | - `c` dropped here while still borrowed +LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { + | -- lifetime `'a` defined here +LL | let c = 66; + | - binding `c` declared here +LL | / combine( +LL | | SomeEnum::SomeVariant(Cell::new(&c)), + | | ^^ borrowed value does not live long enough +LL | | SomeEnum::SomeOtherVariant::>, +LL | | ); + | |_____- argument requires that `c` is borrowed for `'a` +LL | } + | - `c` dropped here while still borrowed error[E0597]: `c` does not live long enough --> $DIR/adt-nullary-enums.rs:54:45 | -LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { - | -- lifetime `'a` defined here -LL | let _closure = || { -LL | let c = 66; - | - binding `c` declared here -LL | combine( -LL | SomeEnum::SomeVariant(Cell::new(&c)), - | ----------^^- - | | | - | | borrowed value does not live long enough - | argument requires that `c` is borrowed for `'a` -... -LL | }; - | - `c` dropped here while still borrowed +LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) { + | -- lifetime `'a` defined here +LL | let _closure = || { +LL | let c = 66; + | - binding `c` declared here +LL | / combine( +LL | | SomeEnum::SomeVariant(Cell::new(&c)), + | | ^^ borrowed value does not live long enough +LL | | SomeEnum::SomeOtherVariant::>, +LL | | ); + | |_________- argument requires that `c` is borrowed for `'a` +LL | }; + | - `c` dropped here while still borrowed error: aborting due to 3 previous errors diff --git a/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr index 2084697e7e26d..1478ad1431ba4 100644 --- a/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr +++ b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr @@ -4,11 +4,9 @@ error[E0597]: `c` does not live long enough LL | let c = 66; | - binding `c` declared here LL | let f = SomeStruct::<&'static u32>; + | -------------------------- assignment requires that `c` is borrowed for `'static` LL | f(&c); - | --^^- - | | | - | | borrowed value does not live long enough - | argument requires that `c` is borrowed for `'static` + | ^^ borrowed value does not live long enough LL | } | - `c` dropped here while still borrowed @@ -20,11 +18,9 @@ LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { LL | let c = 66; | - binding `c` declared here LL | let f = SomeStruct::<&'a u32>; + | --------------------- assignment requires that `c` is borrowed for `'a` LL | f(&c); - | --^^- - | | | - | | borrowed value does not live long enough - | argument requires that `c` is borrowed for `'a` + | ^^ borrowed value does not live long enough LL | } | - `c` dropped here while still borrowed @@ -37,11 +33,9 @@ LL | let _closure = || { LL | let c = 66; | - binding `c` declared here LL | let f = SomeStruct::<&'a u32>; + | --------------------- assignment requires that `c` is borrowed for `'a` LL | f(&c); - | --^^- - | | | - | | borrowed value does not live long enough - | argument requires that `c` is borrowed for `'a` + | ^^ borrowed value does not live long enough LL | }; | - `c` dropped here while still borrowed diff --git a/tests/ui/nll/user-annotations/method-ufcs-1.stderr b/tests/ui/nll/user-annotations/method-ufcs-1.stderr index c42ea0172cf75..087e270c70f7d 100644 --- a/tests/ui/nll/user-annotations/method-ufcs-1.stderr +++ b/tests/ui/nll/user-annotations/method-ufcs-1.stderr @@ -4,11 +4,10 @@ error[E0597]: `a` does not live long enough LL | let a = 22; | - binding `a` declared here ... +LL | let x = <&'static u32 as Bazoom<_>>::method; + | ----------------------------------- assignment requires that `a` is borrowed for `'static` LL | x(&a, b, c); - | --^^------- - | | | - | | borrowed value does not live long enough - | argument requires that `a` is borrowed for `'static` + | ^^ borrowed value does not live long enough LL | } | - `a` dropped here while still borrowed diff --git a/tests/ui/nll/user-annotations/method-ufcs-2.stderr b/tests/ui/nll/user-annotations/method-ufcs-2.stderr index 287337c7d52d3..c89bed3b1b18f 100644 --- a/tests/ui/nll/user-annotations/method-ufcs-2.stderr +++ b/tests/ui/nll/user-annotations/method-ufcs-2.stderr @@ -4,11 +4,10 @@ error[E0597]: `a` does not live long enough LL | let a = 22; | - binding `a` declared here ... +LL | let x = <&'static u32 as Bazoom<_>>::method; + | ----------------------------------- assignment requires that `a` is borrowed for `'static` LL | x(&a, b, c); - | --^^------- - | | | - | | borrowed value does not live long enough - | argument requires that `a` is borrowed for `'static` + | ^^ borrowed value does not live long enough LL | } | - `a` dropped here while still borrowed diff --git a/tests/ui/nll/where_clauses_in_structs.stderr b/tests/ui/nll/where_clauses_in_structs.stderr index 4cc7e5ab1b4c7..19a1ce00e9a8f 100644 --- a/tests/ui/nll/where_clauses_in_structs.stderr +++ b/tests/ui/nll/where_clauses_in_structs.stderr @@ -1,12 +1,12 @@ error: lifetime may not live long enough - --> $DIR/where_clauses_in_structs.rs:11:11 + --> $DIR/where_clauses_in_structs.rs:11:14 | LL | fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here LL | Foo { x, y }; - | ^ this usage requires that `'a` must outlive `'b` + | ^ this usage requires that `'a` must outlive `'b` | = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of the type `Cell<&u32>`, which makes the generic argument `&u32` invariant diff --git a/tests/ui/regions/better-blame-constraint-for-outlives-static.rs b/tests/ui/regions/better-blame-constraint-for-outlives-static.rs new file mode 100644 index 0000000000000..77cadb783016c --- /dev/null +++ b/tests/ui/regions/better-blame-constraint-for-outlives-static.rs @@ -0,0 +1,13 @@ +//! diagnostic test for #132749: ensure we pick a decent span and reason to blame for region errors +//! when failing to prove a region outlives 'static + +struct Bytes(&'static [u8]); + +fn deserialize_simple_string(buf: &[u8]) -> (Bytes, &[u8]) { + //~^ NOTE let's call the lifetime of this reference `'1` + let (s, rest) = buf.split_at(2); + (Bytes(s), rest) //~ ERROR lifetime may not live long enough + //~| NOTE this usage requires that `'1` must outlive `'static` +} + +fn main() {} diff --git a/tests/ui/regions/better-blame-constraint-for-outlives-static.stderr b/tests/ui/regions/better-blame-constraint-for-outlives-static.stderr new file mode 100644 index 0000000000000..e1e88829f2c4f --- /dev/null +++ b/tests/ui/regions/better-blame-constraint-for-outlives-static.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/better-blame-constraint-for-outlives-static.rs:9:12 + | +LL | fn deserialize_simple_string(buf: &[u8]) -> (Bytes, &[u8]) { + | - let's call the lifetime of this reference `'1` +... +LL | (Bytes(s), rest) + | ^ this usage requires that `'1` must outlive `'static` + +error: aborting due to 1 previous error + diff --git a/tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.stderr b/tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.stderr index fcd0a232a7bd3..9f1315070eb29 100644 --- a/tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.stderr +++ b/tests/ui/regions/lifetime-not-long-enough-suggestion-regression-test-124563.stderr @@ -25,6 +25,10 @@ LL | self.enter_scope(|ctx| { | has type `&mut FooImpl<'2, '_, T>` LL | BarImpl(ctx); | ^^^ this usage requires that `'1` must outlive `'2` + | + = note: requirement occurs because of a mutable reference to `FooImpl<'_, '_, T>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance error: lifetime may not live long enough --> $DIR/lifetime-not-long-enough-suggestion-regression-test-124563.rs:22:9 diff --git a/tests/ui/regions/region-invariant-static-error-reporting.rs b/tests/ui/regions/region-invariant-static-error-reporting.rs index 9ab46a7757897..e58eea3f61ae7 100644 --- a/tests/ui/regions/region-invariant-static-error-reporting.rs +++ b/tests/ui/regions/region-invariant-static-error-reporting.rs @@ -3,7 +3,7 @@ // over time, but this test used to exhibit some pretty bogus messages // that were not remotely helpful. -//@ error-pattern:argument requires that `'a` must outlive `'static` +//@ error-pattern:requires that `'a` must outlive `'static` struct Invariant<'a>(Option<&'a mut &'a mut ()>); @@ -11,9 +11,9 @@ fn mk_static() -> Invariant<'static> { Invariant(None) } fn unify<'a>(x: Option>, f: fn(Invariant<'a>)) { let bad = if x.is_some() { - x.unwrap() //~ ERROR borrowed data escapes outside of function [E0521] + x.unwrap() } else { - mk_static() + mk_static() //~ ERROR lifetime may not live long enough }; f(bad); } diff --git a/tests/ui/regions/region-invariant-static-error-reporting.stderr b/tests/ui/regions/region-invariant-static-error-reporting.stderr index 834d5c6cf5a8b..2ccf36713ae89 100644 --- a/tests/ui/regions/region-invariant-static-error-reporting.stderr +++ b/tests/ui/regions/region-invariant-static-error-reporting.stderr @@ -1,16 +1,11 @@ -error[E0521]: borrowed data escapes outside of function - --> $DIR/region-invariant-static-error-reporting.rs:14:9 +error: lifetime may not live long enough + --> $DIR/region-invariant-static-error-reporting.rs:16:9 | LL | fn unify<'a>(x: Option>, f: fn(Invariant<'a>)) { - | -- - `x` is a reference that is only valid in the function body - | | - | lifetime `'a` defined here -LL | let bad = if x.is_some() { -LL | x.unwrap() - | ^^^^^^^^^^ - | | - | `x` escapes the function body here - | argument requires that `'a` must outlive `'static` + | -- lifetime `'a` defined here +... +LL | mk_static() + | ^^^^^^^^^^^ assignment requires that `'a` must outlive `'static` | = note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant = note: the struct `Invariant<'a>` is invariant over the parameter `'a` @@ -18,4 +13,3 @@ LL | x.unwrap() error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs index c24672816acdb..8f3171222bb6f 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs @@ -64,7 +64,7 @@ mod bay { fn use_it<'a>(val: Box + 'a>) -> &'a () { val.use_self() - //~^ ERROR: cannot return value referencing function parameter `val` + //~^ ERROR: `val` does not live long enough //~| ERROR: borrowed data escapes outside of function } } diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr index 505765d2b41f6..a8a854220b4e5 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr @@ -25,6 +25,20 @@ LL | val.use_self() | returns a value referencing data owned by the current function | `val` is borrowed here +error[E0597]: `val` does not live long enough + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:9 + | +LL | fn use_it<'a>(val: Box + 'a>) -> &'a () { + | --- binding `val` declared here +LL | val.use_self() + | ^^^----------- + | | + | borrowed value does not live long enough + | argument requires that `val` is borrowed for `'static` +... +LL | } + | - `val` dropped here while still borrowed + error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:9 | @@ -50,15 +64,6 @@ help: consider relaxing the implicit `'static` requirement LL | impl MyTrait for Box + '_> { | ++++ -error[E0515]: cannot return value referencing function parameter `val` - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:9 - | -LL | val.use_self() - | ---^^^^^^^^^^^ - | | - | returns a value referencing data owned by the current function - | `val` is borrowed here - error[E0515]: cannot return value referencing function parameter `val` --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:90:9 | @@ -70,5 +75,5 @@ LL | val.use_self() error: aborting due to 6 previous errors -Some errors have detailed explanations: E0515, E0521. +Some errors have detailed explanations: E0515, E0521, E0597. For more information about an error, try `rustc --explain E0515`. diff --git a/tests/ui/traits/coercion-generic-regions.stderr b/tests/ui/traits/coercion-generic-regions.stderr index 576035f8c13e4..c48767095dffb 100644 --- a/tests/ui/traits/coercion-generic-regions.stderr +++ b/tests/ui/traits/coercion-generic-regions.stderr @@ -4,11 +4,9 @@ error[E0597]: `person` does not live long enough LL | let person = "Fred".to_string(); | ------ binding `person` declared here LL | let person: &str = &person; - | ^^^^^^^ - | | - | borrowed value does not live long enough - | assignment requires that `person` is borrowed for `'static` + | ^^^^^^^ borrowed value does not live long enough LL | let s: Box> = Box::new(Struct { person: person }); + | ------ this usage requires that `person` is borrowed for `'static` LL | } | - `person` dropped here while still borrowed diff --git a/tests/ui/traits/trait-object-lifetime-default-note.rs b/tests/ui/traits/trait-object-lifetime-default-note.rs index 275411ff61c85..5d8d2c5391918 100644 --- a/tests/ui/traits/trait-object-lifetime-default-note.rs +++ b/tests/ui/traits/trait-object-lifetime-default-note.rs @@ -6,9 +6,8 @@ fn main() { let local = 0; //~ NOTE binding `local` declared here let r = &local; //~ ERROR `local` does not live long enough //~| NOTE borrowed value does not live long enough - //~| NOTE due to object lifetime defaults, `Box` actually means `Box<(dyn A + 'static)>` require_box(Box::new(r)); - //~^ NOTE coercion requires that `local` is borrowed for `'static` + //~^ NOTE argument requires that `local` is borrowed for `'static` let _ = 0; } //~ NOTE `local` dropped here while still borrowed diff --git a/tests/ui/traits/trait-object-lifetime-default-note.stderr b/tests/ui/traits/trait-object-lifetime-default-note.stderr index 8cb9bc0d80072..9a97704f49371 100644 --- a/tests/ui/traits/trait-object-lifetime-default-note.stderr +++ b/tests/ui/traits/trait-object-lifetime-default-note.stderr @@ -5,14 +5,12 @@ LL | let local = 0; | ----- binding `local` declared here LL | let r = &local; | ^^^^^^ borrowed value does not live long enough -... +LL | LL | require_box(Box::new(r)); - | ----------- coercion requires that `local` is borrowed for `'static` + | ------------------------ argument requires that `local` is borrowed for `'static` ... LL | } | - `local` dropped here while still borrowed - | - = note: due to object lifetime defaults, `Box` actually means `Box<(dyn A + 'static)>` error: aborting due to 1 previous error diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr index 0a969b611e9d3..01b8da645f31a 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr +++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr @@ -1,10 +1,10 @@ error: lifetime may not live long enough - --> $DIR/type-checking-test-3.rs:11:18 + --> $DIR/type-checking-test-3.rs:11:13 | LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here LL | let _ = x as &dyn Bar<'a>; // Error - | ^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^^^ cast requires that `'a` must outlive `'static` error: lifetime may not live long enough --> $DIR/type-checking-test-3.rs:16:18 diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr index 090120a2327a8..e91ea193a0104 100644 --- a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr +++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr @@ -1,10 +1,10 @@ error: lifetime may not live long enough - --> $DIR/type-checking-test-4.rs:19:18 + --> $DIR/type-checking-test-4.rs:19:13 | LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) { | -- lifetime `'a` defined here LL | let _ = x as &dyn Bar<'static, 'a>; // Error - | ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'a` must outlive `'static` error: lifetime may not live long enough --> $DIR/type-checking-test-4.rs:24:18 diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr index 40d3414024553..e2f48f37f0dad 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-argument-types-two-region-pointers.stderr @@ -7,6 +7,10 @@ LL | doit(0, &|x, y| { | has type `&Cell<&'2 i32>` LL | x.set(y); | ^^^^^^^^ argument requires that `'1` must outlive `'2` + | + = note: requirement occurs because of the type `Cell<&i32>`, which makes the generic argument `&i32` invariant + = note: the struct `Cell` is invariant over the parameter `T` + = help: see for more information about variance error: aborting due to 1 previous error diff --git a/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr b/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr index ed9d22d255839..8bd9b1112c56a 100644 --- a/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr +++ b/tests/ui/underscore-lifetime/underscore-lifetime-elison-mismatch.stderr @@ -7,6 +7,9 @@ LL | fn foo(x: &mut Vec<&'_ u8>, y: &'_ u8) { x.push(y); } | | let's call the lifetime of this reference `'1` | let's call the lifetime of this reference `'2` | + = note: requirement occurs because of a mutable reference to `Vec<&u8>` + = note: mutable references are invariant over their type parameter + = help: see for more information about variance help: consider introducing a named lifetime parameter | LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } diff --git a/tests/ui/variance/variance-associated-types2.stderr b/tests/ui/variance/variance-associated-types2.stderr index 158b09b0630ca..292d60941b185 100644 --- a/tests/ui/variance/variance-associated-types2.stderr +++ b/tests/ui/variance/variance-associated-types2.stderr @@ -1,10 +1,10 @@ error: lifetime may not live long enough - --> $DIR/variance-associated-types2.rs:13:12 + --> $DIR/variance-associated-types2.rs:13:42 | LL | fn take<'a>(_: &'a u32) { | -- lifetime `'a` defined here LL | let _: Box> = make(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` + | ^^^^^^ coercion requires that `'a` must outlive `'static` error: aborting due to 1 previous error diff --git a/tests/ui/variance/variance-contravariant-arg-object.stderr b/tests/ui/variance/variance-contravariant-arg-object.stderr index ab28315e11e52..7d7c6cb28cdf0 100644 --- a/tests/ui/variance/variance-contravariant-arg-object.stderr +++ b/tests/ui/variance/variance-contravariant-arg-object.stderr @@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box>) | lifetime `'min` defined here ... LL | v - | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` + | ^ coercion requires that `'min` must outlive `'max` | = help: consider adding the following bound: `'min: 'max` diff --git a/tests/ui/variance/variance-covariant-arg-object.stderr b/tests/ui/variance/variance-covariant-arg-object.stderr index 51f8cb3ec750b..4e82c8e8e1b4b 100644 --- a/tests/ui/variance/variance-covariant-arg-object.stderr +++ b/tests/ui/variance/variance-covariant-arg-object.stderr @@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box>) | lifetime `'min` defined here ... LL | v - | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` + | ^ coercion requires that `'min` must outlive `'max` | = help: consider adding the following bound: `'min: 'max` diff --git a/tests/ui/variance/variance-invariant-arg-object.stderr b/tests/ui/variance/variance-invariant-arg-object.stderr index 9793a36be06ab..e3969ebebcea4 100644 --- a/tests/ui/variance/variance-invariant-arg-object.stderr +++ b/tests/ui/variance/variance-invariant-arg-object.stderr @@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box>) | lifetime `'min` defined here ... LL | v - | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` + | ^ coercion requires that `'min` must outlive `'max` | = help: consider adding the following bound: `'min: 'max` From 2864906fce4e9252eddb96f2d09e9e2f113a9d4b Mon Sep 17 00:00:00 2001 From: dianne Date: Thu, 12 Dec 2024 08:45:32 -0800 Subject: [PATCH 04/12] `best_blame_constraint`: add a special case to recover object lifetime default notes --- .../rustc_borrowck/src/region_infer/mod.rs | 22 +++++++++- .../dropck/dropck_trait_cycle_checked.stderr | 42 +++++++++---------- .../nll/issue-54779-anon-static-lifetime.rs | 2 +- .../issue-54779-anon-static-lifetime.stderr | 14 ++----- .../trait-object-lifetime-default-note.rs | 3 +- .../trait-object-lifetime-default-note.stderr | 6 ++- 6 files changed, 51 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 4c2aeace67ed9..7ec692d36b168 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1945,7 +1945,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { target_test: impl Fn(RegionVid) -> bool, ) -> (BlameConstraint<'tcx>, Vec>) { // Find all paths - let (path, _) = self + let (path, target_region) = self .find_constraint_paths_between_regions(from_region, target_test) .or_else(|| { self.find_constraint_paths_between_regions(from_region, |r| { @@ -2071,6 +2071,26 @@ impl<'tcx> RegionInferenceContext<'tcx> { } } + Some(_) + if target_region == self.universal_regions().fr_static + && let Some(old_best) = path.iter().min_by_key(|p| p.category) + && matches!(old_best.category, ConstraintCategory::Cast { + is_implicit_coercion: true, + unsize_to: Some(_) + }) => + { + // FIXME(dianne): This is a hack in order to emit the subdiagnostic + // `BorrowExplanation::add_object_lifetime_default_note` more often, e.g. on + // `tests/ui/traits/trait-object-lifetime-default-note.rs`. The subdiagnostic + // depends on a coercion being blamed, so we fall back to an earlier version of this + // function's blaming logic to keep the test result the same. A proper fix will + // require rewriting the subdiagnostic not to rely on a coercion being blamed. + // For examples of where notes are missing, see #131008 and + // `tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs`. + // As part of fixing those, this case should be removed. + *old_best + } + Some(i) => path[i], None => { diff --git a/tests/ui/dropck/dropck_trait_cycle_checked.stderr b/tests/ui/dropck/dropck_trait_cycle_checked.stderr index e595e98fa2e43..f32736f1a674c 100644 --- a/tests/ui/dropck/dropck_trait_cycle_checked.stderr +++ b/tests/ui/dropck/dropck_trait_cycle_checked.stderr @@ -2,87 +2,83 @@ error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:111:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -- binding `o2` declared here + | -- binding `o2` declared here -------- coercion requires that `o2` is borrowed for `'static` LL | o1.set0(&o2); | ^^^ borrowed value does not live long enough ... -LL | o3.set0(&o1); - | ------------ argument requires that `o2` is borrowed for `'static` -LL | o3.set1(&o2); LL | } | - `o2` dropped here while still borrowed + | + = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o3` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:112:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -- binding `o3` declared here + | -- binding `o3` declared here -------- coercion requires that `o3` is borrowed for `'static` LL | o1.set0(&o2); LL | o1.set1(&o3); | ^^^ borrowed value does not live long enough ... -LL | o3.set0(&o1); - | ------------ argument requires that `o3` is borrowed for `'static` -LL | o3.set1(&o2); LL | } | - `o3` dropped here while still borrowed + | + = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:113:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -- binding `o2` declared here -LL | o1.set0(&o2); - | ------------ argument requires that `o2` is borrowed for `'static` -LL | o1.set1(&o3); + | -- binding `o2` declared here -------- coercion requires that `o2` is borrowed for `'static` +... LL | o2.set0(&o2); | ^^^ borrowed value does not live long enough ... LL | } | - `o2` dropped here while still borrowed + | + = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o3` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:114:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -- binding `o3` declared here -LL | o1.set0(&o2); - | ------------ argument requires that `o3` is borrowed for `'static` + | -- binding `o3` declared here -------- coercion requires that `o3` is borrowed for `'static` ... LL | o2.set1(&o3); | ^^^ borrowed value does not live long enough ... LL | } | - `o3` dropped here while still borrowed + | + = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o1` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:115:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -- binding `o1` declared here -LL | o1.set0(&o2); -LL | o1.set1(&o3); - | ------------ argument requires that `o1` is borrowed for `'static` + | -- binding `o1` declared here -------- coercion requires that `o1` is borrowed for `'static` ... LL | o3.set0(&o1); | ^^^ borrowed value does not live long enough LL | o3.set1(&o2); LL | } | - `o1` dropped here while still borrowed + | + = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error[E0597]: `o2` does not live long enough --> $DIR/dropck_trait_cycle_checked.rs:116:13 | LL | let (o1, o2, o3): (Box, Box, Box) = (O::new(), O::new(), O::new()); - | -- binding `o2` declared here -LL | o1.set0(&o2); -LL | o1.set1(&o3); - | ------------ argument requires that `o2` is borrowed for `'static` + | -- binding `o2` declared here -------- coercion requires that `o2` is borrowed for `'static` ... LL | o3.set1(&o2); | ^^^ borrowed value does not live long enough LL | } | - `o2` dropped here while still borrowed + | + = note: due to object lifetime defaults, `Box>` actually means `Box<(dyn Obj<'_> + 'static)>` error: aborting due to 6 previous errors diff --git a/tests/ui/nll/issue-54779-anon-static-lifetime.rs b/tests/ui/nll/issue-54779-anon-static-lifetime.rs index 3a92b9709a1d3..1dab7c1712afe 100644 --- a/tests/ui/nll/issue-54779-anon-static-lifetime.rs +++ b/tests/ui/nll/issue-54779-anon-static-lifetime.rs @@ -29,7 +29,7 @@ impl DebugWith for Foo { fmt: &mut std::fmt::Formatter<'_>, ) -> std::fmt::Result { let Foo { bar } = self; - bar.debug_with(cx); //~ ERROR borrowed data escapes outside of method [E0521] + bar.debug_with(cx); //~ lifetime may not live long enough Ok(()) } } diff --git a/tests/ui/nll/issue-54779-anon-static-lifetime.stderr b/tests/ui/nll/issue-54779-anon-static-lifetime.stderr index 03a5590661422..a454ed265685c 100644 --- a/tests/ui/nll/issue-54779-anon-static-lifetime.stderr +++ b/tests/ui/nll/issue-54779-anon-static-lifetime.stderr @@ -1,17 +1,11 @@ -error[E0521]: borrowed data escapes outside of method - --> $DIR/issue-54779-anon-static-lifetime.rs:32:9 +error: lifetime may not live long enough + --> $DIR/issue-54779-anon-static-lifetime.rs:32:24 | LL | cx: &dyn DebugContext, - | -- - let's call the lifetime of this reference `'1` - | | - | `cx` is a reference that is only valid in the method body + | - let's call the lifetime of this reference `'1` ... LL | bar.debug_with(cx); - | ^^^^^^^^^^^^^^^^^^ - | | - | `cx` escapes the method body here - | argument requires that `'1` must outlive `'static` + | ^^ coercion requires that `'1` must outlive `'static` error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/traits/trait-object-lifetime-default-note.rs b/tests/ui/traits/trait-object-lifetime-default-note.rs index 5d8d2c5391918..275411ff61c85 100644 --- a/tests/ui/traits/trait-object-lifetime-default-note.rs +++ b/tests/ui/traits/trait-object-lifetime-default-note.rs @@ -6,8 +6,9 @@ fn main() { let local = 0; //~ NOTE binding `local` declared here let r = &local; //~ ERROR `local` does not live long enough //~| NOTE borrowed value does not live long enough + //~| NOTE due to object lifetime defaults, `Box` actually means `Box<(dyn A + 'static)>` require_box(Box::new(r)); - //~^ NOTE argument requires that `local` is borrowed for `'static` + //~^ NOTE coercion requires that `local` is borrowed for `'static` let _ = 0; } //~ NOTE `local` dropped here while still borrowed diff --git a/tests/ui/traits/trait-object-lifetime-default-note.stderr b/tests/ui/traits/trait-object-lifetime-default-note.stderr index 9a97704f49371..8cb9bc0d80072 100644 --- a/tests/ui/traits/trait-object-lifetime-default-note.stderr +++ b/tests/ui/traits/trait-object-lifetime-default-note.stderr @@ -5,12 +5,14 @@ LL | let local = 0; | ----- binding `local` declared here LL | let r = &local; | ^^^^^^ borrowed value does not live long enough -LL | +... LL | require_box(Box::new(r)); - | ------------------------ argument requires that `local` is borrowed for `'static` + | ----------- coercion requires that `local` is borrowed for `'static` ... LL | } | - `local` dropped here while still borrowed + | + = note: due to object lifetime defaults, `Box` actually means `Box<(dyn A + 'static)>` error: aborting due to 1 previous error From 31e4d8175a3ef5d10f2319e98a20ca6c81614487 Mon Sep 17 00:00:00 2001 From: dianne Date: Fri, 13 Dec 2024 08:04:15 -0800 Subject: [PATCH 05/12] `best_blame_constraint`: avoid blaming constraints from MIR generated by desugaring --- .../rustc_borrowck/src/region_infer/mod.rs | 9 +++++++- tests/ui/async-await/issue-76547.rs | 4 ++-- tests/ui/async-await/issue-76547.stderr | 22 ++++++++++--------- tests/ui/async-await/issues/issue-63388-1.rs | 2 +- .../async-await/issues/issue-63388-1.stderr | 15 +++++-------- tests/ui/async-await/issues/issue-63388-2.rs | 2 +- .../async-await/issues/issue-63388-2.stderr | 15 +++++-------- 7 files changed, 36 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 7ec692d36b168..4ceb2fcd8d703 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -22,6 +22,7 @@ use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex}; use rustc_mir_dataflow::points::DenseLocationMap; use rustc_span::Span; +use rustc_span::hygiene::DesugaringKind; use tracing::{debug, instrument, trace}; use crate::BorrowckInferCtxt; @@ -2033,7 +2034,13 @@ impl<'tcx> RegionInferenceContext<'tcx> { | ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal | ConstraintCategory::Predicate(_) - ) + ) && constraint.span.desugaring_kind().is_none_or(|kind| { + // Try to avoid blaming constraints from desugarings, since they may not clearly + // clearly match what users have written. As an exception, allow blaming returns + // generated by `?` desugaring, since the correspondence is fairly clear. + kind == DesugaringKind::QuestionMark + && matches!(constraint.category, ConstraintCategory::Return(_)) + }) }; let best_choice = if blame_source { diff --git a/tests/ui/async-await/issue-76547.rs b/tests/ui/async-await/issue-76547.rs index 24decf9b5f77e..30a39c8943789 100644 --- a/tests/ui/async-await/issue-76547.rs +++ b/tests/ui/async-await/issue-76547.rs @@ -17,8 +17,8 @@ impl<'a> Future for ListFut<'a> { } async fn fut(bufs: &mut [&mut [u8]]) { - //~^ ERROR lifetime may not live long enough ListFut(bufs).await + //~^ ERROR lifetime may not live long enough } pub struct ListFut2<'a>(&'a mut [&'a mut [u8]]); @@ -31,8 +31,8 @@ impl<'a> Future for ListFut2<'a> { } async fn fut2(bufs: &mut [&mut [u8]]) -> i32 { - //~^ ERROR lifetime may not live long enough ListFut2(bufs).await + //~^ ERROR lifetime may not live long enough } fn main() {} diff --git a/tests/ui/async-await/issue-76547.stderr b/tests/ui/async-await/issue-76547.stderr index 73803a14e7a5e..4d96cce824b91 100644 --- a/tests/ui/async-await/issue-76547.stderr +++ b/tests/ui/async-await/issue-76547.stderr @@ -1,11 +1,12 @@ error: lifetime may not live long enough - --> $DIR/issue-76547.rs:19:14 + --> $DIR/issue-76547.rs:20:13 | LL | async fn fut(bufs: &mut [&mut [u8]]) { - | ^^^^ - - let's call the lifetime of this reference `'2` - | | | - | | let's call the lifetime of this reference `'1` - | assignment requires that `'1` must outlive `'2` + | - - let's call the lifetime of this reference `'2` + | | + | let's call the lifetime of this reference `'1` +LL | ListFut(bufs).await + | ^^^^ this usage requires that `'1` must outlive `'2` | help: consider introducing a named lifetime parameter | @@ -13,13 +14,14 @@ LL | async fn fut<'a>(bufs: &'a mut [&'a mut [u8]]) { | ++++ ++ ++ error: lifetime may not live long enough - --> $DIR/issue-76547.rs:33:15 + --> $DIR/issue-76547.rs:34:14 | LL | async fn fut2(bufs: &mut [&mut [u8]]) -> i32 { - | ^^^^ - - let's call the lifetime of this reference `'2` - | | | - | | let's call the lifetime of this reference `'1` - | assignment requires that `'1` must outlive `'2` + | - - let's call the lifetime of this reference `'2` + | | + | let's call the lifetime of this reference `'1` +LL | ListFut2(bufs).await + | ^^^^ this usage requires that `'1` must outlive `'2` | help: consider introducing a named lifetime parameter | diff --git a/tests/ui/async-await/issues/issue-63388-1.rs b/tests/ui/async-await/issues/issue-63388-1.rs index a6f499ba94e29..acfc64baff97d 100644 --- a/tests/ui/async-await/issues/issue-63388-1.rs +++ b/tests/ui/async-await/issues/issue-63388-1.rs @@ -11,8 +11,8 @@ impl Xyz { &'a self, foo: &dyn Foo ) -> &dyn Foo //~ WARNING elided lifetime has a name { - //~^ ERROR explicit lifetime required in the type of `foo` [E0621] foo + //~^ ERROR explicit lifetime required in the type of `foo` [E0621] } } diff --git a/tests/ui/async-await/issues/issue-63388-1.stderr b/tests/ui/async-await/issues/issue-63388-1.stderr index ef74bfe32375e..579caa45bc945 100644 --- a/tests/ui/async-await/issues/issue-63388-1.stderr +++ b/tests/ui/async-await/issues/issue-63388-1.stderr @@ -10,16 +10,13 @@ LL | ) -> &dyn Foo = note: `#[warn(elided_named_lifetimes)]` on by default error[E0621]: explicit lifetime required in the type of `foo` - --> $DIR/issue-63388-1.rs:13:5 + --> $DIR/issue-63388-1.rs:14:9 | -LL | &'a self, foo: &dyn Foo - | -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)` -LL | ) -> &dyn Foo -LL | / { -LL | | -LL | | foo -LL | | } - | |_____^ lifetime `'a` required +LL | &'a self, foo: &dyn Foo + | -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)` +... +LL | foo + | ^^^ lifetime `'a` required error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/async-await/issues/issue-63388-2.rs b/tests/ui/async-await/issues/issue-63388-2.rs index 85718f4112151..8bb5cfa4a594a 100644 --- a/tests/ui/async-await/issues/issue-63388-2.rs +++ b/tests/ui/async-await/issues/issue-63388-2.rs @@ -11,8 +11,8 @@ impl Xyz { foo: &dyn Foo, bar: &'a dyn Foo ) -> &dyn Foo //~ ERROR missing lifetime specifier { - //~^ ERROR explicit lifetime required in the type of `foo` [E0621] foo + //~^ ERROR explicit lifetime required in the type of `foo` [E0621] } } diff --git a/tests/ui/async-await/issues/issue-63388-2.stderr b/tests/ui/async-await/issues/issue-63388-2.stderr index e515f227c7ef6..7e3c0a1227de8 100644 --- a/tests/ui/async-await/issues/issue-63388-2.stderr +++ b/tests/ui/async-await/issues/issue-63388-2.stderr @@ -13,16 +13,13 @@ LL | ) -> &'a dyn Foo | ++ error[E0621]: explicit lifetime required in the type of `foo` - --> $DIR/issue-63388-2.rs:13:5 + --> $DIR/issue-63388-2.rs:14:9 | -LL | foo: &dyn Foo, bar: &'a dyn Foo - | -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)` -LL | ) -> &dyn Foo -LL | / { -LL | | -LL | | foo -LL | | } - | |_____^ lifetime `'a` required +LL | foo: &dyn Foo, bar: &'a dyn Foo + | -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)` +... +LL | foo + | ^^^ lifetime `'a` required error: aborting due to 2 previous errors From 50222dba2edd2bcf265a8ca4753de0df59bf587d Mon Sep 17 00:00:00 2001 From: dianne Date: Thu, 19 Dec 2024 01:16:53 -0800 Subject: [PATCH 06/12] `best_blame_constraint`: avoid blaming assignments without user-provided types --- .../src/diagnostics/conflict_errors.rs | 2 +- .../src/diagnostics/region_errors.rs | 6 +-- .../rustc_borrowck/src/region_infer/mod.rs | 1 + compiler/rustc_borrowck/src/type_check/mod.rs | 16 +++++++- compiler/rustc_middle/src/mir/query.rs | 7 +++- ...egion_subtyping_basic.main.nll.0.32bit.mir | 4 +- ...egion_subtyping_basic.main.nll.0.64bit.mir | 4 +- tests/mir-opt/storage_ranges.main.nll.0.mir | 2 +- tests/ui/fn/fn_def_coercion.rs | 4 +- tests/ui/fn/fn_def_coercion.stderr | 41 +++++++++---------- .../ex3-both-anon-regions-2.rs | 2 +- .../ex3-both-anon-regions-2.stderr | 14 +++---- .../ui/match/match-ref-mut-invariance.stderr | 4 +- .../ui/match/match-ref-mut-let-invariance.rs | 2 +- .../match/match-ref-mut-let-invariance.stderr | 5 ++- .../adt-tuple-struct-calls.stderr | 18 +++++--- .../nll/user-annotations/method-ufcs-1.stderr | 7 ++-- .../nll/user-annotations/method-ufcs-2.stderr | 7 ++-- .../promoted-annotation.stderr | 6 ++- 19 files changed, 88 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2d993a3fd16f7..8a43e4b54b195 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2911,7 +2911,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ( name, BorrowExplanation::MustBeValidFor { - category: ConstraintCategory::Assignment, + category: ConstraintCategory::Assignment { .. }, from_closure: false, region_name: RegionName { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 481b8d41f10cd..78809908180ac 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -41,7 +41,7 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { fn description(&self) -> &'static str { // Must end with a space. Allows for empty names to be provided. match self { - ConstraintCategory::Assignment => "assignment ", + ConstraintCategory::Assignment { .. } => "assignment ", ConstraintCategory::Return(_) => "returning this value ", ConstraintCategory::Yield => "yielding this value ", ConstraintCategory::UseAsConst => "using this value as a constant ", @@ -481,7 +481,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { (ConstraintCategory::Return(kind), true, false) if self.is_closure_fn_mut(fr) => { self.report_fnmut_error(&errci, kind) } - (ConstraintCategory::Assignment, true, false) + (ConstraintCategory::Assignment { .. }, true, false) | (ConstraintCategory::CallArgument(_), true, false) => { let mut db = self.report_escaping_data_error(&errci); @@ -672,7 +672,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // Revert to the normal error in these cases. // Assignments aren't "escapes" in function items. if (fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none()) - || (*category == ConstraintCategory::Assignment + || (matches!(category, ConstraintCategory::Assignment { .. }) && self.regioncx.universal_regions().defining_ty.is_fn_def()) || self.regioncx.universal_regions().defining_ty.is_const() { diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 4ceb2fcd8d703..7e8fad8698aef 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -2034,6 +2034,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { | ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal | ConstraintCategory::Predicate(_) + | ConstraintCategory::Assignment { has_interesting_ty: false } ) && constraint.span.desugaring_kind().is_none_or(|kind| { // Try to avoid blaming constraints from desugarings, since they may not clearly // clearly match what users have written. As an exception, allow blaming returns diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 10fb8a399a267..a436edd85d92e 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -892,7 +892,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Some(l) if !body.local_decls[l].is_user_variable() => { ConstraintCategory::Boring } - _ => ConstraintCategory::Assignment, + Some(l) => ConstraintCategory::Assignment { + has_interesting_ty: body.local_decls[l].user_ty.is_some() + || matches!( + body.local_decls[l].local_info(), + LocalInfo::User(BindingForm::Var(VarBindingForm { + opt_ty_info: Some(_), + .. + })) + ), + }, + // Assignments to projections should be considered interesting. + _ => ConstraintCategory::Assignment { has_interesting_ty: true }, }; debug!( "assignment category: {:?} {:?}", @@ -1226,7 +1237,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Some(l) if !body.local_decls[l].is_user_variable() => { ConstraintCategory::Boring } - _ => ConstraintCategory::Assignment, + // The return type of a call is interesting for diagnostics. + _ => ConstraintCategory::Assignment { has_interesting_ty: true }, }; let locations = term_location.to_locations(); diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 429be9bc725be..c2bb95a91c47e 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -250,7 +250,12 @@ pub enum ConstraintCategory<'tcx> { CallArgument(#[derive_where(skip)] Option>), CopyBound, SizedBound, - Assignment, + Assignment { + /// Whether this assignment is likely to be interesting to refer to in diagnostics. + /// Currently, this is true when it's assigning to a projection, when it's assigning from + /// the return value of a call, and when it has a user-provided type annotation. + has_interesting_ty: bool, + }, /// A constraint that came from a usage of a variable (e.g. in an ADT expression /// like `Foo { field: my_val }`) Usage, diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir index 35e44b2314a50..7f4a2bbbb5c34 100644 --- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir +++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir @@ -17,8 +17,8 @@ | '?2 live at {bb1[0]} | '?3 live at {bb1[1..=3]} | '?4 live at {bb1[4..=7], bb2[0..=2]} -| '?2: '?3 due to Assignment at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:19:13: 19:18 (#0) -| '?3: '?4 due to Assignment at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:20:13: 20:14 (#0) +| '?2: '?3 due to Assignment { has_interesting_ty: false } at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:19:13: 19:18 (#0) +| '?3: '?4 due to Assignment { has_interesting_ty: false } at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:20:13: 20:14 (#0) | | Borrows | bw0: issued at bb1[0] in '?2 diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir index 6d415f42d06f3..1d80df76b3f77 100644 --- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir +++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir @@ -17,8 +17,8 @@ | '?2 live at {bb1[0]} | '?3 live at {bb1[1..=3]} | '?4 live at {bb1[4..=7], bb2[0..=2]} -| '?2: '?3 due to Assignment at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:19:13: 19:18 (#0) -| '?3: '?4 due to Assignment at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:20:13: 20:14 (#0) +| '?2: '?3 due to Assignment { has_interesting_ty: false } at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:19:13: 19:18 (#0) +| '?3: '?4 due to Assignment { has_interesting_ty: false } at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:20:13: 20:14 (#0) | | Borrows | bw0: issued at bb1[0] in '?2 diff --git a/tests/mir-opt/storage_ranges.main.nll.0.mir b/tests/mir-opt/storage_ranges.main.nll.0.mir index ae8cd0c894dac..291e3bbc87354 100644 --- a/tests/mir-opt/storage_ranges.main.nll.0.mir +++ b/tests/mir-opt/storage_ranges.main.nll.0.mir @@ -15,7 +15,7 @@ | '?1 live at {bb0[0..=22]} | '?2 live at {bb0[10]} | '?3 live at {bb0[11]} -| '?2: '?3 due to Assignment at Single(bb0[10]) ($DIR/storage_ranges.rs:7:17: 7:25 (#0) +| '?2: '?3 due to Assignment { has_interesting_ty: false } at Single(bb0[10]) ($DIR/storage_ranges.rs:7:17: 7:25 (#0) | | Borrows | bw0: issued at bb0[10] in '?2 diff --git a/tests/ui/fn/fn_def_coercion.rs b/tests/ui/fn/fn_def_coercion.rs index 31c8fa41de17c..313be6f28cdcc 100644 --- a/tests/ui/fn/fn_def_coercion.rs +++ b/tests/ui/fn/fn_def_coercion.rs @@ -46,12 +46,12 @@ fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { let x = match true { - true => foo::<&'c ()>, //~ ERROR lifetime may not live long enough + true => foo::<&'c ()>, false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough }; x(a); - x(b); + x(b); //~ ERROR lifetime may not live long enough x(c); } diff --git a/tests/ui/fn/fn_def_coercion.stderr b/tests/ui/fn/fn_def_coercion.stderr index c2776887b79d4..ec4a1bde7fd61 100644 --- a/tests/ui/fn/fn_def_coercion.stderr +++ b/tests/ui/fn/fn_def_coercion.stderr @@ -6,9 +6,9 @@ LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | | | lifetime `'a` defined here LL | let mut x = foo::<&'a ()>; - | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -22,9 +22,9 @@ LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here LL | let mut x = foo::<&'a ()>; LL | x = foo::<&'b ()>; - | ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -53,9 +53,9 @@ LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here LL | let mut x = foo::<&'c ()>; LL | x = foo::<&'b ()>; - | ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -69,9 +69,9 @@ LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here ... LL | x = foo::<&'a ()>; - | ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -89,9 +89,9 @@ LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here LL | let x = match true { LL | true => foo::<&'b ()>, - | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -105,9 +105,9 @@ LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here ... LL | false => foo::<&'a ()>, - | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -117,15 +117,15 @@ help: `'a` and `'b` must be the same: replace one with the other = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: lifetime may not live long enough - --> $DIR/fn_def_coercion.rs:49:17 + --> $DIR/fn_def_coercion.rs:50:18 | LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | -- -- lifetime `'c` defined here | | | lifetime `'a` defined here -LL | let x = match true { -LL | true => foo::<&'c ()>, - | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c` +... +LL | false => foo::<&'a ()>, + | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c` | = help: consider adding the following bound: `'a: 'c` = note: requirement occurs because of a function pointer to `foo` @@ -133,20 +133,17 @@ LL | true => foo::<&'c ()>, = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/fn_def_coercion.rs:50:18 + --> $DIR/fn_def_coercion.rs:54:5 | LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here ... -LL | false => foo::<&'a ()>, - | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` +LL | x(b); + | ^^^^ argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` - = note: requirement occurs because of a function pointer to `foo` - = note: the function `foo` is invariant over the parameter `T` - = help: see for more information about variance help: the following changes may resolve your lifetime errors | diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs index 66e6eb91a22e3..09ee9accccd2f 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.rs @@ -1,6 +1,6 @@ fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) { - //~^ ERROR lifetime may not live long enough *v = x; + //~^ ERROR lifetime may not live long enough } fn main() { } diff --git a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr index e7cab52084ddd..30083b5ef5462 100644 --- a/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr +++ b/tests/ui/lifetimes/lifetime-errors/ex3-both-anon-regions-2.stderr @@ -1,15 +1,13 @@ error: lifetime may not live long enough - --> $DIR/ex3-both-anon-regions-2.rs:1:14 + --> $DIR/ex3-both-anon-regions-2.rs:2:5 | LL | fn foo(&mut (ref mut v, w): &mut (&u8, &u8), x: &u8) { - | ^^^^^^^^^ - - let's call the lifetime of this reference `'1` - | | | - | | let's call the lifetime of this reference `'2` - | assignment requires that `'1` must outlive `'2` + | - - let's call the lifetime of this reference `'1` + | | + | let's call the lifetime of this reference `'2` +LL | *v = x; + | ^^^^^^ assignment requires that `'1` must outlive `'2` | - = note: requirement occurs because of a mutable reference to `&u8` - = note: mutable references are invariant over their type parameter - = help: see for more information about variance help: consider introducing a named lifetime parameter | LL | fn foo<'a>(&mut (ref mut v, w): &mut (&'a u8, &u8), x: &'a u8) { diff --git a/tests/ui/match/match-ref-mut-invariance.stderr b/tests/ui/match/match-ref-mut-invariance.stderr index 93844d34b414b..b9878a1953242 100644 --- a/tests/ui/match/match-ref-mut-invariance.stderr +++ b/tests/ui/match/match-ref-mut-invariance.stderr @@ -1,12 +1,12 @@ error: lifetime may not live long enough - --> $DIR/match-ref-mut-invariance.rs:10:24 + --> $DIR/match-ref-mut-invariance.rs:10:9 | LL | impl<'b> S<'b> { | -- lifetime `'b` defined here LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { | -- lifetime `'a` defined here LL | match self.0 { ref mut x => x } - | ^^^^^^^^^ assignment requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ method was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a mutable reference to `&i32` diff --git a/tests/ui/match/match-ref-mut-let-invariance.rs b/tests/ui/match/match-ref-mut-let-invariance.rs index 2c1f865b6d750..a33be09ac8be2 100644 --- a/tests/ui/match/match-ref-mut-let-invariance.rs +++ b/tests/ui/match/match-ref-mut-let-invariance.rs @@ -8,8 +8,8 @@ struct S<'b>(&'b i32); impl<'b> S<'b> { fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { let ref mut x = self.0; - //~^ ERROR lifetime may not live long enough x + //~^ ERROR lifetime may not live long enough } } diff --git a/tests/ui/match/match-ref-mut-let-invariance.stderr b/tests/ui/match/match-ref-mut-let-invariance.stderr index 3c5d73bb4f724..27968239a8e54 100644 --- a/tests/ui/match/match-ref-mut-let-invariance.stderr +++ b/tests/ui/match/match-ref-mut-let-invariance.stderr @@ -1,12 +1,13 @@ error: lifetime may not live long enough - --> $DIR/match-ref-mut-let-invariance.rs:10:13 + --> $DIR/match-ref-mut-let-invariance.rs:11:9 | LL | impl<'b> S<'b> { | -- lifetime `'b` defined here LL | fn bar<'a>(&'a mut self) -> &'a mut &'a i32 { | -- lifetime `'a` defined here LL | let ref mut x = self.0; - | ^^^^^^^^^ assignment requires that `'a` must outlive `'b` +LL | x + | ^ method was supposed to return data with lifetime `'b` but it is returning data with lifetime `'a` | = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a mutable reference to `&i32` diff --git a/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr index 1478ad1431ba4..2084697e7e26d 100644 --- a/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr +++ b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr @@ -4,9 +4,11 @@ error[E0597]: `c` does not live long enough LL | let c = 66; | - binding `c` declared here LL | let f = SomeStruct::<&'static u32>; - | -------------------------- assignment requires that `c` is borrowed for `'static` LL | f(&c); - | ^^ borrowed value does not live long enough + | --^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'static` LL | } | - `c` dropped here while still borrowed @@ -18,9 +20,11 @@ LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { LL | let c = 66; | - binding `c` declared here LL | let f = SomeStruct::<&'a u32>; - | --------------------- assignment requires that `c` is borrowed for `'a` LL | f(&c); - | ^^ borrowed value does not live long enough + | --^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` LL | } | - `c` dropped here while still borrowed @@ -33,9 +37,11 @@ LL | let _closure = || { LL | let c = 66; | - binding `c` declared here LL | let f = SomeStruct::<&'a u32>; - | --------------------- assignment requires that `c` is borrowed for `'a` LL | f(&c); - | ^^ borrowed value does not live long enough + | --^^- + | | | + | | borrowed value does not live long enough + | argument requires that `c` is borrowed for `'a` LL | }; | - `c` dropped here while still borrowed diff --git a/tests/ui/nll/user-annotations/method-ufcs-1.stderr b/tests/ui/nll/user-annotations/method-ufcs-1.stderr index 087e270c70f7d..c42ea0172cf75 100644 --- a/tests/ui/nll/user-annotations/method-ufcs-1.stderr +++ b/tests/ui/nll/user-annotations/method-ufcs-1.stderr @@ -4,10 +4,11 @@ error[E0597]: `a` does not live long enough LL | let a = 22; | - binding `a` declared here ... -LL | let x = <&'static u32 as Bazoom<_>>::method; - | ----------------------------------- assignment requires that `a` is borrowed for `'static` LL | x(&a, b, c); - | ^^ borrowed value does not live long enough + | --^^------- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'static` LL | } | - `a` dropped here while still borrowed diff --git a/tests/ui/nll/user-annotations/method-ufcs-2.stderr b/tests/ui/nll/user-annotations/method-ufcs-2.stderr index c89bed3b1b18f..287337c7d52d3 100644 --- a/tests/ui/nll/user-annotations/method-ufcs-2.stderr +++ b/tests/ui/nll/user-annotations/method-ufcs-2.stderr @@ -4,10 +4,11 @@ error[E0597]: `a` does not live long enough LL | let a = 22; | - binding `a` declared here ... -LL | let x = <&'static u32 as Bazoom<_>>::method; - | ----------------------------------- assignment requires that `a` is borrowed for `'static` LL | x(&a, b, c); - | ^^ borrowed value does not live long enough + | --^^------- + | | | + | | borrowed value does not live long enough + | argument requires that `a` is borrowed for `'static` LL | } | - `a` dropped here while still borrowed diff --git a/tests/ui/nll/user-annotations/promoted-annotation.stderr b/tests/ui/nll/user-annotations/promoted-annotation.stderr index ca99e53187091..39993475796f5 100644 --- a/tests/ui/nll/user-annotations/promoted-annotation.stderr +++ b/tests/ui/nll/user-annotations/promoted-annotation.stderr @@ -6,9 +6,11 @@ LL | fn foo<'a>() { LL | let x = 0; | - binding `x` declared here LL | let f = &drop::<&'a i32>; - | ---------------- assignment requires that `x` is borrowed for `'a` LL | f(&x); - | ^^ borrowed value does not live long enough + | --^^- + | | | + | | borrowed value does not live long enough + | argument requires that `x` is borrowed for `'a` LL | LL | } | - `x` dropped here while still borrowed From 45b2ae935dbc9feb18e9cb9f87ae04d5978e1669 Mon Sep 17 00:00:00 2001 From: dianne Date: Thu, 19 Dec 2024 11:12:31 -0800 Subject: [PATCH 07/12] remove the unused `ConstraintCategory::ClosureBounds` --- compiler/rustc_borrowck/src/diagnostics/region_errors.rs | 1 - compiler/rustc_middle/src/mir/query.rs | 5 ----- 2 files changed, 6 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 78809908180ac..3e90ecbaf5b4e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -50,7 +50,6 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { ConstraintCategory::Cast { is_implicit_coercion: true, .. } => "coercion ", ConstraintCategory::CallArgument(_) => "argument ", ConstraintCategory::TypeAnnotation => "type annotation ", - ConstraintCategory::ClosureBounds => "closure body ", ConstraintCategory::SizedBound => "proving this value is `Sized` ", ConstraintCategory::CopyBound => "copying this value ", ConstraintCategory::OpaqueType => "opaque type ", diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index c2bb95a91c47e..9943914628ea6 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -241,11 +241,6 @@ pub enum ConstraintCategory<'tcx> { unsize_to: Option>, }, - /// A constraint that came from checking the body of a closure. - /// - /// We try to get the category that the closure used when reporting this. - ClosureBounds, - /// Contains the function type if available. CallArgument(#[derive_where(skip)] Option>), CopyBound, From 6421d4cf801491bb4bf3f796ec45a3f65c1a0364 Mon Sep 17 00:00:00 2001 From: dianne Date: Thu, 19 Dec 2024 23:19:24 -0800 Subject: [PATCH 08/12] `best_blame_constraint`: prioritize blaming interesting-seeming constraints --- Cargo.lock | 1 - .../rustc_borrowck/src/region_infer/mod.rs | 159 ++++++++++-------- compiler/rustc_middle/Cargo.toml | 1 - compiler/rustc_middle/src/mir/query.rs | 7 +- ...-trait-obj-different-regions-lt-ext.stderr | 2 +- ...to-trait-obj-different-regions-misc.stderr | 20 ++- tests/ui/fn/fn_def_coercion.rs | 4 +- tests/ui/fn/fn_def_coercion.stderr | 32 ++-- tests/ui/issues/issue-15034.stderr | 4 +- tests/ui/lifetimes/copy_modulo_regions.stderr | 6 +- .../nll/issue-54779-anon-static-lifetime.rs | 2 +- .../issue-54779-anon-static-lifetime.stderr | 14 +- ...98589-closures-relate-named-regions.stderr | 4 +- ...insensitive-scopes-issue-117146.nll.stderr | 35 ++-- ...sitive-scopes-issue-117146.polonius.stderr | 35 ++-- ...ocation-insensitive-scopes-issue-117146.rs | 4 +- .../nll/type-check-pointer-comparisons.stderr | 24 +-- ...t-static-bound-needing-more-suggestions.rs | 2 +- ...atic-bound-needing-more-suggestions.stderr | 25 ++- .../variance-contravariant-arg-object.stderr | 2 +- .../variance-covariant-arg-object.stderr | 2 +- .../variance-invariant-arg-object.stderr | 2 +- 22 files changed, 210 insertions(+), 177 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index fca4469803b4f..c525901869b15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4118,7 +4118,6 @@ name = "rustc_middle" version = "0.0.0" dependencies = [ "bitflags", - "derive-where", "either", "field-offset", "gsgdt", diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 7e8fad8698aef..7b4e82fa31010 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -2026,87 +2026,102 @@ impl<'tcx> RegionInferenceContext<'tcx> { | NllRegionVariableOrigin::Existential { from_forall: true } => false, }; - let interesting_to_blame = |constraint: &OutlivesConstraint<'tcx>| { - !matches!( - constraint.category, - ConstraintCategory::OpaqueType - | ConstraintCategory::Boring - | ConstraintCategory::BoringNoLocation - | ConstraintCategory::Internal - | ConstraintCategory::Predicate(_) - | ConstraintCategory::Assignment { has_interesting_ty: false } - ) && constraint.span.desugaring_kind().is_none_or(|kind| { - // Try to avoid blaming constraints from desugarings, since they may not clearly - // clearly match what users have written. As an exception, allow blaming returns - // generated by `?` desugaring, since the correspondence is fairly clear. - kind == DesugaringKind::QuestionMark - && matches!(constraint.category, ConstraintCategory::Return(_)) - }) + // To pick a constraint to blame, we organize constraints by how interesting we expect them + // to be in diagnostics, then pick the most interesting one closest to either the source or + // the target on our constraint path. + let constraint_interest = |constraint: &OutlivesConstraint<'tcx>| { + // Try to avoid blaming constraints from desugarings, since they may not clearly match + // match what users have written. As an exception, allow blaming returns generated by + // `?` desugaring, since the correspondence is fairly clear. + let category = if let Some(kind) = constraint.span.desugaring_kind() + && (kind != DesugaringKind::QuestionMark + || !matches!(constraint.category, ConstraintCategory::Return(_))) + { + ConstraintCategory::Boring + } else { + constraint.category + }; + + match category { + // Returns usually provide a type to blame and have specially written diagnostics, + // so prioritize them. + ConstraintCategory::Return(_) => 0, + // Unsizing coercions are interesting, since we have a note for that: + // `BorrowExplanation::add_object_lifetime_default_note`. + // FIXME(dianne): That note shouldn't depend on a coercion being blamed; see issue + // #131008 for an example of where we currently don't emit it but should. + // Once the note is handled properly, this case should be removed. Until then, it + // should be as limited as possible; the note is prone to false positives and this + // constraint usually isn't best to blame. + ConstraintCategory::Cast { + unsize_to: Some(unsize_ty), + is_implicit_coercion: true, + } if target_region == self.universal_regions().fr_static + // Mirror the note's condition, to minimize how often this diverts blame. + && let ty::Adt(_, args) = unsize_ty.kind() + && args.iter().any(|arg| arg.as_type().is_some_and(|ty| ty.is_trait())) + // Mimic old logic for this, to minimize false positives in tests. + && !path + .iter() + .any(|c| matches!(c.category, ConstraintCategory::TypeAnnotation)) => + { + 1 + } + // Between other interesting constraints, order by their position on the `path`. + ConstraintCategory::Yield + | ConstraintCategory::UseAsConst + | ConstraintCategory::UseAsStatic + | ConstraintCategory::TypeAnnotation + | ConstraintCategory::Cast { .. } + | ConstraintCategory::CallArgument(_) + | ConstraintCategory::CopyBound + | ConstraintCategory::SizedBound + | ConstraintCategory::Assignment { has_interesting_ty: true } + | ConstraintCategory::Usage + | ConstraintCategory::ClosureUpvar(_) => 2, + // Give assignments a lower priority when flagged as less likely to be interesting. + // In particular, de-prioritize MIR assignments lowered from argument patterns. + ConstraintCategory::Assignment { has_interesting_ty: false } => 3, + // We handle predicates and opaque types specially; don't prioritize them here. + ConstraintCategory::Predicate(_) | ConstraintCategory::OpaqueType => 4, + // `Boring` constraints can correspond to user-written code and have useful spans, + // but don't provide any other useful information for diagnostics. + ConstraintCategory::Boring => 5, + // `BoringNoLocation` constraints can point to user-written code, but are less + // specific, and are not used for relations that would make sense to blame. + ConstraintCategory::BoringNoLocation => 6, + // Do not blame internal constraints. + ConstraintCategory::Internal => 7, + ConstraintCategory::IllegalUniverse => 8, + } }; let best_choice = if blame_source { - path.iter().rposition(interesting_to_blame) + path.iter().enumerate().rev().min_by_key(|(_, c)| constraint_interest(c)).unwrap().0 } else { - path.iter().position(interesting_to_blame) + path.iter().enumerate().min_by_key(|(_, c)| constraint_interest(c)).unwrap().0 }; debug!(?best_choice, ?blame_source); - let best_constraint = match best_choice { - Some(i) - if let Some(next) = path.get(i + 1) - && matches!(path[i].category, ConstraintCategory::Return(_)) - && next.category == ConstraintCategory::OpaqueType => - { - // The return expression is being influenced by the return type being - // impl Trait, point at the return type and not the return expr. - *next - } - - Some(i) - if path[i].category == ConstraintCategory::Return(ReturnConstraint::Normal) - && let Some(field) = path.iter().find_map(|p| { - if let ConstraintCategory::ClosureUpvar(f) = p.category { - Some(f) - } else { - None - } - }) => - { - OutlivesConstraint { - category: ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field)), - ..path[i] - } - } - - Some(_) - if target_region == self.universal_regions().fr_static - && let Some(old_best) = path.iter().min_by_key(|p| p.category) - && matches!(old_best.category, ConstraintCategory::Cast { - is_implicit_coercion: true, - unsize_to: Some(_) - }) => - { - // FIXME(dianne): This is a hack in order to emit the subdiagnostic - // `BorrowExplanation::add_object_lifetime_default_note` more often, e.g. on - // `tests/ui/traits/trait-object-lifetime-default-note.rs`. The subdiagnostic - // depends on a coercion being blamed, so we fall back to an earlier version of this - // function's blaming logic to keep the test result the same. A proper fix will - // require rewriting the subdiagnostic not to rely on a coercion being blamed. - // For examples of where notes are missing, see #131008 and - // `tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs`. - // As part of fixing those, this case should be removed. - *old_best - } - - Some(i) => path[i], - - None => { - // If that search fails, the only constraints on the path are those that we try not - // to blame. In that case, find what appears to be the most interesting point to - // report to the user via an even more ad-hoc guess. - *path.iter().min_by_key(|p| p.category).unwrap() + let best_constraint = if let Some(next) = path.get(best_choice + 1) + && matches!(path[best_choice].category, ConstraintCategory::Return(_)) + && next.category == ConstraintCategory::OpaqueType + { + // The return expression is being influenced by the return type being + // impl Trait, point at the return type and not the return expr. + *next + } else if path[best_choice].category == ConstraintCategory::Return(ReturnConstraint::Normal) + && let Some(field) = path.iter().find_map(|p| { + if let ConstraintCategory::ClosureUpvar(f) = p.category { Some(f) } else { None } + }) + { + OutlivesConstraint { + category: ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field)), + ..path[best_choice] } + } else { + path[best_choice] }; let blame_constraint = BlameConstraint { diff --git a/compiler/rustc_middle/Cargo.toml b/compiler/rustc_middle/Cargo.toml index e64500f812a1d..2c34df6ea61a3 100644 --- a/compiler/rustc_middle/Cargo.toml +++ b/compiler/rustc_middle/Cargo.toml @@ -6,7 +6,6 @@ edition = "2021" [dependencies] # tidy-alphabetical-start bitflags = "2.4.1" -derive-where = "1.2.7" either = "1.5.0" field-offset = "0.3.5" gsgdt = "0.1.2" diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 9943914628ea6..8ab994a2dad6c 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -3,7 +3,6 @@ use std::cell::Cell; use std::fmt::{self, Debug}; -use derive_where::derive_where; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; @@ -225,7 +224,6 @@ rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16); /// See also `rustc_const_eval::borrow_check::constraints`. #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] -#[derive_where(PartialOrd, Ord)] pub enum ConstraintCategory<'tcx> { Return(ReturnConstraint), Yield, @@ -237,12 +235,11 @@ pub enum ConstraintCategory<'tcx> { is_implicit_coercion: bool, /// Whether this is an unsizing coercion and if yes, this contains the target type. /// Region variables are erased to ReErased. - #[derive_where(skip)] unsize_to: Option>, }, /// Contains the function type if available. - CallArgument(#[derive_where(skip)] Option>), + CallArgument(Option>), CopyBound, SizedBound, Assignment { @@ -276,7 +273,7 @@ pub enum ConstraintCategory<'tcx> { IllegalUniverse, } -#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] pub enum ReturnConstraint { Normal, diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr index ed9ebce4832c2..b7319e3356bd0 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-lt-ext.stderr @@ -4,7 +4,7 @@ error: lifetime may not live long enough LL | fn bad_cast<'a>(x: *const dyn Static<'static>) -> *const dyn Static<'a> { | -- lifetime `'a` defined here LL | x as _ - | ^^^^^^ cast requires that `'a` must outlive `'static` + | ^^^^^^ returning this value requires that `'a` must outlive `'static` error: aborting due to 1 previous error diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr index 6eeaeb120a729..faaa6325f3495 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr @@ -6,9 +6,12 @@ LL | fn change_lt<'a, 'b>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> { | | | lifetime `'a` defined here LL | x as _ - | ^^^^^^ cast requires that `'b` must outlive `'a` + | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable pointer to `dyn Trait<'_>` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:6:5 @@ -35,9 +38,12 @@ LL | fn change_lt_ab<'a: 'b, 'b>(x: *mut dyn Trait<'a>) -> *mut dyn Trait<'b> { | | | lifetime `'a` defined here LL | x as _ - | ^^^^^^ cast requires that `'b` must outlive `'a` + | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable pointer to `dyn Trait<'_>` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:15:5 @@ -85,9 +91,12 @@ LL | fn change_assoc_0<'a, 'b>( | lifetime `'a` defined here ... LL | x as _ - | ^^^^^^ cast requires that `'b` must outlive `'a` + | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable pointer to `dyn Assocked` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:31:5 @@ -118,9 +127,12 @@ LL | fn change_assoc_1<'a, 'b>( | lifetime `'a` defined here ... LL | x as _ - | ^^^^^^ cast requires that `'b` must outlive `'a` + | ^^^^^^ function was supposed to return data with lifetime `'a` but it is returning data with lifetime `'b` | = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a mutable pointer to `dyn Assocked>` + = note: mutable pointers are invariant over their type parameter + = help: see for more information about variance error: lifetime may not live long enough --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:38:5 diff --git a/tests/ui/fn/fn_def_coercion.rs b/tests/ui/fn/fn_def_coercion.rs index 313be6f28cdcc..eea9e480827fb 100644 --- a/tests/ui/fn/fn_def_coercion.rs +++ b/tests/ui/fn/fn_def_coercion.rs @@ -46,8 +46,8 @@ fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { let x = match true { - true => foo::<&'c ()>, - false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough + true => foo::<&'c ()>, //~ ERROR lifetime may not live long enough + false => foo::<&'a ()>, }; x(a); diff --git a/tests/ui/fn/fn_def_coercion.stderr b/tests/ui/fn/fn_def_coercion.stderr index ec4a1bde7fd61..a4dc72310815b 100644 --- a/tests/ui/fn/fn_def_coercion.stderr +++ b/tests/ui/fn/fn_def_coercion.stderr @@ -6,9 +6,9 @@ LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | | | lifetime `'a` defined here LL | let mut x = foo::<&'a ()>; - | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -22,9 +22,9 @@ LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here LL | let mut x = foo::<&'a ()>; LL | x = foo::<&'b ()>; - | ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -53,9 +53,9 @@ LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here LL | let mut x = foo::<&'c ()>; LL | x = foo::<&'b ()>; - | ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -69,9 +69,9 @@ LL | fn i<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here ... LL | x = foo::<&'a ()>; - | ^^^^^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -89,9 +89,9 @@ LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here LL | let x = match true { LL | true => foo::<&'b ()>, - | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -105,9 +105,9 @@ LL | fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | lifetime `'a` defined here ... LL | false => foo::<&'a ()>, - | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'b` + | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a function pointer to `foo` = note: the function `foo` is invariant over the parameter `T` = help: see for more information about variance @@ -117,15 +117,15 @@ help: `'a` and `'b` must be the same: replace one with the other = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: lifetime may not live long enough - --> $DIR/fn_def_coercion.rs:50:18 + --> $DIR/fn_def_coercion.rs:49:17 | LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | -- -- lifetime `'c` defined here | | | lifetime `'a` defined here -... -LL | false => foo::<&'a ()>, - | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c` +LL | let x = match true { +LL | true => foo::<&'c ()>, + | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c` | = help: consider adding the following bound: `'a: 'c` = note: requirement occurs because of a function pointer to `foo` diff --git a/tests/ui/issues/issue-15034.stderr b/tests/ui/issues/issue-15034.stderr index c5bc31f94d981..587a5c85e924a 100644 --- a/tests/ui/issues/issue-15034.stderr +++ b/tests/ui/issues/issue-15034.stderr @@ -1,10 +1,10 @@ error[E0621]: explicit lifetime required in the type of `lexer` - --> $DIR/issue-15034.rs:17:25 + --> $DIR/issue-15034.rs:17:9 | LL | pub fn new(lexer: &'a mut Lexer) -> Parser<'a> { | ------------- help: add explicit lifetime `'a` to the type of `lexer`: `&'a mut Lexer<'a>` LL | Parser { lexer: lexer } - | ^^^^^ lifetime `'a` required + | ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/copy_modulo_regions.stderr b/tests/ui/lifetimes/copy_modulo_regions.stderr index 920fec09103b2..310ddb21647f6 100644 --- a/tests/ui/lifetimes/copy_modulo_regions.stderr +++ b/tests/ui/lifetimes/copy_modulo_regions.stderr @@ -4,7 +4,11 @@ error: lifetime may not live long enough LL | fn foo<'a>() -> [Foo<'a>; 100] { | -- lifetime `'a` defined here LL | [mk_foo::<'a>(); 100] - | ^^^^^^^^^^^^^^^^^^^^^ copying this value requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | + = note: requirement occurs because of the type `Foo<'_>`, which makes the generic argument `'_` invariant + = note: the struct `Foo<'a>` is invariant over the parameter `'a` + = help: see for more information about variance error: aborting due to 1 previous error diff --git a/tests/ui/nll/issue-54779-anon-static-lifetime.rs b/tests/ui/nll/issue-54779-anon-static-lifetime.rs index 1dab7c1712afe..6b8fa608ebbb2 100644 --- a/tests/ui/nll/issue-54779-anon-static-lifetime.rs +++ b/tests/ui/nll/issue-54779-anon-static-lifetime.rs @@ -29,7 +29,7 @@ impl DebugWith for Foo { fmt: &mut std::fmt::Formatter<'_>, ) -> std::fmt::Result { let Foo { bar } = self; - bar.debug_with(cx); //~ lifetime may not live long enough + bar.debug_with(cx); //~ borrowed data escapes outside of method Ok(()) } } diff --git a/tests/ui/nll/issue-54779-anon-static-lifetime.stderr b/tests/ui/nll/issue-54779-anon-static-lifetime.stderr index a454ed265685c..03a5590661422 100644 --- a/tests/ui/nll/issue-54779-anon-static-lifetime.stderr +++ b/tests/ui/nll/issue-54779-anon-static-lifetime.stderr @@ -1,11 +1,17 @@ -error: lifetime may not live long enough - --> $DIR/issue-54779-anon-static-lifetime.rs:32:24 +error[E0521]: borrowed data escapes outside of method + --> $DIR/issue-54779-anon-static-lifetime.rs:32:9 | LL | cx: &dyn DebugContext, - | - let's call the lifetime of this reference `'1` + | -- - let's call the lifetime of this reference `'1` + | | + | `cx` is a reference that is only valid in the method body ... LL | bar.debug_with(cx); - | ^^ coercion requires that `'1` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^ + | | + | `cx` escapes the method body here + | argument requires that `'1` must outlive `'static` error: aborting due to 1 previous error +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr b/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr index 4e741abc2dcf2..4f244b54bd07b 100644 --- a/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr +++ b/tests/ui/nll/issue-98589-closures-relate-named-regions.stderr @@ -11,14 +11,14 @@ LL | || { None::<&'a &'b ()>; }; = help: consider adding the following bound: `'b: 'a` error: lifetime may not live long enough - --> $DIR/issue-98589-closures-relate-named-regions.rs:15:10 + --> $DIR/issue-98589-closures-relate-named-regions.rs:15:5 | LL | fn test_early_late<'a: 'a, 'b>() { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here LL | || { None::<&'a &'b ()>; }; - | ^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr index e4b323bc2b6ac..1d086c658dfcd 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr @@ -1,20 +1,23 @@ -error[E0373]: closure may outlive the current function, but it borrows `a`, which is owned by the current function - --> $DIR/location-insensitive-scopes-issue-117146.rs:10:13 +error[E0597]: `a` does not live long enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:10:18 | +LL | let a = (); + | - binding `a` declared here LL | let b = |_| &a; - | ^^^ - `a` is borrowed here - | | - | may outlive borrowed value `a` - | -note: function requires argument type to outlive `'static` - --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 - | -LL | bad(&b); - | ^^^^^^^ -help: to force the closure to take ownership of `a` (and any other referenced variables), use the `move` keyword - | -LL | let b = move |_| &a; - | ++++ + | --- -^ + | | || + | | |borrowed value does not live long enough + | | returning this value requires that `a` is borrowed for `'static` + | value captured here +... +LL | } + | - `a` dropped here while still borrowed + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/location-insensitive-scopes-issue-117146.rs:20:22 + | +LL | fn bad &()>(_: F) {} + | ^^^ error: implementation of `Fn` is not general enough --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 @@ -36,4 +39,4 @@ LL | bad(&b); error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0373`. +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr index e4b323bc2b6ac..1d086c658dfcd 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr @@ -1,20 +1,23 @@ -error[E0373]: closure may outlive the current function, but it borrows `a`, which is owned by the current function - --> $DIR/location-insensitive-scopes-issue-117146.rs:10:13 +error[E0597]: `a` does not live long enough + --> $DIR/location-insensitive-scopes-issue-117146.rs:10:18 | +LL | let a = (); + | - binding `a` declared here LL | let b = |_| &a; - | ^^^ - `a` is borrowed here - | | - | may outlive borrowed value `a` - | -note: function requires argument type to outlive `'static` - --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 - | -LL | bad(&b); - | ^^^^^^^ -help: to force the closure to take ownership of `a` (and any other referenced variables), use the `move` keyword - | -LL | let b = move |_| &a; - | ++++ + | --- -^ + | | || + | | |borrowed value does not live long enough + | | returning this value requires that `a` is borrowed for `'static` + | value captured here +... +LL | } + | - `a` dropped here while still borrowed + | +note: due to current limitations in the borrow checker, this implies a `'static` lifetime + --> $DIR/location-insensitive-scopes-issue-117146.rs:20:22 + | +LL | fn bad &()>(_: F) {} + | ^^^ error: implementation of `Fn` is not general enough --> $DIR/location-insensitive-scopes-issue-117146.rs:13:5 @@ -36,4 +39,4 @@ LL | bad(&b); error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0373`. +For more information about this error, try `rustc --explain E0597`. diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs index bd26af5bee25c..c828a37521e0e 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.rs @@ -8,8 +8,8 @@ fn main() { let a = (); let b = |_| &a; - //[nll]~^ ERROR closure may outlive the current function, but it borrows `a` - //[polonius]~^^ ERROR closure may outlive the current function, but it borrows `a` + //[nll]~^ ERROR `a` does not live long enough + //[polonius]~^^ ERROR `a` does not live long enough bad(&b); //[nll]~^ ERROR implementation of `Fn` //[nll]~| ERROR implementation of `FnOnce` diff --git a/tests/ui/nll/type-check-pointer-comparisons.stderr b/tests/ui/nll/type-check-pointer-comparisons.stderr index 37098b585dfea..90cdb92e81b26 100644 --- a/tests/ui/nll/type-check-pointer-comparisons.stderr +++ b/tests/ui/nll/type-check-pointer-comparisons.stderr @@ -6,9 +6,9 @@ LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) { | | | lifetime `'a` defined here LL | x == y; - | ^ requires that `'a` must outlive `'b` + | ^ requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a mutable reference to `&i32` = note: mutable references are invariant over their type parameter = help: see for more information about variance @@ -21,9 +21,9 @@ LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) { | | | lifetime `'a` defined here LL | x == y; - | ^ requires that `'b` must outlive `'a` + | ^ requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a mutable reference to `&i32` = note: mutable references are invariant over their type parameter = help: see for more information about variance @@ -38,9 +38,9 @@ LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) { | | | lifetime `'a` defined here LL | x == y; - | ^ requires that `'a` must outlive `'b` + | ^ requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a mutable pointer to `&i32` = note: mutable pointers are invariant over their type parameter = help: see for more information about variance @@ -53,9 +53,9 @@ LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) { | | | lifetime `'a` defined here LL | x == y; - | ^ requires that `'b` must outlive `'a` + | ^ requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a mutable pointer to `&i32` = note: mutable pointers are invariant over their type parameter = help: see for more information about variance @@ -72,9 +72,9 @@ LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32 | | | lifetime `'a` defined here LL | f == g; - | ^ requires that `'a` must outlive `'b` + | ^ requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a mutable reference to `&i32` = note: mutable references are invariant over their type parameter = help: see for more information about variance @@ -87,9 +87,9 @@ LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32 | | | lifetime `'a` defined here LL | f == g; - | ^ requires that `'b` must outlive `'a` + | ^ requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a mutable reference to `&i32` = note: mutable references are invariant over their type parameter = help: see for more information about variance diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs index 8f3171222bb6f..c24672816acdb 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs @@ -64,7 +64,7 @@ mod bay { fn use_it<'a>(val: Box + 'a>) -> &'a () { val.use_self() - //~^ ERROR: `val` does not live long enough + //~^ ERROR: cannot return value referencing function parameter `val` //~| ERROR: borrowed data escapes outside of function } } diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr index a8a854220b4e5..505765d2b41f6 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr @@ -25,20 +25,6 @@ LL | val.use_self() | returns a value referencing data owned by the current function | `val` is borrowed here -error[E0597]: `val` does not live long enough - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:9 - | -LL | fn use_it<'a>(val: Box + 'a>) -> &'a () { - | --- binding `val` declared here -LL | val.use_self() - | ^^^----------- - | | - | borrowed value does not live long enough - | argument requires that `val` is borrowed for `'static` -... -LL | } - | - `val` dropped here while still borrowed - error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:9 | @@ -64,6 +50,15 @@ help: consider relaxing the implicit `'static` requirement LL | impl MyTrait for Box + '_> { | ++++ +error[E0515]: cannot return value referencing function parameter `val` + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:9 + | +LL | val.use_self() + | ---^^^^^^^^^^^ + | | + | returns a value referencing data owned by the current function + | `val` is borrowed here + error[E0515]: cannot return value referencing function parameter `val` --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:90:9 | @@ -75,5 +70,5 @@ LL | val.use_self() error: aborting due to 6 previous errors -Some errors have detailed explanations: E0515, E0521, E0597. +Some errors have detailed explanations: E0515, E0521. For more information about an error, try `rustc --explain E0515`. diff --git a/tests/ui/variance/variance-contravariant-arg-object.stderr b/tests/ui/variance/variance-contravariant-arg-object.stderr index 7d7c6cb28cdf0..ab28315e11e52 100644 --- a/tests/ui/variance/variance-contravariant-arg-object.stderr +++ b/tests/ui/variance/variance-contravariant-arg-object.stderr @@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box>) | lifetime `'min` defined here ... LL | v - | ^ coercion requires that `'min` must outlive `'max` + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` diff --git a/tests/ui/variance/variance-covariant-arg-object.stderr b/tests/ui/variance/variance-covariant-arg-object.stderr index 4e82c8e8e1b4b..51f8cb3ec750b 100644 --- a/tests/ui/variance/variance-covariant-arg-object.stderr +++ b/tests/ui/variance/variance-covariant-arg-object.stderr @@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box>) | lifetime `'min` defined here ... LL | v - | ^ coercion requires that `'min` must outlive `'max` + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` diff --git a/tests/ui/variance/variance-invariant-arg-object.stderr b/tests/ui/variance/variance-invariant-arg-object.stderr index e3969ebebcea4..9793a36be06ab 100644 --- a/tests/ui/variance/variance-invariant-arg-object.stderr +++ b/tests/ui/variance/variance-invariant-arg-object.stderr @@ -7,7 +7,7 @@ LL | fn get_min_from_max<'min, 'max>(v: Box>) | lifetime `'min` defined here ... LL | v - | ^ coercion requires that `'min` must outlive `'max` + | ^ function was supposed to return data with lifetime `'max` but it is returning data with lifetime `'min` | = help: consider adding the following bound: `'min: 'max` From 10061b3a4fea7e6268a2d4618504c4bee3ca61fb Mon Sep 17 00:00:00 2001 From: dianne Date: Fri, 20 Dec 2024 17:08:27 -0800 Subject: [PATCH 09/12] make outlives constraints from generic arguments less boring --- .../src/diagnostics/region_errors.rs | 5 ++-- .../rustc_borrowck/src/region_infer/mod.rs | 26 ++++++++++++------- compiler/rustc_borrowck/src/type_check/mod.rs | 10 +++---- compiler/rustc_middle/src/mir/query.rs | 11 +++++++- ...ied-bounds-unnorm-associated-type-2.stderr | 2 +- 5 files changed, 35 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 3e90ecbaf5b4e..51fe47f878179 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -13,7 +13,7 @@ use rustc_hir::{PolyTraitRef, TyKind, WhereBoundPredicate}; use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound}; use rustc_middle::bug; use rustc_middle::hir::place::PlaceBase; -use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; +use rustc_middle::mir::{AnnotationSource, ConstraintCategory, ReturnConstraint}; use rustc_middle::ty::{self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeVisitor}; use rustc_span::{Ident, Span, kw}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; @@ -49,7 +49,8 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { ConstraintCategory::Cast { is_implicit_coercion: false, .. } => "cast ", ConstraintCategory::Cast { is_implicit_coercion: true, .. } => "coercion ", ConstraintCategory::CallArgument(_) => "argument ", - ConstraintCategory::TypeAnnotation => "type annotation ", + ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => "generic argument ", + ConstraintCategory::TypeAnnotation(_) => "type annotation ", ConstraintCategory::SizedBound => "proving this value is `Sized` ", ConstraintCategory::CopyBound => "copying this value ", ConstraintCategory::OpaqueType => "opaque type ", diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 7b4e82fa31010..73e25cbae27ed 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -13,9 +13,9 @@ use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound, use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin}; use rustc_middle::bug; use rustc_middle::mir::{ - BasicBlock, Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureOutlivesSubjectTy, - ClosureRegionRequirements, ConstraintCategory, Local, Location, ReturnConstraint, - TerminatorKind, + AnnotationSource, BasicBlock, Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, + ClosureOutlivesSubjectTy, ClosureRegionRequirements, ConstraintCategory, Local, Location, + ReturnConstraint, TerminatorKind, }; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::fold::fold_regions; @@ -2063,7 +2063,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Mimic old logic for this, to minimize false positives in tests. && !path .iter() - .any(|c| matches!(c.category, ConstraintCategory::TypeAnnotation)) => + .any(|c| matches!(c.category, ConstraintCategory::TypeAnnotation(_))) => { 1 } @@ -2071,7 +2071,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { ConstraintCategory::Yield | ConstraintCategory::UseAsConst | ConstraintCategory::UseAsStatic - | ConstraintCategory::TypeAnnotation + | ConstraintCategory::TypeAnnotation( + AnnotationSource::Ascription + | AnnotationSource::Declaration + | AnnotationSource::OpaqueCast, + ) | ConstraintCategory::Cast { .. } | ConstraintCategory::CallArgument(_) | ConstraintCategory::CopyBound @@ -2082,17 +2086,19 @@ impl<'tcx> RegionInferenceContext<'tcx> { // Give assignments a lower priority when flagged as less likely to be interesting. // In particular, de-prioritize MIR assignments lowered from argument patterns. ConstraintCategory::Assignment { has_interesting_ty: false } => 3, + // Generic arguments are unlikely to be what relates regions together + ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => 4, // We handle predicates and opaque types specially; don't prioritize them here. - ConstraintCategory::Predicate(_) | ConstraintCategory::OpaqueType => 4, + ConstraintCategory::Predicate(_) | ConstraintCategory::OpaqueType => 5, // `Boring` constraints can correspond to user-written code and have useful spans, // but don't provide any other useful information for diagnostics. - ConstraintCategory::Boring => 5, + ConstraintCategory::Boring => 6, // `BoringNoLocation` constraints can point to user-written code, but are less // specific, and are not used for relations that would make sense to blame. - ConstraintCategory::BoringNoLocation => 6, + ConstraintCategory::BoringNoLocation => 7, // Do not blame internal constraints. - ConstraintCategory::Internal => 7, - ConstraintCategory::IllegalUniverse => 8, + ConstraintCategory::Internal => 8, + ConstraintCategory::IllegalUniverse => 9, } }; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index a436edd85d92e..d11e86aea35a7 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -298,7 +298,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { context.ambient_variance(), base_ty.ty, location.to_locations(), - ConstraintCategory::TypeAnnotation, + ConstraintCategory::TypeAnnotation(AnnotationSource::OpaqueCast), ) .unwrap(); } @@ -333,7 +333,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { ty::Invariant, &UserTypeProjection { base: annotation_index, projs: vec![] }, locations, - ConstraintCategory::Boring, + ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg), ) { let annotation = &self.typeck.user_type_annotations[annotation_index]; span_mirbug!( @@ -455,7 +455,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { ty::Invariant, user_ty, Locations::All(*span), - ConstraintCategory::TypeAnnotation, + ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration), ) { span_mirbug!( self, @@ -938,7 +938,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ty::Invariant, &UserTypeProjection { base: annotation_index, projs: vec![] }, location.to_locations(), - ConstraintCategory::Boring, + ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg), ) { let annotation = &self.user_type_annotations[annotation_index]; span_mirbug!( @@ -973,7 +973,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { *variance, projection, Locations::All(stmt.source_info.span), - ConstraintCategory::TypeAnnotation, + ConstraintCategory::TypeAnnotation(AnnotationSource::Ascription), ) { let annotation = &self.user_type_annotations[projection.base]; span_mirbug!( diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 8ab994a2dad6c..f2fbc63ee4112 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -229,7 +229,7 @@ pub enum ConstraintCategory<'tcx> { Yield, UseAsConst, UseAsStatic, - TypeAnnotation, + TypeAnnotation(AnnotationSource), Cast { /// Whether this cast is a coercion that was automatically inserted by the compiler. is_implicit_coercion: bool, @@ -280,6 +280,15 @@ pub enum ReturnConstraint { ClosureUpvar(FieldIdx), } +#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] +#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] +pub enum AnnotationSource { + Ascription, + Declaration, + OpaqueCast, + GenericArg, +} + /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing /// that must outlive some region. #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] diff --git a/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr b/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr index e57b5af82cded..85e3452fbf2ca 100644 --- a/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr +++ b/tests/ui/fn/implied-bounds-unnorm-associated-type-2.stderr @@ -6,7 +6,7 @@ LL | fn g<'a, 'b>() { | | | lifetime `'a` defined here LL | f::<'a, 'b>(()); - | ^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` + | ^^^^^^^^^^^^^^^ generic argument requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a function pointer to `f` From 2c5815b2855e74beb608e2a4985bec135c4586dd Mon Sep 17 00:00:00 2001 From: dianne Date: Fri, 20 Dec 2024 18:33:12 -0800 Subject: [PATCH 10/12] make outlives constraints from pointer comparisons less boring --- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +-- .../nll/type-check-pointer-comparisons.stderr | 30 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index d11e86aea35a7..495ec956f35a8 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -2181,7 +2181,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ty_left, common_ty, location.to_locations(), - ConstraintCategory::Boring, + ConstraintCategory::CallArgument(None), ) .unwrap_or_else(|err| { bug!("Could not equate type variable with {:?}: {:?}", ty_left, err) @@ -2190,7 +2190,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ty_right, common_ty, location.to_locations(), - ConstraintCategory::Boring, + ConstraintCategory::CallArgument(None), ) { span_mirbug!( self, diff --git a/tests/ui/nll/type-check-pointer-comparisons.stderr b/tests/ui/nll/type-check-pointer-comparisons.stderr index 90cdb92e81b26..e362dfb3c6e7a 100644 --- a/tests/ui/nll/type-check-pointer-comparisons.stderr +++ b/tests/ui/nll/type-check-pointer-comparisons.stderr @@ -6,24 +6,24 @@ LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) { | | | lifetime `'a` defined here LL | x == y; - | ^ requires that `'b` must outlive `'a` + | ^^^^^^ argument requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a mutable reference to `&i32` = note: mutable references are invariant over their type parameter = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/type-check-pointer-comparisons.rs:4:10 + --> $DIR/type-check-pointer-comparisons.rs:4:5 | LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here LL | x == y; - | ^ requires that `'a` must outlive `'b` + | ^^^^^^ argument requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a mutable reference to `&i32` = note: mutable references are invariant over their type parameter = help: see for more information about variance @@ -38,24 +38,24 @@ LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) { | | | lifetime `'a` defined here LL | x == y; - | ^ requires that `'b` must outlive `'a` + | ^^^^^^ argument requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a mutable pointer to `&i32` = note: mutable pointers are invariant over their type parameter = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/type-check-pointer-comparisons.rs:10:10 + --> $DIR/type-check-pointer-comparisons.rs:10:5 | LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here LL | x == y; - | ^ requires that `'a` must outlive `'b` + | ^^^^^^ argument requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a mutable pointer to `&i32` = note: mutable pointers are invariant over their type parameter = help: see for more information about variance @@ -72,24 +72,24 @@ LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32 | | | lifetime `'a` defined here LL | f == g; - | ^ requires that `'b` must outlive `'a` + | ^^^^^^ argument requires that `'a` must outlive `'b` | - = help: consider adding the following bound: `'b: 'a` + = help: consider adding the following bound: `'a: 'b` = note: requirement occurs because of a mutable reference to `&i32` = note: mutable references are invariant over their type parameter = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/type-check-pointer-comparisons.rs:16:10 + --> $DIR/type-check-pointer-comparisons.rs:16:5 | LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32)) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here LL | f == g; - | ^ requires that `'a` must outlive `'b` + | ^^^^^^ argument requires that `'b` must outlive `'a` | - = help: consider adding the following bound: `'a: 'b` + = help: consider adding the following bound: `'b: 'a` = note: requirement occurs because of a mutable reference to `&i32` = note: mutable references are invariant over their type parameter = help: see for more information about variance From 1b2281a49321e8a3b839dd69fce4b738e50e770a Mon Sep 17 00:00:00 2001 From: dianne Date: Fri, 20 Dec 2024 21:14:16 -0800 Subject: [PATCH 11/12] point out unblamed constraints from `Copy`/`Sized` bounds in region errors --- .../src/diagnostics/explain_borrow.rs | 1 + .../rustc_borrowck/src/diagnostics/mod.rs | 22 +++++++++++++++++++ .../src/diagnostics/region_errors.rs | 1 + .../multiple-lifetimes/error-handling.stderr | 3 +++ tests/ui/lifetimes/copy_modulo_regions.stderr | 5 ++++- 5 files changed, 31 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 860d6338a0284..48f28f3f1de95 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -331,6 +331,7 @@ impl<'tcx> BorrowExplanation<'tcx> { }; cx.add_placeholder_from_predicate_note(err, &path); + cx.add_sized_or_copy_bound_info(err, category, &path); if let ConstraintCategory::Cast { is_implicit_coercion: true, diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index c9100f23e12e7..0286ea6cd9dca 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -37,6 +37,7 @@ use super::MirBorrowckCtxt; use super::borrow_set::BorrowData; use crate::constraints::OutlivesConstraint; use crate::fluent_generated as fluent; +use crate::nll::ConstraintDescription; use crate::session_diagnostics::{ CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause, CaptureVarKind, CaptureVarPathUseCause, OnClosureNote, @@ -647,6 +648,27 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { err.span_note(span, "due to current limitations in the borrow checker, this implies a `'static` lifetime"); } } + + /// Add a label to region errors and borrow explanations when outlives constraints arise from + /// proving a type implements `Sized` or `Copy`. + fn add_sized_or_copy_bound_info( + &self, + err: &mut Diag<'_>, + blamed_category: ConstraintCategory<'tcx>, + path: &[OutlivesConstraint<'tcx>], + ) { + for sought_category in [ConstraintCategory::SizedBound, ConstraintCategory::CopyBound] { + if sought_category != blamed_category + && let Some(sought_constraint) = path.iter().find(|c| c.category == sought_category) + { + let label = format!( + "requirement occurs due to {}", + sought_category.description().trim_end() + ); + err.span_label(sought_constraint.span, label); + } + } + } } /// The span(s) associated to a use of a place. diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 51fe47f878179..051778dcace80 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -554,6 +554,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { } self.add_placeholder_from_predicate_note(&mut diag, &path); + self.add_sized_or_copy_bound_info(&mut diag, category, &path); self.buffer_error(diag); } diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr b/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr index 00709ee7438a7..945fb0fc618fb 100644 --- a/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr +++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr @@ -6,6 +6,9 @@ LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> { | | | lifetime `'a` defined here ... +LL | let u = v; + | - requirement occurs due to copying this value +... LL | let _: &'b i32 = *u.0; | ^^^^^^^ type annotation requires that `'a` must outlive `'b` | diff --git a/tests/ui/lifetimes/copy_modulo_regions.stderr b/tests/ui/lifetimes/copy_modulo_regions.stderr index 310ddb21647f6..0d69f0323d621 100644 --- a/tests/ui/lifetimes/copy_modulo_regions.stderr +++ b/tests/ui/lifetimes/copy_modulo_regions.stderr @@ -4,7 +4,10 @@ error: lifetime may not live long enough LL | fn foo<'a>() -> [Foo<'a>; 100] { | -- lifetime `'a` defined here LL | [mk_foo::<'a>(); 100] - | ^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static` + | ^^^^^^^^^^^^^^^^^^^^^ + | | + | returning this value requires that `'a` must outlive `'static` + | requirement occurs due to copying this value | = note: requirement occurs because of the type `Foo<'_>`, which makes the generic argument `'_` invariant = note: the struct `Foo<'a>` is invariant over the parameter `'a` From fe8b12f8cfd27984a6102c441b49023d5bce0b02 Mon Sep 17 00:00:00 2001 From: dianne Date: Sat, 21 Dec 2024 13:23:57 -0800 Subject: [PATCH 12/12] only avoid blaming assignments from argument patterns --- .../src/diagnostics/conflict_errors.rs | 2 +- .../src/diagnostics/region_errors.rs | 6 ++-- .../rustc_borrowck/src/region_infer/mod.rs | 17 +++++------ compiler/rustc_borrowck/src/type_check/mod.rs | 28 ++++++++++--------- compiler/rustc_middle/src/mir/query.rs | 7 +---- ...egion_subtyping_basic.main.nll.0.32bit.mir | 4 +-- ...egion_subtyping_basic.main.nll.0.64bit.mir | 4 +-- tests/mir-opt/storage_ranges.main.nll.0.mir | 2 +- tests/ui/fn/fn_def_coercion.rs | 4 +-- tests/ui/fn/fn_def_coercion.stderr | 9 ++++-- .../adt-tuple-struct-calls.stderr | 18 ++++-------- .../nll/user-annotations/method-ufcs-1.stderr | 7 ++--- .../nll/user-annotations/method-ufcs-2.stderr | 7 ++--- .../promoted-annotation.stderr | 6 ++-- 14 files changed, 54 insertions(+), 67 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 8a43e4b54b195..2d993a3fd16f7 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2911,7 +2911,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { ( name, BorrowExplanation::MustBeValidFor { - category: ConstraintCategory::Assignment { .. }, + category: ConstraintCategory::Assignment, from_closure: false, region_name: RegionName { diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 051778dcace80..f0baa20648cd2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -41,7 +41,7 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { fn description(&self) -> &'static str { // Must end with a space. Allows for empty names to be provided. match self { - ConstraintCategory::Assignment { .. } => "assignment ", + ConstraintCategory::Assignment => "assignment ", ConstraintCategory::Return(_) => "returning this value ", ConstraintCategory::Yield => "yielding this value ", ConstraintCategory::UseAsConst => "using this value as a constant ", @@ -481,7 +481,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { (ConstraintCategory::Return(kind), true, false) if self.is_closure_fn_mut(fr) => { self.report_fnmut_error(&errci, kind) } - (ConstraintCategory::Assignment { .. }, true, false) + (ConstraintCategory::Assignment, true, false) | (ConstraintCategory::CallArgument(_), true, false) => { let mut db = self.report_escaping_data_error(&errci); @@ -673,7 +673,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { // Revert to the normal error in these cases. // Assignments aren't "escapes" in function items. if (fr_name_and_span.is_none() && outlived_fr_name_and_span.is_none()) - || (matches!(category, ConstraintCategory::Assignment { .. }) + || (*category == ConstraintCategory::Assignment && self.regioncx.universal_regions().defining_ty.is_fn_def()) || self.regioncx.universal_regions().defining_ty.is_const() { diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 73e25cbae27ed..d6375c5dc2701 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -2080,25 +2080,22 @@ impl<'tcx> RegionInferenceContext<'tcx> { | ConstraintCategory::CallArgument(_) | ConstraintCategory::CopyBound | ConstraintCategory::SizedBound - | ConstraintCategory::Assignment { has_interesting_ty: true } + | ConstraintCategory::Assignment | ConstraintCategory::Usage | ConstraintCategory::ClosureUpvar(_) => 2, - // Give assignments a lower priority when flagged as less likely to be interesting. - // In particular, de-prioritize MIR assignments lowered from argument patterns. - ConstraintCategory::Assignment { has_interesting_ty: false } => 3, // Generic arguments are unlikely to be what relates regions together - ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => 4, + ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => 3, // We handle predicates and opaque types specially; don't prioritize them here. - ConstraintCategory::Predicate(_) | ConstraintCategory::OpaqueType => 5, + ConstraintCategory::Predicate(_) | ConstraintCategory::OpaqueType => 4, // `Boring` constraints can correspond to user-written code and have useful spans, // but don't provide any other useful information for diagnostics. - ConstraintCategory::Boring => 6, + ConstraintCategory::Boring => 5, // `BoringNoLocation` constraints can point to user-written code, but are less // specific, and are not used for relations that would make sense to blame. - ConstraintCategory::BoringNoLocation => 7, + ConstraintCategory::BoringNoLocation => 6, // Do not blame internal constraints. - ConstraintCategory::Internal => 8, - ConstraintCategory::IllegalUniverse => 9, + ConstraintCategory::Internal => 7, + ConstraintCategory::IllegalUniverse => 8, } }; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 495ec956f35a8..1eb471968b285 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -892,18 +892,20 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { Some(l) if !body.local_decls[l].is_user_variable() => { ConstraintCategory::Boring } - Some(l) => ConstraintCategory::Assignment { - has_interesting_ty: body.local_decls[l].user_ty.is_some() - || matches!( - body.local_decls[l].local_info(), - LocalInfo::User(BindingForm::Var(VarBindingForm { - opt_ty_info: Some(_), - .. - })) - ), - }, - // Assignments to projections should be considered interesting. - _ => ConstraintCategory::Assignment { has_interesting_ty: true }, + Some(_) + if let Some(body_id) = tcx + .hir_node_by_def_id(body.source.def_id().expect_local()) + .body_id() + && let params = tcx.hir().body(body_id).params + && params + .iter() + .any(|param| param.span.contains(stmt.source_info.span)) => + { + // Assignments generated from lowering argument patterns shouldn't be called + // "assignments" in diagnostics and aren't interesting to blame for errors. + ConstraintCategory::Boring + } + _ => ConstraintCategory::Assignment, }; debug!( "assignment category: {:?} {:?}", @@ -1238,7 +1240,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ConstraintCategory::Boring } // The return type of a call is interesting for diagnostics. - _ => ConstraintCategory::Assignment { has_interesting_ty: true }, + _ => ConstraintCategory::Assignment, }; let locations = term_location.to_locations(); diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index f2fbc63ee4112..db5da941f1e7b 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -242,12 +242,7 @@ pub enum ConstraintCategory<'tcx> { CallArgument(Option>), CopyBound, SizedBound, - Assignment { - /// Whether this assignment is likely to be interesting to refer to in diagnostics. - /// Currently, this is true when it's assigning to a projection, when it's assigning from - /// the return value of a call, and when it has a user-provided type annotation. - has_interesting_ty: bool, - }, + Assignment, /// A constraint that came from a usage of a variable (e.g. in an ADT expression /// like `Foo { field: my_val }`) Usage, diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir index 7f4a2bbbb5c34..35e44b2314a50 100644 --- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir +++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.32bit.mir @@ -17,8 +17,8 @@ | '?2 live at {bb1[0]} | '?3 live at {bb1[1..=3]} | '?4 live at {bb1[4..=7], bb2[0..=2]} -| '?2: '?3 due to Assignment { has_interesting_ty: false } at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:19:13: 19:18 (#0) -| '?3: '?4 due to Assignment { has_interesting_ty: false } at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:20:13: 20:14 (#0) +| '?2: '?3 due to Assignment at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:19:13: 19:18 (#0) +| '?3: '?4 due to Assignment at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:20:13: 20:14 (#0) | | Borrows | bw0: issued at bb1[0] in '?2 diff --git a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir index 1d80df76b3f77..6d415f42d06f3 100644 --- a/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir +++ b/tests/mir-opt/nll/region_subtyping_basic.main.nll.0.64bit.mir @@ -17,8 +17,8 @@ | '?2 live at {bb1[0]} | '?3 live at {bb1[1..=3]} | '?4 live at {bb1[4..=7], bb2[0..=2]} -| '?2: '?3 due to Assignment { has_interesting_ty: false } at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:19:13: 19:18 (#0) -| '?3: '?4 due to Assignment { has_interesting_ty: false } at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:20:13: 20:14 (#0) +| '?2: '?3 due to Assignment at Single(bb1[0]) ($DIR/region_subtyping_basic.rs:19:13: 19:18 (#0) +| '?3: '?4 due to Assignment at Single(bb1[3]) ($DIR/region_subtyping_basic.rs:20:13: 20:14 (#0) | | Borrows | bw0: issued at bb1[0] in '?2 diff --git a/tests/mir-opt/storage_ranges.main.nll.0.mir b/tests/mir-opt/storage_ranges.main.nll.0.mir index 291e3bbc87354..ae8cd0c894dac 100644 --- a/tests/mir-opt/storage_ranges.main.nll.0.mir +++ b/tests/mir-opt/storage_ranges.main.nll.0.mir @@ -15,7 +15,7 @@ | '?1 live at {bb0[0..=22]} | '?2 live at {bb0[10]} | '?3 live at {bb0[11]} -| '?2: '?3 due to Assignment { has_interesting_ty: false } at Single(bb0[10]) ($DIR/storage_ranges.rs:7:17: 7:25 (#0) +| '?2: '?3 due to Assignment at Single(bb0[10]) ($DIR/storage_ranges.rs:7:17: 7:25 (#0) | | Borrows | bw0: issued at bb0[10] in '?2 diff --git a/tests/ui/fn/fn_def_coercion.rs b/tests/ui/fn/fn_def_coercion.rs index eea9e480827fb..31c8fa41de17c 100644 --- a/tests/ui/fn/fn_def_coercion.rs +++ b/tests/ui/fn/fn_def_coercion.rs @@ -47,11 +47,11 @@ fn j<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { let x = match true { true => foo::<&'c ()>, //~ ERROR lifetime may not live long enough - false => foo::<&'a ()>, + false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough }; x(a); - x(b); //~ ERROR lifetime may not live long enough + x(b); x(c); } diff --git a/tests/ui/fn/fn_def_coercion.stderr b/tests/ui/fn/fn_def_coercion.stderr index a4dc72310815b..c2776887b79d4 100644 --- a/tests/ui/fn/fn_def_coercion.stderr +++ b/tests/ui/fn/fn_def_coercion.stderr @@ -133,17 +133,20 @@ LL | true => foo::<&'c ()>, = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/fn_def_coercion.rs:54:5 + --> $DIR/fn_def_coercion.rs:50:18 | LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) { | -- -- lifetime `'b` defined here | | | lifetime `'a` defined here ... -LL | x(b); - | ^^^^ argument requires that `'b` must outlive `'a` +LL | false => foo::<&'a ()>, + | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a` | = help: consider adding the following bound: `'b: 'a` + = note: requirement occurs because of a function pointer to `foo` + = note: the function `foo` is invariant over the parameter `T` + = help: see for more information about variance help: the following changes may resolve your lifetime errors | diff --git a/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr index 2084697e7e26d..1478ad1431ba4 100644 --- a/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr +++ b/tests/ui/nll/user-annotations/adt-tuple-struct-calls.stderr @@ -4,11 +4,9 @@ error[E0597]: `c` does not live long enough LL | let c = 66; | - binding `c` declared here LL | let f = SomeStruct::<&'static u32>; + | -------------------------- assignment requires that `c` is borrowed for `'static` LL | f(&c); - | --^^- - | | | - | | borrowed value does not live long enough - | argument requires that `c` is borrowed for `'static` + | ^^ borrowed value does not live long enough LL | } | - `c` dropped here while still borrowed @@ -20,11 +18,9 @@ LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) { LL | let c = 66; | - binding `c` declared here LL | let f = SomeStruct::<&'a u32>; + | --------------------- assignment requires that `c` is borrowed for `'a` LL | f(&c); - | --^^- - | | | - | | borrowed value does not live long enough - | argument requires that `c` is borrowed for `'a` + | ^^ borrowed value does not live long enough LL | } | - `c` dropped here while still borrowed @@ -37,11 +33,9 @@ LL | let _closure = || { LL | let c = 66; | - binding `c` declared here LL | let f = SomeStruct::<&'a u32>; + | --------------------- assignment requires that `c` is borrowed for `'a` LL | f(&c); - | --^^- - | | | - | | borrowed value does not live long enough - | argument requires that `c` is borrowed for `'a` + | ^^ borrowed value does not live long enough LL | }; | - `c` dropped here while still borrowed diff --git a/tests/ui/nll/user-annotations/method-ufcs-1.stderr b/tests/ui/nll/user-annotations/method-ufcs-1.stderr index c42ea0172cf75..087e270c70f7d 100644 --- a/tests/ui/nll/user-annotations/method-ufcs-1.stderr +++ b/tests/ui/nll/user-annotations/method-ufcs-1.stderr @@ -4,11 +4,10 @@ error[E0597]: `a` does not live long enough LL | let a = 22; | - binding `a` declared here ... +LL | let x = <&'static u32 as Bazoom<_>>::method; + | ----------------------------------- assignment requires that `a` is borrowed for `'static` LL | x(&a, b, c); - | --^^------- - | | | - | | borrowed value does not live long enough - | argument requires that `a` is borrowed for `'static` + | ^^ borrowed value does not live long enough LL | } | - `a` dropped here while still borrowed diff --git a/tests/ui/nll/user-annotations/method-ufcs-2.stderr b/tests/ui/nll/user-annotations/method-ufcs-2.stderr index 287337c7d52d3..c89bed3b1b18f 100644 --- a/tests/ui/nll/user-annotations/method-ufcs-2.stderr +++ b/tests/ui/nll/user-annotations/method-ufcs-2.stderr @@ -4,11 +4,10 @@ error[E0597]: `a` does not live long enough LL | let a = 22; | - binding `a` declared here ... +LL | let x = <&'static u32 as Bazoom<_>>::method; + | ----------------------------------- assignment requires that `a` is borrowed for `'static` LL | x(&a, b, c); - | --^^------- - | | | - | | borrowed value does not live long enough - | argument requires that `a` is borrowed for `'static` + | ^^ borrowed value does not live long enough LL | } | - `a` dropped here while still borrowed diff --git a/tests/ui/nll/user-annotations/promoted-annotation.stderr b/tests/ui/nll/user-annotations/promoted-annotation.stderr index 39993475796f5..ca99e53187091 100644 --- a/tests/ui/nll/user-annotations/promoted-annotation.stderr +++ b/tests/ui/nll/user-annotations/promoted-annotation.stderr @@ -6,11 +6,9 @@ LL | fn foo<'a>() { LL | let x = 0; | - binding `x` declared here LL | let f = &drop::<&'a i32>; + | ---------------- assignment requires that `x` is borrowed for `'a` LL | f(&x); - | --^^- - | | | - | | borrowed value does not live long enough - | argument requires that `x` is borrowed for `'a` + | ^^ borrowed value does not live long enough LL | LL | } | - `x` dropped here while still borrowed