1
Fork 0

Auto merge of #133858 - dianne:better-blame-constraints-for-static, r=lcnr

`best_blame_constraint`: Blame better constraints when the region graph has cycles from invariance or `'static`

This fixes #132749 by changing which constraint is blamed for region errors in several cases. `best_blame_constraint` had a heuristic that tried to pinpoint the constraint causing an error by filtering out any constraints where the outliving region is unified with the ultimate target region being outlived. However, it used the SCCs of the region graph to do this, which is unreliable; in particular, if the target region is `'static`, or if there are cycles from the presence of invariant types, it was skipping over the constraints it should be blaming. As is the case in that issue, this could lead to confusing diagnostics. The simplest fix seems to work decently, judging by test stderr: this makes `best_blame_constraint` no longer filter constraints by their outliving region's SCC.

There are admittedly some quirks in the test output. In many cases, subdiagnostics that depend on the particular constraint being blamed have either started or stopped being emitted. After starting at this for quite a while, I think anything too fickle about whether it outputs based on the particular constraint being blamed should instead be looking at the constraint path as a whole, similar to what's done for [the placeholder-from-predicate note](https://github.com/rust-lang/rust/compare/master...dianne:rust:better-blame-constraints-for-static#diff-3c0de6462469af483c9ecdf2c4b00cb26192218ef2d5c62a0fde75107a74caaeR506).

Very many tests involving invariant types gained a note pointing out the types' invariance, but in a few cases it was lost. A particularly illustrative example is [tests/ui/lifetimes/copy_modulo_regions.stderr](https://github.com/rust-lang/rust/compare/master...dianne:rust:better-blame-constraints-for-static?expand=1#diff-96e1f8b29789b3c4ce2f77a5e0fba248829b97ef9d1ce39e7d2b4aa57b2cf4f0); I'd argue the new constraint is a better one to blame, but it lacks the variance diagnostic information that's elsewhere in the constraint path. If desired, I can try making that note check the whole path rather than just the blamed constraint.

The subdiagnostic [`BorrowExplanation::add_object_lifetime_default_note`](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_borrowck/diagnostics/explain_borrow/enum.BorrowExplanation.html#method.add_object_lifetime_default_note) depends on a `Cast` being blamed, so [a special case](364ca7f99c) was necessary to keep it from disappearing from tests specifically testing for it. However, see the FIXME comment in that commit; I think the special case should be removed once that subdiagnostic works properly, but it's nontrivial enough to warrant a separate PR. Incidentally, this removes the note from a test where it was being added erroneously: in [tests/ui/borrowck/two-phase-surprise-no-conflict.stderr](https://github.com/rust-lang/rust/compare/master...dianne:rust:better-blame-constraints-for-static?expand=1#diff-8cf085af8203677de6575a45458c9e6b03412a927df879412adec7e4f7ff5e14), the object lifetime is explicitly provided and it's not `'static`.
This commit is contained in:
bors 2025-01-08 12:37:54 +00:00
commit 6afee111c2
99 changed files with 731 additions and 620 deletions

View file

@ -4115,7 +4115,6 @@ name = "rustc_middle"
version = "0.0.0" version = "0.0.0"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"derive-where",
"either", "either",
"field-offset", "field-offset",
"gsgdt", "gsgdt",

View file

@ -1516,15 +1516,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}); });
self.explain_why_borrow_contains_point(location, borrow, None) self.explain_why_borrow_contains_point(location, borrow, None)
.add_explanation_to_diagnostic( .add_explanation_to_diagnostic(&self, &mut err, "", Some(borrow_span), None);
self.infcx.tcx,
self.body,
&self.local_names,
&mut err,
"",
Some(borrow_span),
None,
);
self.suggest_copy_for_type_in_cloned_ref(&mut err, place); self.suggest_copy_for_type_in_cloned_ref(&mut err, place);
let typeck_results = self.infcx.tcx.typeck(self.mir_def_id()); let typeck_results = self.infcx.tcx.typeck(self.mir_def_id());
if let Some(expr) = self.find_expr(borrow_span) { 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) self.explain_why_borrow_contains_point(location, borrow, None)
.add_explanation_to_diagnostic( .add_explanation_to_diagnostic(&self, &mut err, "", None, None);
self.infcx.tcx,
self.body,
&self.local_names,
&mut err,
"",
None,
None,
);
err err
} }
@ -1886,9 +1870,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
} }
explanation.add_explanation_to_diagnostic( explanation.add_explanation_to_diagnostic(
self.infcx.tcx, &self,
self.body,
&self.local_names,
&mut err, &mut err,
first_borrow_desc, first_borrow_desc,
None, None,
@ -3046,15 +3028,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
if let BorrowExplanation::MustBeValidFor { .. } = explanation { if let BorrowExplanation::MustBeValidFor { .. } = explanation {
} else { } else {
explanation.add_explanation_to_diagnostic( explanation.add_explanation_to_diagnostic(&self, &mut err, "", None, None);
self.infcx.tcx,
self.body,
&self.local_names,
&mut err,
"",
None,
None,
);
} }
} else { } else {
err.span_label(borrow_span, "borrowed value does not live long enough"); 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( explanation.add_explanation_to_diagnostic(&self, &mut err, "", Some(borrow_span), None);
self.infcx.tcx,
self.body,
&self.local_names,
&mut err,
"",
Some(borrow_span),
None,
);
} }
err err
@ -3128,15 +3094,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
_ => {} _ => {}
} }
explanation.add_explanation_to_diagnostic( explanation.add_explanation_to_diagnostic(&self, &mut err, "", None, None);
self.infcx.tcx,
self.body,
&self.local_names,
&mut err,
"",
None,
None,
);
self.buffer_error(err); self.buffer_error(err);
} }
@ -3309,15 +3267,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
} }
_ => {} _ => {}
} }
explanation.add_explanation_to_diagnostic( explanation.add_explanation_to_diagnostic(&self, &mut err, "", None, None);
self.infcx.tcx,
self.body,
&self.local_names,
&mut err,
"",
None,
None,
);
borrow_spans.args_subdiag(&mut err, |args_span| { borrow_spans.args_subdiag(&mut err, |args_span| {
crate::session_diagnostics::CaptureArgLabel::Capture { 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.explain_why_borrow_contains_point(location, loan, None)
self.infcx.tcx, .add_explanation_to_diagnostic(&self, &mut err, "", None, None);
self.body,
&self.local_names,
&mut err,
"",
None,
None,
);
self.explain_deref_coercion(loan, &mut err); self.explain_deref_coercion(loan, &mut err);

View file

@ -8,7 +8,6 @@ use std::assert_matches::assert_matches;
use rustc_errors::{Applicability, Diag}; use rustc_errors::{Applicability, Diag};
use rustc_hir as hir; use rustc_hir as hir;
use rustc_hir::intravisit::Visitor; use rustc_hir::intravisit::Visitor;
use rustc_index::IndexSlice;
use rustc_infer::infer::NllRegionVariableOrigin; use rustc_infer::infer::NllRegionVariableOrigin;
use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault;
use rustc_middle::mir::{ use rustc_middle::mir::{
@ -18,14 +17,15 @@ use rustc_middle::mir::{
use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::adjustment::PointerCoercion;
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt}; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt};
use rustc_middle::util::CallKind; 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 rustc_trait_selection::error_reporting::traits::FindExprBySpan;
use tracing::{debug, instrument}; use tracing::{debug, instrument};
use super::{RegionName, UseSpans, find_use}; use super::{RegionName, UseSpans, find_use};
use crate::borrow_set::BorrowData; use crate::borrow_set::BorrowData;
use crate::constraints::OutlivesConstraint;
use crate::nll::ConstraintDescription; use crate::nll::ConstraintDescription;
use crate::region_infer::{BlameConstraint, Cause, ExtraConstraintInfo}; use crate::region_infer::{BlameConstraint, Cause};
use crate::{MirBorrowckCtxt, WriteKind}; use crate::{MirBorrowckCtxt, WriteKind};
#[derive(Debug)] #[derive(Debug)]
@ -43,7 +43,7 @@ pub(crate) enum BorrowExplanation<'tcx> {
span: Span, span: Span,
region_name: RegionName, region_name: RegionName,
opt_place_desc: Option<String>, opt_place_desc: Option<String>,
extra_info: Vec<ExtraConstraintInfo>, path: Vec<OutlivesConstraint<'tcx>>,
}, },
Unexplained, Unexplained,
} }
@ -63,14 +63,16 @@ impl<'tcx> BorrowExplanation<'tcx> {
} }
pub(crate) fn add_explanation_to_diagnostic( pub(crate) fn add_explanation_to_diagnostic(
&self, &self,
tcx: TyCtxt<'tcx>, cx: &MirBorrowckCtxt<'_, '_, 'tcx>,
body: &Body<'tcx>,
local_names: &IndexSlice<Local, Option<Symbol>>,
err: &mut Diag<'_>, err: &mut Diag<'_>,
borrow_desc: &str, borrow_desc: &str,
borrow_span: Option<Span>, borrow_span: Option<Span>,
multiple_borrow_span: Option<(Span, Span)>, 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 { if let Some(span) = borrow_span {
let def_id = body.source.def_id(); let def_id = body.source.def_id();
if let Some(node) = tcx.hir().get_if_local(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 region_name,
ref opt_place_desc, ref opt_place_desc,
from_closure: _, from_closure: _,
ref extra_info, ref path,
} => { } => {
region_name.highlight_region_name(err); region_name.highlight_region_name(err);
@ -328,13 +330,8 @@ impl<'tcx> BorrowExplanation<'tcx> {
); );
}; };
for extra in extra_info { cx.add_placeholder_from_predicate_note(err, &path);
match extra { cx.add_sized_or_copy_bound_info(err, category, &path);
ExtraConstraintInfo::PlaceholderFromPredicate(span) => {
err.span_note(*span, "due to current limitations in the borrow checker, this implies a `'static` lifetime");
}
}
}
if let ConstraintCategory::Cast { if let ConstraintCategory::Cast {
is_implicit_coercion: true, is_implicit_coercion: true,
@ -487,8 +484,9 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
&self, &self,
borrow_region: RegionVid, borrow_region: RegionVid,
outlived_region: RegionVid, outlived_region: RegionVid,
) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>, Vec<ExtraConstraintInfo>) { ) -> (ConstraintCategory<'tcx>, bool, Span, Option<RegionName>, Vec<OutlivesConstraint<'tcx>>)
let (blame_constraint, extra_info) = self.regioncx.best_blame_constraint( {
let (blame_constraint, path) = self.regioncx.best_blame_constraint(
borrow_region, borrow_region,
NllRegionVariableOrigin::FreeRegion, NllRegionVariableOrigin::FreeRegion,
|r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region), |r| self.regioncx.provides_universal_region(r, borrow_region, outlived_region),
@ -497,7 +495,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
let outlived_fr_name = self.give_region_a_name(outlived_region); 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 /// Returns structured explanation for *why* the borrow contains the
@ -596,7 +594,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
None => { None => {
if let Some(region) = self.to_error_region_vid(borrow_region_vid) { 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); self.free_region_constraint_info(borrow_region_vid, region);
if let Some(region_name) = region_name { if let Some(region_name) = region_name {
let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref()); let opt_place_desc = self.describe_place(borrow.borrowed_place.as_ref());
@ -606,7 +604,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
span, span,
region_name, region_name,
opt_place_desc, opt_place_desc,
extra_info, path,
} }
} else { } else {
debug!("Could not generate a region name"); debug!("Could not generate a region name");

View file

@ -8,14 +8,16 @@ use rustc_errors::{Applicability, Diag, MultiSpan};
use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::def::{CtorKind, Namespace};
use rustc_hir::{self as hir, CoroutineKind, LangItem}; use rustc_hir::{self as hir, CoroutineKind, LangItem};
use rustc_index::IndexSlice; use rustc_index::IndexSlice;
use rustc_infer::infer::BoundRegionConversionTime; use rustc_infer::infer::{
BoundRegionConversionTime, NllRegionVariableOrigin, RegionVariableOrigin,
};
use rustc_infer::traits::SelectionError; use rustc_infer::traits::SelectionError;
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::mir::tcx::PlaceTy; use rustc_middle::mir::tcx::PlaceTy;
use rustc_middle::mir::{ use rustc_middle::mir::{
AggregateKind, CallSource, ConstOperand, FakeReadCause, Local, LocalInfo, LocalKind, Location, AggregateKind, CallSource, ConstOperand, ConstraintCategory, FakeReadCause, Local, LocalInfo,
Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, LocalKind, Location, Operand, Place, PlaceRef, ProjectionElem, Rvalue, Statement,
TerminatorKind, StatementKind, Terminator, TerminatorKind,
}; };
use rustc_middle::ty::print::Print; use rustc_middle::ty::print::Print;
use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
@ -33,7 +35,9 @@ use tracing::debug;
use super::MirBorrowckCtxt; use super::MirBorrowckCtxt;
use super::borrow_set::BorrowData; use super::borrow_set::BorrowData;
use crate::constraints::OutlivesConstraint;
use crate::fluent_generated as fluent; use crate::fluent_generated as fluent;
use crate::nll::ConstraintDescription;
use crate::session_diagnostics::{ use crate::session_diagnostics::{
CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause, CaptureArgLabel, CaptureReasonLabel, CaptureReasonNote, CaptureReasonSuggest, CaptureVarCause,
CaptureVarKind, CaptureVarPathUseCause, OnClosureNote, CaptureVarKind, CaptureVarPathUseCause, OnClosureNote,
@ -619,6 +623,52 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
region.print(&mut printer).unwrap(); region.print(&mut printer).unwrap();
printer.into_buffer() 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");
}
}
/// 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. /// The span(s) associated to a use of a place.

View file

@ -13,7 +13,7 @@ use rustc_hir::{PolyTraitRef, TyKind, WhereBoundPredicate};
use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound}; use rustc_infer::infer::{NllRegionVariableOrigin, RelateParamBound};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::hir::place::PlaceBase; 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_middle::ty::{self, GenericArgs, Region, RegionVid, Ty, TyCtxt, TypeVisitor};
use rustc_span::{Ident, Span, kw}; use rustc_span::{Ident, Span, kw};
use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
@ -29,7 +29,7 @@ use tracing::{debug, instrument, trace};
use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource}; use super::{OutlivesSuggestionBuilder, RegionName, RegionNameSource};
use crate::nll::ConstraintDescription; use crate::nll::ConstraintDescription;
use crate::region_infer::values::RegionElement; use crate::region_infer::values::RegionElement;
use crate::region_infer::{BlameConstraint, ExtraConstraintInfo, TypeTest}; use crate::region_infer::{BlameConstraint, TypeTest};
use crate::session_diagnostics::{ use crate::session_diagnostics::{
FnMutError, FnMutReturnTypeErr, GenericDoesNotLiveLongEnough, LifetimeOutliveErr, FnMutError, FnMutReturnTypeErr, GenericDoesNotLiveLongEnough, LifetimeOutliveErr,
LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote, LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote,
@ -49,8 +49,8 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> {
ConstraintCategory::Cast { is_implicit_coercion: false, .. } => "cast ", ConstraintCategory::Cast { is_implicit_coercion: false, .. } => "cast ",
ConstraintCategory::Cast { is_implicit_coercion: true, .. } => "coercion ", ConstraintCategory::Cast { is_implicit_coercion: true, .. } => "coercion ",
ConstraintCategory::CallArgument(_) => "argument ", ConstraintCategory::CallArgument(_) => "argument ",
ConstraintCategory::TypeAnnotation => "type annotation ", ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => "generic argument ",
ConstraintCategory::ClosureBounds => "closure body ", ConstraintCategory::TypeAnnotation(_) => "type annotation ",
ConstraintCategory::SizedBound => "proving this value is `Sized` ", ConstraintCategory::SizedBound => "proving this value is `Sized` ",
ConstraintCategory::CopyBound => "copying this value ", ConstraintCategory::CopyBound => "copying this value ",
ConstraintCategory::OpaqueType => "opaque type ", ConstraintCategory::OpaqueType => "opaque type ",
@ -440,8 +440,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
) { ) {
debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr); debug!("report_region_error(fr={:?}, outlived_fr={:?})", fr, outlived_fr);
let (blame_constraint, extra_info) = let (blame_constraint, path) = self.regioncx.best_blame_constraint(fr, fr_origin, |r| {
self.regioncx.best_blame_constraint(fr, fr_origin, |r| {
self.regioncx.provides_universal_region(r, fr, outlived_fr) self.regioncx.provides_universal_region(r, fr, outlived_fr)
}); });
let BlameConstraint { category, cause, variance_info, .. } = blame_constraint; let BlameConstraint { category, cause, variance_info, .. } = blame_constraint;
@ -554,13 +553,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
} }
} }
for extra in extra_info { self.add_placeholder_from_predicate_note(&mut diag, &path);
match extra { self.add_sized_or_copy_bound_info(&mut diag, category, &path);
ExtraConstraintInfo::PlaceholderFromPredicate(span) => {
diag.span_note(span, "due to current limitations in the borrow checker, this implies a `'static` lifetime");
}
}
}
self.buffer_error(diag); self.buffer_error(diag);
} }

View file

@ -6,6 +6,7 @@
#![feature(assert_matches)] #![feature(assert_matches)]
#![feature(box_patterns)] #![feature(box_patterns)]
#![feature(file_buffered)] #![feature(file_buffered)]
#![feature(if_let_guard)]
#![feature(let_chains)] #![feature(let_chains)]
#![feature(never_type)] #![feature(never_type)]
#![feature(rustc_attrs)] #![feature(rustc_attrs)]

View file

@ -13,15 +13,16 @@ use rustc_infer::infer::region_constraints::{GenericKind, VarInfos, VerifyBound,
use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin}; use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin};
use rustc_middle::bug; use rustc_middle::bug;
use rustc_middle::mir::{ use rustc_middle::mir::{
BasicBlock, Body, ClosureOutlivesRequirement, ClosureOutlivesSubject, ClosureOutlivesSubjectTy, AnnotationSource, BasicBlock, Body, ClosureOutlivesRequirement, ClosureOutlivesSubject,
ClosureRegionRequirements, ConstraintCategory, Local, Location, ReturnConstraint, ClosureOutlivesSubjectTy, ClosureRegionRequirements, ConstraintCategory, Local, Location,
TerminatorKind, ReturnConstraint, TerminatorKind,
}; };
use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::traits::{ObligationCause, ObligationCauseCode};
use rustc_middle::ty::fold::fold_regions; use rustc_middle::ty::fold::fold_regions;
use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex}; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex};
use rustc_mir_dataflow::points::DenseLocationMap; use rustc_mir_dataflow::points::DenseLocationMap;
use rustc_span::Span; use rustc_span::Span;
use rustc_span::hygiene::DesugaringKind;
use tracing::{debug, instrument, trace}; use tracing::{debug, instrument, trace};
use crate::BorrowckInferCtxt; use crate::BorrowckInferCtxt;
@ -315,11 +316,6 @@ enum Trace<'tcx> {
NotVisited, NotVisited,
} }
#[derive(Clone, PartialEq, Eq, Debug)]
pub(crate) enum ExtraConstraintInfo {
PlaceholderFromPredicate(Span),
}
#[instrument(skip(infcx, sccs), level = "debug")] #[instrument(skip(infcx, sccs), level = "debug")]
fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) { fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) {
use crate::renumber::RegionCtxt; use crate::renumber::RegionCtxt;
@ -1938,7 +1934,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
from_region: RegionVid, from_region: RegionVid,
from_region_origin: NllRegionVariableOrigin, from_region_origin: NllRegionVariableOrigin,
target_test: impl Fn(RegionVid) -> bool, target_test: impl Fn(RegionVid) -> bool,
) -> (BlameConstraint<'tcx>, Vec<ExtraConstraintInfo>) { ) -> (BlameConstraint<'tcx>, Vec<OutlivesConstraint<'tcx>>) {
// Find all paths // Find all paths
let (path, target_region) = self let (path, target_region) = self
.find_constraint_paths_between_regions(from_region, target_test) .find_constraint_paths_between_regions(from_region, target_test)
@ -1960,25 +1956,6 @@ impl<'tcx> RegionInferenceContext<'tcx> {
.collect::<Vec<_>>() .collect::<Vec<_>>()
); );
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. // We try to avoid reporting a `ConstraintCategory::Predicate` as our best constraint.
// Instead, we use it to produce an improved `ObligationCauseCode`. // Instead, we use it to produce an improved `ObligationCauseCode`.
// FIXME - determine what we should do if we encounter multiple // FIXME - determine what we should do if we encounter multiple
@ -1997,42 +1974,8 @@ impl<'tcx> RegionInferenceContext<'tcx> {
}) })
.unwrap_or_else(|| ObligationCauseCode::Misc); .unwrap_or_else(|| ObligationCauseCode::Misc);
// Classify each of the constraints along the path. // When reporting an error, there is typically a chain of constraints leading from some
let mut categorized_path: Vec<BlameConstraint<'tcx>> = path // "source" region which must outlive some "target" region.
.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
// 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);
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.
// In most cases, we prefer to "blame" the constraints closer to the target -- // 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, // but there is one exception. When constraints arise from higher-ranked subtyping,
// we generally prefer to blame the source value, // we generally prefer to blame the source value,
@ -2073,78 +2016,114 @@ impl<'tcx> RegionInferenceContext<'tcx> {
| NllRegionVariableOrigin::Existential { from_forall: true } => false, | NllRegionVariableOrigin::Existential { from_forall: true } => false,
}; };
let find_region = |i: &usize| { // To pick a constraint to blame, we organize constraints by how interesting we expect them
let constraint = &path[*i]; // to be in diagnostics, then pick the most interesting one closest to either the source or
// the target on our constraint path.
let constraint_sup_scc = self.constraint_sccs.scc(constraint.sup); let constraint_interest = |constraint: &OutlivesConstraint<'tcx>| {
// Try to avoid blaming constraints from desugarings, since they may not clearly match
if blame_source { // match what users have written. As an exception, allow blaming returns generated by
match categorized_path[*i].category { // `?` desugaring, since the correspondence is fairly clear.
ConstraintCategory::OpaqueType let category = if let Some(kind) = constraint.span.desugaring_kind()
| ConstraintCategory::Boring && (kind != DesugaringKind::QuestionMark
| ConstraintCategory::BoringNoLocation || !matches!(constraint.category, ConstraintCategory::Return(_)))
| ConstraintCategory::Internal {
| ConstraintCategory::Predicate(_) => false, ConstraintCategory::Boring
ConstraintCategory::TypeAnnotation
| ConstraintCategory::Return(_)
| ConstraintCategory::Yield => true,
_ => constraint_sup_scc != target_scc,
}
} else { } else {
!matches!( constraint.category
categorized_path[*i].category, };
ConstraintCategory::OpaqueType
| ConstraintCategory::Boring match category {
| ConstraintCategory::BoringNoLocation // Returns usually provide a type to blame and have specially written diagnostics,
| ConstraintCategory::Internal // so prioritize them.
| ConstraintCategory::Predicate(_) 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(
AnnotationSource::Ascription
| AnnotationSource::Declaration
| AnnotationSource::OpaqueCast,
) )
| ConstraintCategory::Cast { .. }
| ConstraintCategory::CallArgument(_)
| ConstraintCategory::CopyBound
| ConstraintCategory::SizedBound
| ConstraintCategory::Assignment
| ConstraintCategory::Usage
| ConstraintCategory::ClosureUpvar(_) => 2,
// Generic arguments are unlikely to be what relates regions together
ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => 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 = let best_choice = if blame_source {
if blame_source { range.rev().find(find_region) } else { range.find(find_region) }; path.iter().enumerate().rev().min_by_key(|(_, c)| constraint_interest(c)).unwrap().0
} else {
path.iter().enumerate().min_by_key(|(_, c)| constraint_interest(c)).unwrap().0
};
debug!(?best_choice, ?blame_source, ?extra_info); debug!(?best_choice, ?blame_source);
if let Some(i) = best_choice { let best_constraint = if let Some(next) = path.get(best_choice + 1)
if let Some(next) = categorized_path.get(i + 1) { && matches!(path[best_choice].category, ConstraintCategory::Return(_))
if matches!(categorized_path[i].category, ConstraintCategory::Return(_))
&& next.category == ConstraintCategory::OpaqueType && next.category == ConstraintCategory::OpaqueType
{ {
// The return expression is being influenced by the return type being // The return expression is being influenced by the return type being
// impl Trait, point at the return type and not the return expr. // impl Trait, point at the return type and not the return expr.
return (next.clone(), extra_info); *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 }
if categorized_path[i].category == ConstraintCategory::Return(ReturnConstraint::Normal) })
{ {
let field = categorized_path.iter().find_map(|p| { OutlivesConstraint {
if let ConstraintCategory::ClosureUpvar(f) = p.category { category: ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field)),
Some(f) ..path[best_choice]
}
} else { } else {
None path[best_choice]
} };
});
if let Some(field) = field { let blame_constraint = BlameConstraint {
categorized_path[i].category = category: best_constraint.category,
ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field)); from_closure: best_constraint.from_closure,
} cause: ObligationCause::new(best_constraint.span, CRATE_DEF_ID, cause_code.clone()),
} variance_info: best_constraint.variance_info,
};
return (categorized_path[i].clone(), extra_info); (blame_constraint, path)
}
// 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);
(categorized_path.remove(0), extra_info)
} }
pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> {

View file

@ -298,7 +298,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
context.ambient_variance(), context.ambient_variance(),
base_ty.ty, base_ty.ty,
location.to_locations(), location.to_locations(),
ConstraintCategory::TypeAnnotation, ConstraintCategory::TypeAnnotation(AnnotationSource::OpaqueCast),
) )
.unwrap(); .unwrap();
} }
@ -333,7 +333,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
ty::Invariant, ty::Invariant,
&UserTypeProjection { base: annotation_index, projs: vec![] }, &UserTypeProjection { base: annotation_index, projs: vec![] },
locations, locations,
ConstraintCategory::Boring, ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
) { ) {
let annotation = &self.typeck.user_type_annotations[annotation_index]; let annotation = &self.typeck.user_type_annotations[annotation_index];
span_mirbug!( span_mirbug!(
@ -455,7 +455,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
ty::Invariant, ty::Invariant,
user_ty, user_ty,
Locations::All(*span), Locations::All(*span),
ConstraintCategory::TypeAnnotation, ConstraintCategory::TypeAnnotation(AnnotationSource::Declaration),
) { ) {
span_mirbug!( span_mirbug!(
self, self,
@ -892,6 +892,19 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
Some(l) if !body.local_decls[l].is_user_variable() => { Some(l) if !body.local_decls[l].is_user_variable() => {
ConstraintCategory::Boring ConstraintCategory::Boring
} }
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, _ => ConstraintCategory::Assignment,
}; };
debug!( debug!(
@ -927,7 +940,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ty::Invariant, ty::Invariant,
&UserTypeProjection { base: annotation_index, projs: vec![] }, &UserTypeProjection { base: annotation_index, projs: vec![] },
location.to_locations(), location.to_locations(),
ConstraintCategory::Boring, ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg),
) { ) {
let annotation = &self.user_type_annotations[annotation_index]; let annotation = &self.user_type_annotations[annotation_index];
span_mirbug!( span_mirbug!(
@ -962,7 +975,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
*variance, *variance,
projection, projection,
Locations::All(stmt.source_info.span), Locations::All(stmt.source_info.span),
ConstraintCategory::TypeAnnotation, ConstraintCategory::TypeAnnotation(AnnotationSource::Ascription),
) { ) {
let annotation = &self.user_type_annotations[projection.base]; let annotation = &self.user_type_annotations[projection.base];
span_mirbug!( span_mirbug!(
@ -1226,6 +1239,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
Some(l) if !body.local_decls[l].is_user_variable() => { Some(l) if !body.local_decls[l].is_user_variable() => {
ConstraintCategory::Boring ConstraintCategory::Boring
} }
// The return type of a call is interesting for diagnostics.
_ => ConstraintCategory::Assignment, _ => ConstraintCategory::Assignment,
}; };
@ -2169,7 +2183,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ty_left, ty_left,
common_ty, common_ty,
location.to_locations(), location.to_locations(),
ConstraintCategory::Boring, ConstraintCategory::CallArgument(None),
) )
.unwrap_or_else(|err| { .unwrap_or_else(|err| {
bug!("Could not equate type variable with {:?}: {:?}", ty_left, err) bug!("Could not equate type variable with {:?}: {:?}", ty_left, err)
@ -2178,7 +2192,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
ty_right, ty_right,
common_ty, common_ty,
location.to_locations(), location.to_locations(),
ConstraintCategory::Boring, ConstraintCategory::CallArgument(None),
) { ) {
span_mirbug!( span_mirbug!(
self, self,

View file

@ -6,7 +6,6 @@ edition = "2021"
[dependencies] [dependencies]
# tidy-alphabetical-start # tidy-alphabetical-start
bitflags = "2.4.1" bitflags = "2.4.1"
derive-where = "1.2.7"
either = "1.5.0" either = "1.5.0"
field-offset = "0.3.5" field-offset = "0.3.5"
gsgdt = "0.1.2" gsgdt = "0.1.2"

View file

@ -3,7 +3,6 @@
use std::cell::Cell; use std::cell::Cell;
use std::fmt::{self, Debug}; use std::fmt::{self, Debug};
use derive_where::derive_where;
use rustc_abi::{FieldIdx, VariantIdx}; use rustc_abi::{FieldIdx, VariantIdx};
use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed; use rustc_errors::ErrorGuaranteed;
@ -225,29 +224,22 @@ rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16);
/// See also `rustc_const_eval::borrow_check::constraints`. /// See also `rustc_const_eval::borrow_check::constraints`.
#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
#[derive_where(PartialOrd, Ord)]
pub enum ConstraintCategory<'tcx> { pub enum ConstraintCategory<'tcx> {
Return(ReturnConstraint), Return(ReturnConstraint),
Yield, Yield,
UseAsConst, UseAsConst,
UseAsStatic, UseAsStatic,
TypeAnnotation, TypeAnnotation(AnnotationSource),
Cast { Cast {
/// Whether this cast is a coercion that was automatically inserted by the compiler. /// Whether this cast is a coercion that was automatically inserted by the compiler.
is_implicit_coercion: bool, is_implicit_coercion: bool,
/// Whether this is an unsizing coercion and if yes, this contains the target type. /// Whether this is an unsizing coercion and if yes, this contains the target type.
/// Region variables are erased to ReErased. /// Region variables are erased to ReErased.
#[derive_where(skip)]
unsize_to: Option<Ty<'tcx>>, unsize_to: Option<Ty<'tcx>>,
}, },
/// 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. /// Contains the function type if available.
CallArgument(#[derive_where(skip)] Option<Ty<'tcx>>), CallArgument(Option<Ty<'tcx>>),
CopyBound, CopyBound,
SizedBound, SizedBound,
Assignment, Assignment,
@ -276,13 +268,22 @@ pub enum ConstraintCategory<'tcx> {
IllegalUniverse, IllegalUniverse,
} }
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)] #[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
#[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)] #[derive(TyEncodable, TyDecodable, HashStable, TypeVisitable, TypeFoldable)]
pub enum ReturnConstraint { pub enum ReturnConstraint {
Normal, Normal,
ClosureUpvar(FieldIdx), 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 /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing
/// that must outlive some region. /// that must outlive some region.
#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)] #[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, HashStable)]

View file

@ -6,24 +6,24 @@ LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>(
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
... ...
LL | let z: I::A = if cond { x } else { y };
| ^ assignment requires that `'a` must outlive `'b`
|
= help: consider adding the following bound: `'a: 'b`
error: lifetime may not live long enough
--> $DIR/associated-types-project-from-hrtb-in-fn-body.rs:22:40
|
LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>(
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
...
LL | let z: I::A = if cond { x } else { y }; LL | let z: I::A = if cond { x } else { y };
| ^ assignment requires that `'b` must outlive `'a` | ^ assignment requires that `'b` must outlive `'a`
| |
= help: consider adding the following bound: `'b: 'a` = 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
|
LL | fn bar<'a, 'b, I : for<'x> Foo<&'x isize>>(
| -- -- lifetime `'b` defined here
| |
| lifetime `'a` defined here
...
LL | let z: I::A = if cond { x } else { y };
| ^ assignment requires that `'a` must outlive `'b`
|
= help: consider adding the following bound: `'a: 'b`
help: `'a` and `'b` must be the same: replace one with the other help: `'a` and `'b` must be the same: replace one with the other
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -7,9 +7,9 @@ LL | fn baz<'a, 'b>(x: Type<'a>, y: Type<'b>) -> (Type<'a>, Type<'b>) {
| lifetime `'a` defined here | lifetime `'a` defined here
LL | let f = foo; // <-- No consistent type can be inferred for `f` here. LL | let f = foo; // <-- No consistent type can be inferred for `f` here.
LL | let a = bar(f, x); 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: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant
= note: the struct `Type<'a>` is invariant over the parameter `'a` = note: the struct `Type<'a>` is invariant over the parameter `'a`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> 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 | lifetime `'a` defined here
... ...
LL | let b = bar(f, y); 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: requirement occurs because of the type `Type<'_>`, which makes the generic argument `'_` invariant
= note: the struct `Type<'a>` is invariant over the parameter `'a` = note: the struct `Type<'a>` is invariant over the parameter `'a`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

View file

@ -7,7 +7,7 @@ LL | let c = async || { println!("{}", *x); };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
LL | outlives::<'a>(c()); LL | outlives::<'a>(c());
LL | outlives::<'a>(call_once(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 | }
| - `x` dropped here while still borrowed | - `x` dropped here while still borrowed
@ -21,9 +21,9 @@ LL | fn simple<'a>(x: &'a i32) {
LL | let c = async move || { println!("{}", *x); }; LL | let c = async move || { println!("{}", *x); };
| - binding `c` declared here | - binding `c` declared here
LL | outlives::<'a>(c()); LL | outlives::<'a>(c());
| ^-- | ---------------^---
| | | | |
| borrowed value does not live long enough | | borrowed value does not live long enough
| argument requires that `c` is borrowed for `'a` | argument requires that `c` is borrowed for `'a`
LL | outlives::<'a>(call_once(c)); LL | outlives::<'a>(call_once(c));
LL | } LL | }
@ -38,7 +38,7 @@ LL | let c = async || { println!("{}", *x.0); };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
LL | outlives::<'a>(c()); LL | outlives::<'a>(c());
LL | outlives::<'a>(call_once(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 | }
| - `x` dropped here while still borrowed | - `x` dropped here while still borrowed
@ -52,7 +52,7 @@ LL | let c = async || { println!("{}", *x.0); };
| ---------------------------------- borrow of `x` occurs here | ---------------------------------- borrow of `x` occurs here
LL | outlives::<'a>(c()); LL | outlives::<'a>(c());
LL | outlives::<'a>(call_once(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 |
LL | let c = async move || { println!("{}", *x.0); }; LL | let c = async move || { println!("{}", *x.0); };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move out of `x` occurs here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ move out of `x` occurs here
@ -66,9 +66,9 @@ LL | fn through_field<'a>(x: S<'a>) {
LL | let c = async move || { println!("{}", *x.0); }; LL | let c = async move || { println!("{}", *x.0); };
| - binding `c` declared here | - binding `c` declared here
LL | outlives::<'a>(c()); LL | outlives::<'a>(c());
| ^-- | ---------------^---
| | | | |
| borrowed value does not live long enough | | borrowed value does not live long enough
| argument requires that `c` is borrowed for `'a` | argument requires that `c` is borrowed for `'a`
LL | outlives::<'a>(call_once(c)); LL | outlives::<'a>(call_once(c));
LL | } LL | }
@ -83,9 +83,9 @@ LL | fn through_field<'a>(x: S<'a>) {
LL | let c = async move || { println!("{}", *x.0); }; LL | let c = async move || { println!("{}", *x.0); };
| - binding `c` declared here | - binding `c` declared here
LL | outlives::<'a>(c()); LL | outlives::<'a>(c());
| --- | -------------------
| | | | |
| borrow of `c` occurs here | | borrow of `c` occurs here
| argument requires that `c` is borrowed for `'a` | argument requires that `c` is borrowed for `'a`
LL | outlives::<'a>(call_once(c)); LL | outlives::<'a>(call_once(c));
| ^ move out of `c` occurs here | ^ move out of `c` occurs here
@ -99,18 +99,18 @@ LL | let c = async || { println!("{}", *x.0); };
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ borrowed value does not live long enough
LL | outlives::<'a>(c()); LL | outlives::<'a>(c());
LL | outlives::<'a>(call_once(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 | }
| - `x` dropped here while still borrowed | - `x` dropped here while still borrowed
error[E0621]: explicit lifetime required in the type of `x` 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>) { LL | fn through_field_and_ref<'a>(x: &S<'a>) {
| ------ help: add explicit lifetime `'a` to the type of `x`: `&'a S<'a>` | ------ help: add explicit lifetime `'a` to the type of `x`: `&'a S<'a>`
... ...
LL | outlives::<'a>(call_once(c)); LL | outlives::<'a>(call_once(c));
| ^^^^^^^^^^^^ lifetime `'a` required | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
error[E0597]: `c` does not live long enough error[E0597]: `c` does not live long enough
--> $DIR/without-precise-captures-we-are-powerless.rs:43:20 --> $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); }; LL | let c = async move || { println!("{}", *x.0); };
| - binding `c` declared here | - binding `c` declared here
LL | outlives::<'a>(c()); LL | outlives::<'a>(c());
| ^-- | ---------------^---
| | | | |
| borrowed value does not live long enough | | borrowed value does not live long enough
| argument requires that `c` is borrowed for `'a` | argument requires that `c` is borrowed for `'a`
LL | outlives::<'a>(call_once(c)); LL | outlives::<'a>(call_once(c));
LL | } LL | }
| - `c` dropped here while still borrowed | - `c` dropped here while still borrowed
error[E0621]: explicit lifetime required in the type of `x` 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>) { LL | fn through_field_and_ref_move<'a>(x: &S<'a>) {
| ------ help: add explicit lifetime `'a` to the type of `x`: `&'a S<'a>` | ------ help: add explicit lifetime `'a` to the type of `x`: `&'a S<'a>`
... ...
LL | outlives::<'a>(call_once(c)); LL | outlives::<'a>(call_once(c));
| ^^^^^^^^^^^^ lifetime `'a` required | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
error: aborting due to 10 previous errors error: aborting due to 10 previous errors

View file

@ -11,8 +11,8 @@ impl Xyz {
&'a self, foo: &dyn Foo &'a self, foo: &dyn Foo
) -> &dyn Foo //~ WARNING elided lifetime has a name ) -> &dyn Foo //~ WARNING elided lifetime has a name
{ {
//~^ ERROR explicit lifetime required in the type of `foo` [E0621]
foo foo
//~^ ERROR explicit lifetime required in the type of `foo` [E0621]
} }
} }

View file

@ -10,16 +10,13 @@ LL | ) -> &dyn Foo
= note: `#[warn(elided_named_lifetimes)]` on by default = note: `#[warn(elided_named_lifetimes)]` on by default
error[E0621]: explicit lifetime required in the type of `foo` 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 LL | &'a self, foo: &dyn Foo
| -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)` | -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)`
LL | ) -> &dyn Foo ...
LL | / { LL | foo
LL | | | ^^^ lifetime `'a` required
LL | | foo
LL | | }
| |_____^ lifetime `'a` required
error: aborting due to 1 previous error; 1 warning emitted error: aborting due to 1 previous error; 1 warning emitted

View file

@ -11,8 +11,8 @@ impl Xyz {
foo: &dyn Foo, bar: &'a dyn Foo foo: &dyn Foo, bar: &'a dyn Foo
) -> &dyn Foo //~ ERROR missing lifetime specifier ) -> &dyn Foo //~ ERROR missing lifetime specifier
{ {
//~^ ERROR explicit lifetime required in the type of `foo` [E0621]
foo foo
//~^ ERROR explicit lifetime required in the type of `foo` [E0621]
} }
} }

View file

@ -13,16 +13,13 @@ LL | ) -> &'a dyn Foo
| ++ | ++
error[E0621]: explicit lifetime required in the type of `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 LL | foo: &dyn Foo, bar: &'a dyn Foo
| -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)` | -------- help: add explicit lifetime `'a` to the type of `foo`: `&'a (dyn Foo + 'a)`
LL | ) -> &dyn Foo ...
LL | / { LL | foo
LL | | | ^^^ lifetime `'a` required
LL | | foo
LL | | }
| |_____^ lifetime `'a` required
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -12,12 +12,12 @@ LL | extend_lt(val);
| argument requires that `'a` must outlive `'static` | argument requires that `'a` must outlive `'static`
error: lifetime may not live long enough 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>() { LL | pub fn test_coercion<'a>() {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
LL | let _: fn(&'a str) -> _ = extend_lt; 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 error[E0716]: temporary value dropped while borrowed
--> $DIR/fn-item-check-type-params.rs:48:11 --> $DIR/fn-item-check-type-params.rs:48:11

View file

@ -15,7 +15,7 @@ LL | async {
LL | let not_static = 0; LL | let not_static = 0;
| ---------- binding `not_static` declared here | ---------- binding `not_static` declared here
LL | force_send(async_load(&not_static)); LL | force_send(async_load(&not_static));
| -----------^^^^^^^^^^^- | ----------------------^^^^^^^^^^^--
| | | | | |
| | borrowed value does not live long enough | | borrowed value does not live long enough
| argument requires that `not_static` is borrowed for `'1` | argument requires that `not_static` is borrowed for `'1`

View file

@ -17,6 +17,8 @@ pub fn remove_package_from_database() {
lines_to_use.push(installed_id); lines_to_use.push(installed_id);
//~^ ERROR borrowed data escapes outside of closure //~^ ERROR borrowed data escapes outside of closure
//~| NOTE `installed_id` escapes the closure body here //~| 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); list_database(push_id);

View file

@ -9,6 +9,10 @@ LL | let push_id = |installed_id: &CrateId| {
LL | LL |
LL | lines_to_use.push(installed_id); LL | lines_to_use.push(installed_id);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `installed_id` escapes the closure body here | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -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>) { LL | fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) {
| -- lifetime `'a` defined here | -- 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(&reg.sess_mut))); LL | reg.register_univ(Box::new(CapturePass::new(&reg.sess_mut)));
| ^^^^^^^^^^^^^^^^^^-----------------------------------------^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-------------^^^
| | | | | | |
| | | immutable borrow occurs here | | immutable borrow occurs here
| | coercion requires that `reg.sess_mut` is borrowed for `'a`
| mutable borrow occurs here | mutable borrow occurs here
|
= note: due to object lifetime defaults, `Box<dyn for<'b> 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 error[E0502]: cannot borrow `*reg` as mutable because it is also borrowed as immutable
--> $DIR/two-phase-surprise-no-conflict.rs:144:5 --> $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>) { LL | fn register_plugins<'a>(mk_reg: impl Fn() -> &'a mut Registry<'a>) {
| -- lifetime `'a` defined here | -- 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))); LL | reg.register_univ(Box::new(CapturePass::new_mut(&mut reg.sess_mut)));
| ^^^^^^^^^^^^^^^^^^-------------------------------------------------^ | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-----------------^^^
| | | | | | |
| | | first mutable borrow occurs here | | first mutable borrow occurs here
| | coercion requires that `reg.sess_mut` is borrowed for `'a`
| second mutable borrow occurs here | second mutable borrow occurs here
|
= note: due to object lifetime defaults, `Box<dyn for<'b> 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 error[E0499]: cannot borrow `reg.sess_mut` as mutable more than once at a time
--> $DIR/two-phase-surprise-no-conflict.rs:158:53 --> $DIR/two-phase-surprise-no-conflict.rs:158:53

View file

@ -120,14 +120,14 @@ LL | }
| - `ap1` dropped here while still borrowed | - `ap1` dropped here while still borrowed
error: lifetime may not live long enough 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: ...) { LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| ------- ------- has type `VaListImpl<'2>` | ------- ------- has type `VaListImpl<'2>`
| | | |
| has type `&mut VaListImpl<'1>` | has type `&mut VaListImpl<'1>`
LL | *ap0 = ap1.clone(); 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: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant
= note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` = 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>` | has type `&mut VaListImpl<'1>`
LL | *ap0 = ap1.clone(); 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: requirement occurs because of the type `VaListImpl<'_>`, which makes the generic argument `'_` invariant
= note: the struct `VaListImpl<'f>` is invariant over the parameter `'f` = note: the struct `VaListImpl<'f>` is invariant over the parameter `'f`

View file

@ -42,7 +42,7 @@ fn change_assoc_1<'a, 'b>(
// This tests the default borrow check error, without the special casing for return values. // This tests the default borrow check error, without the special casing for return values.
fn require_static(_: *const dyn Trait<'static>) {} fn require_static(_: *const dyn Trait<'static>) {}
fn extend_to_static<'a>(ptr: *const dyn Trait<'a>) { 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() {} fn main() {}

View file

@ -154,14 +154,22 @@ help: `'b` and `'a` must be the same: replace one with the other
| |
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: lifetime may not live long enough error[E0521]: borrowed data escapes outside of function
--> $DIR/ptr-to-trait-obj-different-regions-misc.rs:45:20 --> $DIR/ptr-to-trait-obj-different-regions-misc.rs:45:5
| |
LL | fn extend_to_static<'a>(ptr: *const dyn Trait<'a>) { 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 _) 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 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`.

View file

@ -18,8 +18,8 @@ fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> {
// exploit: // exploit:
generator.as_mut().resume(""); generator.as_mut().resume("");
generator.as_mut().resume(s); // <- generator hoards it as `let ctx`. generator.as_mut().resume(s); // <- generator hoards it as `let ctx`.
//~^ ERROR borrowed data escapes outside of function
thread::spawn(move || { thread::spawn(move || {
//~^ ERROR borrowed data escapes outside of function
thread::sleep(time::Duration::from_millis(200)); thread::sleep(time::Duration::from_millis(200));
generator.as_mut().resume(""); // <- resumes from the last `yield`, running `dbg!(ctx)`. generator.as_mut().resume(""); // <- resumes from the last `yield`, running `dbg!(ctx)`.
}) })

View file

@ -1,15 +1,19 @@
error[E0521]: borrowed data escapes outside of function 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<()> { LL | fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> {
| ----------- - `s` is a reference that is only valid in the function body | ----------- - `s` is a reference that is only valid in the function body
| | | |
| lifetime `'not_static` defined here | lifetime `'not_static` defined here
... ...
LL | generator.as_mut().resume(s); // <- generator hoards it as `let ctx`. LL | / thread::spawn(move || {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | |
| | LL | | thread::sleep(time::Duration::from_millis(200));
| `s` escapes the function body here 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` | argument requires that `'not_static` must outlive `'static`
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -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 ()) { fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
let x = match true { 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 false => foo::<&'a ()>, //~ ERROR lifetime may not live long enough
}; };
x(a); x(a);
x(b); //~ ERROR lifetime may not live long enough x(b);
x(c); x(c);
} }

View file

@ -6,9 +6,9 @@ LL | fn f<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
LL | let mut x = foo::<&'a ()>; 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: requirement occurs because of a function pointer to `foo`
= note: the function `foo` is invariant over the parameter `T` = note: the function `foo` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> 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 | lifetime `'a` defined here
LL | let mut x = foo::<&'a ()>; LL | let mut x = foo::<&'a ()>;
LL | x = foo::<&'b ()>; 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: requirement occurs because of a function pointer to `foo`
= note: the function `foo` is invariant over the parameter `T` = note: the function `foo` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> 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 | lifetime `'a` defined here
LL | let mut x = foo::<&'c ()>; LL | let mut x = foo::<&'c ()>;
LL | x = foo::<&'b ()>; 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: requirement occurs because of a function pointer to `foo`
= note: the function `foo` is invariant over the parameter `T` = note: the function `foo` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> 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 | lifetime `'a` defined here
... ...
LL | x = foo::<&'a ()>; 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: requirement occurs because of a function pointer to `foo`
= note: the function `foo` is invariant over the parameter `T` = note: the function `foo` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> 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 | lifetime `'a` defined here
LL | let x = match true { LL | let x = match true {
LL | true => foo::<&'b ()>, 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: requirement occurs because of a function pointer to `foo`
= note: the function `foo` is invariant over the parameter `T` = note: the function `foo` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> 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 | lifetime `'a` defined here
... ...
LL | false => foo::<&'a ()>, 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: requirement occurs because of a function pointer to `foo`
= note: the function `foo` is invariant over the parameter `T` = note: the function `foo` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
@ -117,14 +117,14 @@ help: `'a` and `'b` must be the same: replace one with the other
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: lifetime may not live long enough 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 ()) { LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
| -- -- lifetime `'c` defined here | -- -- lifetime `'c` defined here
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
... LL | let x = match true {
LL | false => foo::<&'a ()>, LL | true => foo::<&'c ()>,
| ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c` | ^^^^^^^^^^^^^ assignment requires that `'a` must outlive `'c`
| |
= help: consider adding the following bound: `'a: 'c` = help: consider adding the following bound: `'a: 'c`
@ -133,17 +133,20 @@ LL | false => foo::<&'a ()>,
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: lifetime may not live long enough 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 ()) { LL | fn k<'a, 'b, 'c: 'a + 'b>(a: &'a (), b: &'b (), c: &'c ()) {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
... ...
LL | x(b); LL | false => foo::<&'a ()>,
| ^^^^ argument requires that `'b` must outlive `'a` | ^^^^^^^^^^^^^ assignment requires that `'b` must outlive `'a`
| |
= help: consider adding the following bound: `'b: '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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: the following changes may resolve your lifetime errors help: the following changes may resolve your lifetime errors
| |

View file

@ -6,7 +6,7 @@ LL | fn g<'a, 'b>() {
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
LL | f::<'a, 'b>(()); 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` = help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of a function pointer to `f` = note: requirement occurs because of a function pointer to `f`

View file

@ -6,6 +6,9 @@ LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
... ...
LL | let u = v;
| - requirement occurs due to copying this value
...
LL | let _: &'b i32 = *u.0; LL | let _: &'b i32 = *u.0;
| ^^^^^^^ type annotation requires that `'a` must outlive `'b` | ^^^^^^^ type annotation requires that `'a` must outlive `'b`
| |

View file

@ -29,11 +29,11 @@ fn needs_static() {
let a = display_len(&x); let a = display_len(&x);
//~^ ERROR `x` does not live long enough //~^ ERROR `x` does not live long enough
//~| NOTE this call may capture more lifetimes than intended //~| 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 //~| NOTE borrowed value does not live long enoug
fn needs_static(_: impl Sized + 'static) {} fn needs_static(_: impl Sized + 'static) {}
needs_static(a); needs_static(a);
//~^ NOTE argument requires that `x` is borrowed for `'static`
} }
//~^ NOTE `x` dropped here while still borrowed //~^ NOTE `x` dropped here while still borrowed
@ -76,11 +76,11 @@ fn needs_static_mut() {
let a = display_len_mut(&mut x); let a = display_len_mut(&mut x);
//~^ ERROR `x` does not live long enough //~^ ERROR `x` does not live long enough
//~| NOTE this call may capture more lifetimes than intended //~| 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 //~| NOTE borrowed value does not live long enough
fn needs_static(_: impl Sized + 'static) {} fn needs_static(_: impl Sized + 'static) {}
needs_static(a); needs_static(a);
//~^ NOTE argument requires that `x` is borrowed for `'static`
} }
//~^ NOTE `x` dropped here while still borrowed //~^ NOTE `x` dropped here while still borrowed

View file

@ -42,11 +42,11 @@ LL | let x = vec![1];
| - binding `x` declared here | - binding `x` declared here
LL | LL |
LL | let a = display_len(&x); LL | let a = display_len(&x);
| ------------^^- | ^^ borrowed value does not live long enough
| | |
| | borrowed value does not live long enough
| argument requires that `x` is borrowed for `'static`
... ...
LL | needs_static(a);
| --------------- argument requires that `x` is borrowed for `'static`
LL |
LL | } LL | }
| - `x` dropped here while still borrowed | - `x` dropped here while still borrowed
| |
@ -118,11 +118,11 @@ LL | let mut x = vec![1];
| ----- binding `x` declared here | ----- binding `x` declared here
LL | LL |
LL | let a = display_len_mut(&mut x); LL | let a = display_len_mut(&mut x);
| ----------------^^^^^^- | ^^^^^^ borrowed value does not live long enough
| | |
| | borrowed value does not live long enough
| argument requires that `x` is borrowed for `'static`
... ...
LL | needs_static(a);
| --------------- argument requires that `x` is borrowed for `'static`
LL |
LL | } LL | }
| - `x` dropped here while still borrowed | - `x` dropped here while still borrowed
| |

View file

@ -6,10 +6,9 @@ LL | fn foo<'a>() {
LL | let y = (); LL | let y = ();
| - binding `y` declared here | - binding `y` declared here
LL | equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW }); LL | equate(InvariantRef::new(&y), const { InvariantRef::<'a>::NEW });
| ------------------^^- | ^^ ----------------------- using this value as a constant requires that `y` is borrowed for `'a`
| | | | |
| | borrowed value does not live long enough | borrowed value does not live long enough
| argument requires that `y` is borrowed for `'a`
LL | LL |
LL | } LL | }
| - `y` dropped here while still borrowed | - `y` dropped here while still borrowed

View file

@ -9,7 +9,7 @@ LL | match InvariantRef::new(&y) {
| ^^ borrowed value does not live long enough | ^^ borrowed value does not live long enough
LL | LL |
LL | const { InvariantRef::<'a>::NEW } => (), 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 | }
LL | } LL | }
| - `y` dropped here while still borrowed | - `y` dropped here while still borrowed

View file

@ -112,13 +112,13 @@ LL | struct Foo; // does not impl Copy
| |
error: lifetime may not live long enough 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>() { LL | fn foo<'a>() {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
LL | let t: S<&'a isize> = S(marker::PhantomData); LL | let t: S<&'a isize> = S(marker::PhantomData);
LL | let a = &t as &dyn Gettable<&'a isize>; 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 error: aborting due to 7 previous errors

View file

@ -4,7 +4,10 @@ error: lifetime may not live long enough
LL | fn foo<'a>() -> [Foo<'a>; 100] { LL | fn foo<'a>() -> [Foo<'a>; 100] {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
LL | [mk_foo::<'a>(); 100] 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: requirement occurs because of the type `Foo<'_>`, which makes the generic argument `'_` invariant
= note: the struct `Foo<'a>` is invariant over the parameter `'a` = note: the struct `Foo<'a>` is invariant over the parameter `'a`

View file

@ -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 `'1`
| let's call the lifetime of this reference `'2` | 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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider introducing a named lifetime parameter help: consider introducing a named lifetime parameter
| |
LL | pub fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } 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 `'1`
| let's call the lifetime of this reference `'2` | 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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider introducing a named lifetime parameter help: consider introducing a named lifetime parameter
| |
LL | pub fn foo2<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } 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 `'1`
| let's call the lifetime of this reference `'2` | 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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider reusing a named lifetime parameter 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); } LL | pub fn foo3<'a>(_other: &'a [u8], x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }

View file

@ -7,9 +7,9 @@ fn inner(mut foo: &[u8]) {
let refcell = RefCell::new(&mut foo); let refcell = RefCell::new(&mut foo);
//~^ ERROR `foo` does not live long enough //~^ ERROR `foo` does not live long enough
let read = &refcell as &RefCell<dyn Read>; let read = &refcell as &RefCell<dyn Read>;
//~^ ERROR lifetime may not live long enough
read_thing(read); read_thing(read);
//~^ ERROR borrowed data escapes outside of function
} }
fn read_thing(refcell: &RefCell<dyn Read>) {} fn read_thing(refcell: &RefCell<dyn Read>) {}

View file

@ -5,22 +5,32 @@ LL | fn inner(mut foo: &[u8]) {
| ------- binding `foo` declared here | ------- binding `foo` declared here
LL | let refcell = RefCell::new(&mut foo); LL | let refcell = RefCell::new(&mut foo);
| ^^^^^^^^ borrowed value does not live long enough | ^^^^^^^^ borrowed value does not live long enough
LL |
LL | let read = &refcell as &RefCell<dyn Read>;
| ------------------------------ cast requires that `foo` is borrowed for `'static`
... ...
LL | read_thing(read);
| ---------------- argument requires that `foo` is borrowed for `'static`
LL |
LL | } LL | }
| - `foo` dropped here while still borrowed | - `foo` dropped here while still borrowed
error: lifetime may not live long enough error[E0521]: borrowed data escapes outside of function
--> $DIR/issue-90600-expected-return-static-indirect.rs:9:16 --> $DIR/issue-90600-expected-return-static-indirect.rs:11:5
| |
LL | fn inner(mut foo: &[u8]) { 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<dyn Read>; LL | read_thing(read);
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static` | ^^^^^^^^^^^^^^^^
| |
| `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<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 2 previous errors 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`.

View file

@ -8,6 +8,9 @@ LL | fn foo(x: &mut Vec<Ref<i32>>, y: Ref<i32>) {
LL | x.push(y); LL | x.push(y);
| ^^^^^^^^^ argument requires that `'1` must outlive `'2` | ^^^^^^^^^ argument requires that `'1` must outlive `'2`
| |
= note: requirement occurs because of a mutable reference to `Vec<Ref<'_, i32>>`
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider introducing a named lifetime parameter help: consider introducing a named lifetime parameter
| |
LL | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<'a, i32>) { LL | fn foo<'a>(x: &mut Vec<Ref<'a, i32>>, y: Ref<'a, i32>) {

View file

@ -10,6 +10,9 @@ LL | x.push(z);
| ^^^^^^^^^ argument requires that `'c` must outlive `'b` | ^^^^^^^^^ argument requires that `'c` must outlive `'b`
| |
= help: consider adding the following bound: `'c: 'b` = help: consider adding the following bound: `'c: 'b`
= note: requirement occurs because of a mutable reference to `Vec<Ref<'_, i32>>`
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -4,9 +4,9 @@ struct Ref<'a, T: 'a> {
fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) { fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
let a: &mut Vec<Ref<i32>> = x; let a: &mut Vec<Ref<i32>> = x;
//~^ ERROR lifetime may not live long enough
let b = Ref { data: y.data }; let b = Ref { data: y.data };
a.push(b); a.push(b);
//~^ ERROR lifetime may not live long enough
} }
fn main() { } fn main() { }

View file

@ -1,15 +1,17 @@
error: lifetime may not live long enough 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<Ref<'b, i32>>, y: Ref<'c, i32>) { LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
| -- -- lifetime `'c` defined here | -- -- lifetime `'c` defined here
| | | |
| lifetime `'b` defined here | lifetime `'b` defined here
... LL | let a: &mut Vec<Ref<i32>> = x;
LL | a.push(b); | ^ assignment requires that `'c` must outlive `'b`
| ^^^^^^^^^ argument requires that `'c` must outlive `'b`
| |
= help: consider adding the following bound: `'c: 'b` = help: consider adding the following bound: `'c: 'b`
= note: requirement occurs because of a mutable reference to `Vec<Ref<'_, i32>>`
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -4,9 +4,9 @@ struct Ref<'a, T: 'a> {
fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) { fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
let a: &mut Vec<Ref<i32>> = x; let a: &mut Vec<Ref<i32>> = x;
//~^ ERROR lifetime may not live long enough
let b = Ref { data: y.data }; let b = Ref { data: y.data };
Vec::push(a, b); Vec::push(a, b);
//~^ ERROR lifetime may not live long enough
} }
fn main() { } fn main() { }

View file

@ -1,15 +1,17 @@
error: lifetime may not live long enough 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<Ref<'b, i32>>, y: Ref<'c, i32>) { LL | fn foo<'a, 'b, 'c>(x: &'a mut Vec<Ref<'b, i32>>, y: Ref<'c, i32>) {
| -- -- lifetime `'c` defined here | -- -- lifetime `'c` defined here
| | | |
| lifetime `'b` defined here | lifetime `'b` defined here
... LL | let a: &mut Vec<Ref<i32>> = x;
LL | Vec::push(a, b); | ^ assignment requires that `'c` must outlive `'b`
| ^^^^^^^^^^^^^^^ argument requires that `'c` must outlive `'b`
| |
= help: consider adding the following bound: `'c: 'b` = help: consider adding the following bound: `'c: 'b`
= note: requirement occurs because of a mutable reference to `Vec<Ref<'_, i32>>`
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -8,6 +8,9 @@ LL | fn foo(z: &mut Vec<(&u8,&u8)>, (x, y): (&u8, &u8)) {
LL | z.push((x,y)); LL | z.push((x,y));
| ^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` | ^^^^^^^^^^^^^ 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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider introducing a named lifetime parameter help: consider introducing a named lifetime parameter
| |
LL | fn foo<'a>(z: &mut Vec<(&'a u8,&u8)>, (x, y): (&'a u8, &u8)) { 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)); LL | z.push((x,y));
| ^^^^^^^^^^^^^ argument requires that `'3` must outlive `'4` | ^^^^^^^^^^^^^ 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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider introducing a named lifetime parameter help: consider introducing a named lifetime parameter
| |
LL | fn foo<'a>(z: &mut Vec<(&u8,&'a u8)>, (x, y): (&u8, &'a u8)) { LL | fn foo<'a>(z: &mut Vec<(&u8,&'a u8)>, (x, y): (&u8, &'a u8)) {

View file

@ -10,6 +10,9 @@ LL | x.push(y);
| ^^^^^^^^^ argument requires that `'b` must outlive `'a` | ^^^^^^^^^ argument requires that `'b` must outlive `'a`
| |
= help: consider adding the following bound: `'b: 'a` = help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of a mutable reference to `Vec<Ref<'_>>`
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -9,6 +9,9 @@ LL | x.push(y);
| ^^^^^^^^^ argument requires that `'b` must outlive `'a` | ^^^^^^^^^ argument requires that `'b` must outlive `'a`
| |
= help: consider adding the following bound: `'b: 'a` = help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of a mutable reference to `Vec<Ref<'_>>`
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -8,6 +8,9 @@ LL | fn foo(mut x: Vec<Ref>, y: Ref) {
LL | x.push(y); LL | x.push(y);
| ^^^^^^^^^ argument requires that `'1` must outlive `'2` | ^^^^^^^^^ argument requires that `'1` must outlive `'2`
| |
= note: requirement occurs because of a mutable reference to `Vec<Ref<'_>>`
= note: mutable references are invariant over their type parameter
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider introducing a named lifetime parameter help: consider introducing a named lifetime parameter
| |
LL | fn foo<'a>(mut x: Vec<Ref<'a>>, y: Ref<'a>) { LL | fn foo<'a>(mut x: Vec<Ref<'a>>, y: Ref<'a>) {

View file

@ -9,6 +9,9 @@ LL | x.push(y);
| ^^^^^^^^^ argument requires that `'b` must outlive `'a` | ^^^^^^^^^ argument requires that `'b` must outlive `'a`
| |
= help: consider adding the following bound: `'b: '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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -19,6 +19,9 @@ LL | fn foo(x:fn(&u8, &u8), y: Vec<&u8>, z: &u8) {
LL | y.push(z); LL | y.push(z);
| ^^^^^^^^^ argument requires that `'1` must outlive `'2` | ^^^^^^^^^ 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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider introducing a named lifetime parameter help: consider introducing a named lifetime parameter
| |
LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) { LL | fn foo<'a>(x:fn(&u8, &u8), y: Vec<&'a u8>, z: &'a u8) {

View file

@ -8,6 +8,9 @@ LL | fn foo(x: &mut Vec<&u8>, y: &u8) {
LL | x.push(y); LL | x.push(y);
| ^^^^^^^^^ argument requires that `'1` must outlive `'2` | ^^^^^^^^^ 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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider introducing a named lifetime parameter and update trait if needed help: consider introducing a named lifetime parameter and update trait if needed
| |
LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) {

View file

@ -19,6 +19,9 @@ LL | fn foo(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&u8>, z: &u8) {
LL | y.push(z); LL | y.push(z);
| ^^^^^^^^^ argument requires that `'1` must outlive `'2` | ^^^^^^^^^ 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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider introducing a named lifetime parameter help: consider introducing a named lifetime parameter
| |
LL | fn foo<'a>(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&'a u8>, z: &'a u8) { LL | fn foo<'a>(x:Box<dyn Fn(&u8, &u8)> , y: Vec<&'a u8>, z: &'a u8) {

View file

@ -8,6 +8,9 @@ LL | fn foo(x: &mut Vec<&u8>, y: &u8) {
LL | x.push(y); LL | x.push(y);
| ^^^^^^^^^ argument requires that `'1` must outlive `'2` | ^^^^^^^^^ 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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider introducing a named lifetime parameter help: consider introducing a named lifetime parameter
| |
LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) {

View file

@ -23,6 +23,10 @@ LL | |_outlives1, _outlives2, _outlives3, x, y| {
... ...
LL | demand_y(x, y, p) LL | demand_y(x, y, p)
| ^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` | ^^^^^^^^^^^^^^^^^ 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<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
note: no external requirements note: no external requirements
--> $DIR/propagate-approximated-fail-no-postdom.rs:38:1 --> $DIR/propagate-approximated-fail-no-postdom.rs:38:1

View file

@ -41,9 +41,10 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3
#[rustc_regions] #[rustc_regions]
fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
//~^ ERROR lifetime may not live long enough
// Only works if 'x: 'y: // Only works if 'x: 'y:
demand_y(x, y, x.get()) demand_y(x, y, x.get())
//~^ ERROR lifetime may not live long enough
}); });
} }

View file

@ -23,17 +23,21 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
= note: defining type: supply = note: defining type: supply
error: lifetime may not live long enough 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>) { LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
... LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
LL | demand_y(x, y, x.get()) ... |
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b` LL | | });
| |______^ argument requires that `'a` must outlive `'b`
| |
= help: consider adding the following bound: `'a: '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<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -19,6 +19,10 @@ LL | foo(cell, |cell_a, cell_x| {
| `cell_a` declared here, outside of the closure body | `cell_a` declared here, outside of the closure body
LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure
| ^^^^^^^^^^^^^^^^^^^^^^^^ `cell_x` escapes the closure body here | ^^^^^^^^^^^^^^^^^^^^^^^^ `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<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
note: no external requirements note: no external requirements
--> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:18:1 --> $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; LL | let a = 0;
| - binding `a` declared here | - binding `a` declared here
LL | let cell = Cell::new(&a); LL | let cell = Cell::new(&a);
| ----------^^- | ^^ borrowed value does not live long enough
| | |
| | borrowed value does not live long enough
| argument requires that `a` is borrowed for `'static`
... ...
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 | } LL | }
| - `a` dropped here while still borrowed | - `a` dropped here while still borrowed

View file

@ -30,10 +30,9 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3
#[rustc_regions] #[rustc_regions]
fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
//~^ ERROR borrowed data escapes outside of function
// Only works if 'x: 'y: // Only works if 'x: 'y:
demand_y(x, y, x.get()) demand_y(x, y, x.get())
//~^ ERROR borrowed data escapes outside of function
}); });
} }

View file

@ -23,23 +23,18 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
= note: defining type: supply = note: defining type: supply
error[E0521]: borrowed data escapes outside of function 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>) { 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 | -- ------ `cell_a` is a reference that is only valid in the function body
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
LL | / establish_relationships(&cell_a, &cell_b, |_outlives, x, y| { ...
... | LL | demand_y(x, y, x.get())
LL | | }); | ^^^^^^^^^^^^^^^^^^^^^^^
| | ^ | |
| | | | `cell_a` escapes the function body here
| |______`cell_a` escapes the function body here
| argument requires that `'a` must outlive `'static` | 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<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -33,10 +33,9 @@ fn demand_y<'x, 'y>(_cell_x: &Cell<&'x u32>, _cell_y: &Cell<&'y u32>, _y: &'y u3
#[rustc_regions] #[rustc_regions]
fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| {
//~^ ERROR borrowed data escapes outside of function
// Only works if 'x: 'y: // Only works if 'x: 'y:
demand_y(x, y, x.get()) demand_y(x, y, x.get())
//~^ ERROR borrowed data escapes outside of function
}); });
} }

View file

@ -23,23 +23,18 @@ LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
= note: defining type: supply = note: defining type: supply
error[E0521]: borrowed data escapes outside of function 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>) { 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 | -- ------ `cell_a` is a reference that is only valid in the function body
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
LL | / establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y| { ...
... | LL | demand_y(x, y, x.get())
LL | | }); | ^^^^^^^^^^^^^^^^^^^^^^^
| | ^ | |
| | | | `cell_a` escapes the function body here
| |______`cell_a` escapes the function body here
| argument requires that `'a` must outlive `'static` | 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<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -34,9 +34,10 @@ fn demand_y<'x, 'y>(_outlives1: Cell<&&'x u32>, _outlives2: Cell<&'y &u32>, _y:
#[rustc_regions] #[rustc_regions]
fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| { establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
//~^ ERROR lifetime may not live long enough
// Only works if 'x: 'y: // Only works if 'x: 'y:
demand_y(outlives1, outlives2, x.get()) demand_y(outlives1, outlives2, x.get())
//~^ ERROR lifetime may not live long enough
}); });
} }

View file

@ -23,17 +23,21 @@ LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
= note: defining type: test = note: defining type: test
error: lifetime may not live long enough 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>) { LL | fn test<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
... LL | / establish_relationships(cell_a, cell_b, |outlives1, outlives2, x, y| {
LL | demand_y(outlives1, outlives2, x.get()) ... |
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'b` LL | | });
| |______^ argument requires that `'a` must outlive `'b`
| |
= help: consider adding the following bound: `'a: '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<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -22,6 +22,10 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives, x, y| {
LL | // Only works if 'x: 'y: LL | // Only works if 'x: 'y:
LL | demand_y(x, y, x.get()) LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` | ^^^^^^^^^^^^^^^^^^^^^^^ 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<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
note: no external requirements note: no external requirements
--> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:34:1 --> $DIR/propagate-fail-to-approximate-longer-no-bounds.rs:34:1

View file

@ -22,6 +22,10 @@ LL | establish_relationships(&cell_a, &cell_b, |_outlives1, _outlives2, x, y
LL | // Only works if 'x: 'y: LL | // Only works if 'x: 'y:
LL | demand_y(x, y, x.get()) LL | demand_y(x, y, x.get())
| ^^^^^^^^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'2` | ^^^^^^^^^^^^^^^^^^^^^^^ 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<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
note: no external requirements note: no external requirements
--> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:38:1 --> $DIR/propagate-fail-to-approximate-longer-wrong-bounds.rs:38:1

View file

@ -29,7 +29,7 @@ impl DebugWith<dyn DebugContext> for Foo {
fmt: &mut std::fmt::Formatter<'_>, fmt: &mut std::fmt::Formatter<'_>,
) -> std::fmt::Result { ) -> std::fmt::Result {
let Foo { bar } = self; let Foo { bar } = self;
bar.debug_with(cx); //~ ERROR: lifetime may not live long enough bar.debug_with(cx); //~ borrowed data escapes outside of method
Ok(()) Ok(())
} }
} }

View file

@ -1,11 +1,17 @@
error: lifetime may not live long enough error[E0521]: borrowed data escapes outside of method
--> $DIR/issue-54779-anon-static-lifetime.rs:32:24 --> $DIR/issue-54779-anon-static-lifetime.rs:32:9
| |
LL | cx: &dyn DebugContext, 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); 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 error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0521`.

View file

@ -17,10 +17,9 @@ LL | fn to_refs<T>(mut list: [&mut List<T>; 2]) -> Vec<&mut T> {
| - let's call the lifetime of this reference `'1` | - let's call the lifetime of this reference `'1`
... ...
LL | if let Some(n) = list[0].next.as_mut() { LL | if let Some(n) = list[0].next.as_mut() {
| ^^^^^^^^^^^^--------- | ^^^^^^^^^^^^ `list[_].next` was mutably borrowed here in the previous iteration of the loop
| | LL | list[0] = n;
| `list[_].next` was mutably borrowed here in the previous iteration of the loop | ----------- assignment requires that `list[_].next` is borrowed for `'1`
| argument requires that `list[_].next` is borrowed for `'1`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -17,10 +17,9 @@ LL | fn to_refs<'a, T>(mut list: (&'a mut List<T>, &'a mut List<T>)) -> Vec<&'a
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
... ...
LL | if let Some(n) = (list.0).next.as_mut() { LL | if let Some(n) = (list.0).next.as_mut() {
| ^^^^^^^^^^^^^--------- | ^^^^^^^^^^^^^ `list.0.next` was mutably borrowed here in the previous iteration of the loop
| | LL | list.1 = n;
| `list.0.next` was mutably borrowed here in the previous iteration of the loop | ---------- assignment requires that `list.0.next` is borrowed for `'a`
| argument requires that `list.0.next` is borrowed for `'a`
error: aborting due to 2 previous errors error: aborting due to 2 previous errors

View file

@ -12,8 +12,8 @@ struct Consumer<'tcx>(&'tcx ());
impl<'tcx> Consumer<'tcx> { impl<'tcx> Consumer<'tcx> {
fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) { fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) {
let other = self.use_fcx(fcx); //~ ERROR lifetime may not live long enough let other = self.use_fcx(fcx);
fcx.use_it(other); fcx.use_it(other); //~ ERROR lifetime may not live long enough
} }
fn use_fcx<'a>(&self, _: &FnCtxt<'a, 'tcx>) -> &'a () { fn use_fcx<'a>(&self, _: &FnCtxt<'a, 'tcx>) -> &'a () {

View file

@ -1,14 +1,18 @@
error: lifetime may not live long enough 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> { LL | impl<'tcx> Consumer<'tcx> {
| ---- lifetime `'tcx` defined here | ---- lifetime `'tcx` defined here
LL | fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) { LL | fn bad_method<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
LL | let other = self.use_fcx(fcx); LL | let other = self.use_fcx(fcx);
LL | fcx.use_it(other);
| ^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'tcx` | ^^^^^^^^^^^^^^^^^ argument requires that `'a` must outlive `'tcx`
| |
= help: consider adding the following bound: `'a: '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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -8,8 +8,8 @@ where
fn test<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) { fn test<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) {
let f = check; let f = check;
//~^ ERROR lifetime may not live long enough
f(x, y); f(x, y);
//~^ ERROR lifetime may not live long enough
} }
fn main() {} fn main() {}

View file

@ -1,16 +1,17 @@
error: lifetime may not live long enough 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 ()>) { LL | fn test<'a, 'b>(x: Cell<&'a ()>, y: Cell<&'b ()>) {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
LL | let f = check; 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` = help: consider adding the following bound: `'a: 'b`
= note: requirement occurs because of a function pointer to `check` = note: requirement occurs because of the type `Cell<&()>`, which makes the generic argument `&()` invariant
= note: the function `check` is invariant over the parameter `'a` = note: the struct `Cell<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -11,14 +11,14 @@ LL | || { None::<&'a &'b ()>; };
= help: consider adding the following bound: `'b: 'a` = help: consider adding the following bound: `'b: 'a`
error: lifetime may not live long enough 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>() { LL | fn test_early_late<'a: 'a, 'b>() {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
LL | || { None::<&'a &'b ()>; }; LL | || { None::<&'a &'b ()>; };
| ^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a` | ^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'b` must outlive `'a`
| |
= help: consider adding the following bound: `'b: 'a` = help: consider adding the following bound: `'b: 'a`

View file

@ -99,6 +99,10 @@ LL | fn get_bar(&self) -> Bar2 {
| - let's call the lifetime of this reference `'1` | - let's call the lifetime of this reference `'1`
LL | Bar2::new(&self) LL | Bar2::new(&self)
| ^^^^^^^^^^^^^^^^ argument requires that `'1` must outlive `'a` | ^^^^^^^^^^^^^^^^ 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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 9 previous errors error: aborting due to 9 previous errors

View file

@ -17,10 +17,10 @@ LL | fn assignment_to_field_projection<'a, T>(
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
... ...
LL | if let Some(n) = (list.0).next.as_mut() { LL | if let Some(n) = (list.0).next.as_mut() {
| ^^^^^^^^^^^^^--------- | ^^^^^^^^^^^^^ `list.0.next` was mutably borrowed here in the previous iteration of the loop
| | LL |
| `list.0.next` was mutably borrowed here in the previous iteration of the loop LL | list.1 = n;
| argument requires that `list.0.next` is borrowed for `'a` | ---------- 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 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 --> $DIR/assignment-to-differing-field.rs:37:21
@ -41,10 +41,10 @@ LL | fn assignment_through_projection_chain<'a, T>(
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
... ...
LL | if let Some(n) = ((((list.0).0).0).0).0.next.as_mut() { 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
| | LL |
| `list.0.0.0.0.0.next` was mutably borrowed here in the previous iteration of the loop LL | *((((list.0).0).0).0).1 = n;
| argument requires that `list.0.0.0.0.0.next` is borrowed for `'a` | --------------------------- assignment requires that `list.0.0.0.0.0.next` is borrowed for `'a`
error: aborting due to 4 previous errors error: aborting due to 4 previous errors

View file

@ -5,9 +5,10 @@ LL | let b = 44;
| - binding `b` declared here | - binding `b` declared here
... ...
LL | let x: DoubleCell<_> = make_cell(&b); 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 | } LL | }
| - `b` dropped here while still borrowed | - `b` dropped here while still borrowed

View file

@ -24,6 +24,22 @@ LL | | T: Anything<'b>,
| |
= note: defining type: no_relationships_late::<'?1, T> = 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<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error[E0309]: the parameter type `T` may not live long enough error[E0309]: the parameter type `T` may not live long enough
--> $DIR/projection-one-region-closure.rs:45:39 --> $DIR/projection-one-region-closure.rs:45:39
| |
@ -38,19 +54,6 @@ help: consider adding an explicit lifetime bound
LL | T: Anything<'b> + 'a, 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 note: external requirements
--> $DIR/projection-one-region-closure.rs:56:29 --> $DIR/projection-one-region-closure.rs:56:29
| |
@ -77,6 +80,22 @@ LL | | 'a: 'a,
| |
= note: defining type: no_relationships_early::<'?1, '?2, T> = 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<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error[E0309]: the parameter type `T` may not live long enough error[E0309]: the parameter type `T` may not live long enough
--> $DIR/projection-one-region-closure.rs:56:39 --> $DIR/projection-one-region-closure.rs:56:39
| |
@ -91,19 +110,6 @@ help: consider adding an explicit lifetime bound
LL | T: Anything<'b> + 'a, 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 note: external requirements
--> $DIR/projection-one-region-closure.rs:70:29 --> $DIR/projection-one-region-closure.rs:70:29
| |

View file

@ -24,7 +24,7 @@ LL | | T: Anything<'b>,
= note: defining type: no_relationships_late::<'?1, T> = note: defining type: no_relationships_late::<'?1, T>
error: lifetime may not live long enough 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) LL | fn no_relationships_late<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
| -- -- lifetime `'b` defined here | -- -- 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 | lifetime `'a` defined here
... ...
LL | with_signature(cell, t, |cell, t| require(cell, t)); 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` = 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<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
note: external requirements note: external requirements
--> $DIR/projection-one-region-trait-bound-closure.rs:47:29 --> $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> = note: defining type: no_relationships_early::<'?1, '?2, T>
error: lifetime may not live long enough 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) LL | fn no_relationships_early<'a, 'b, T>(cell: Cell<&'a ()>, t: T)
| -- -- lifetime `'b` defined here | -- -- 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 | lifetime `'a` defined here
... ...
LL | with_signature(cell, t, |cell, t| require(cell, t)); 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` = 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<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
note: external requirements note: external requirements
--> $DIR/projection-one-region-trait-bound-closure.rs:60:29 --> $DIR/projection-one-region-trait-bound-closure.rs:60:29

View file

@ -182,7 +182,7 @@ 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` = 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<T>` is invariant over the parameter `T` = note: the struct `Cell<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance

View file

@ -6,7 +6,7 @@ LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
LL | x == y; LL | x == y;
| ^ requires that `'a` must outlive `'b` | ^^^^^^ argument requires that `'a` must outlive `'b`
| |
= help: consider adding the following bound: `'a: 'b` = help: consider adding the following bound: `'a: 'b`
= note: requirement occurs because of a mutable reference to `&i32` = note: requirement occurs because of a mutable reference to `&i32`
@ -14,14 +14,14 @@ LL | x == y;
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: lifetime may not live long enough 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) { LL | fn compare_const<'a, 'b>(x: *const &mut &'a i32, y: *const &mut &'b i32) {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
LL | x == y; LL | x == y;
| ^ requires that `'b` must outlive `'a` | ^^^^^^ argument requires that `'b` must outlive `'a`
| |
= help: consider adding the following bound: `'b: 'a` = help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of a mutable reference to `&i32` = note: requirement occurs because of a mutable reference to `&i32`
@ -38,7 +38,7 @@ LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
LL | x == y; LL | x == y;
| ^ requires that `'a` must outlive `'b` | ^^^^^^ argument requires that `'a` must outlive `'b`
| |
= help: consider adding the following bound: `'a: 'b` = help: consider adding the following bound: `'a: 'b`
= note: requirement occurs because of a mutable pointer to `&i32` = note: requirement occurs because of a mutable pointer to `&i32`
@ -46,14 +46,14 @@ LL | x == y;
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: lifetime may not live long enough 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) { LL | fn compare_mut<'a, 'b>(x: *mut &'a i32, y: *mut &'b i32) {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
LL | x == y; LL | x == y;
| ^ requires that `'b` must outlive `'a` | ^^^^^^ argument requires that `'b` must outlive `'a`
| |
= help: consider adding the following bound: `'b: 'a` = help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of a mutable pointer to `&i32` = note: requirement occurs because of a mutable pointer to `&i32`
@ -72,7 +72,7 @@ LL | fn compare_fn_ptr<'a, 'b, 'c>(f: fn(&'c mut &'a i32), g: fn(&'c mut &'b i32
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
LL | f == g; LL | f == g;
| ^ requires that `'a` must outlive `'b` | ^^^^^^ argument requires that `'a` must outlive `'b`
| |
= help: consider adding the following bound: `'a: 'b` = help: consider adding the following bound: `'a: 'b`
= note: requirement occurs because of a mutable reference to `&i32` = note: requirement occurs because of a mutable reference to `&i32`
@ -80,14 +80,14 @@ LL | f == g;
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: lifetime may not live long enough 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)) { 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 `'b` defined here
| | | |
| lifetime `'a` defined here | lifetime `'a` defined here
LL | f == g; LL | f == g;
| ^ requires that `'b` must outlive `'a` | ^^^^^^ argument requires that `'b` must outlive `'a`
| |
= help: consider adding the following bound: `'b: 'a` = help: consider adding the following bound: `'b: 'a`
= note: requirement occurs because of a mutable reference to `&i32` = note: requirement occurs because of a mutable reference to `&i32`

View file

@ -3,13 +3,12 @@ error[E0597]: `c` does not live long enough
| |
LL | let c = 66; LL | let c = 66;
| - binding `c` declared here | - binding `c` declared here
LL | combine( LL | / combine(
LL | SomeEnum::SomeVariant(Cell::new(&c)), LL | | SomeEnum::SomeVariant(Cell::new(&c)),
| ----------^^- | | ^^ borrowed value does not live long enough
| | | LL | | SomeEnum::SomeOtherVariant::<Cell<&'static u32>>,
| | borrowed value does not live long enough LL | | );
| argument requires that `c` is borrowed for `'static` | |_____- argument requires that `c` is borrowed for `'static`
...
LL | } LL | }
| - `c` dropped here while still borrowed | - `c` dropped here while still borrowed
@ -20,13 +19,12 @@ LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
LL | let c = 66; LL | let c = 66;
| - binding `c` declared here | - binding `c` declared here
LL | combine( LL | / combine(
LL | SomeEnum::SomeVariant(Cell::new(&c)), LL | | SomeEnum::SomeVariant(Cell::new(&c)),
| ----------^^- | | ^^ borrowed value does not live long enough
| | | LL | | SomeEnum::SomeOtherVariant::<Cell<&'a u32>>,
| | borrowed value does not live long enough LL | | );
| argument requires that `c` is borrowed for `'a` | |_____- argument requires that `c` is borrowed for `'a`
...
LL | } LL | }
| - `c` dropped here while still borrowed | - `c` dropped here while still borrowed
@ -38,13 +36,12 @@ LL | fn annot_reference_named_lifetime_in_closure<'a>(_: &'a u32) {
LL | let _closure = || { LL | let _closure = || {
LL | let c = 66; LL | let c = 66;
| - binding `c` declared here | - binding `c` declared here
LL | combine( LL | / combine(
LL | SomeEnum::SomeVariant(Cell::new(&c)), LL | | SomeEnum::SomeVariant(Cell::new(&c)),
| ----------^^- | | ^^ borrowed value does not live long enough
| | | LL | | SomeEnum::SomeOtherVariant::<Cell<&'a u32>>,
| | borrowed value does not live long enough LL | | );
| argument requires that `c` is borrowed for `'a` | |_________- argument requires that `c` is borrowed for `'a`
...
LL | }; LL | };
| - `c` dropped here while still borrowed | - `c` dropped here while still borrowed

View file

@ -4,11 +4,9 @@ error[E0597]: `c` does not live long enough
LL | let c = 66; LL | let c = 66;
| - binding `c` declared here | - binding `c` declared here
LL | let f = SomeStruct::<&'static u32>; LL | let f = SomeStruct::<&'static u32>;
| -------------------------- assignment requires that `c` is borrowed for `'static`
LL | f(&c); 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 | } LL | }
| - `c` dropped here while still borrowed | - `c` dropped here while still borrowed
@ -20,11 +18,9 @@ LL | fn annot_reference_named_lifetime<'a>(_d: &'a u32) {
LL | let c = 66; LL | let c = 66;
| - binding `c` declared here | - binding `c` declared here
LL | let f = SomeStruct::<&'a u32>; LL | let f = SomeStruct::<&'a u32>;
| --------------------- assignment requires that `c` is borrowed for `'a`
LL | f(&c); 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 | } LL | }
| - `c` dropped here while still borrowed | - `c` dropped here while still borrowed
@ -37,11 +33,9 @@ LL | let _closure = || {
LL | let c = 66; LL | let c = 66;
| - binding `c` declared here | - binding `c` declared here
LL | let f = SomeStruct::<&'a u32>; LL | let f = SomeStruct::<&'a u32>;
| --------------------- assignment requires that `c` is borrowed for `'a`
LL | f(&c); 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 | }; LL | };
| - `c` dropped here while still borrowed | - `c` dropped here while still borrowed

View file

@ -4,11 +4,10 @@ error[E0597]: `a` does not live long enough
LL | let a = 22; LL | let a = 22;
| - binding `a` declared here | - 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); 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 | } LL | }
| - `a` dropped here while still borrowed | - `a` dropped here while still borrowed

View file

@ -4,11 +4,10 @@ error[E0597]: `a` does not live long enough
LL | let a = 22; LL | let a = 22;
| - binding `a` declared here | - 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); 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 | } LL | }
| - `a` dropped here while still borrowed | - `a` dropped here while still borrowed

View file

@ -1,5 +1,5 @@
error: lifetime may not live long enough 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>) { LL | fn bar<'a, 'b>(x: Cell<&'a u32>, y: Cell<&'b u32>) {
| -- -- lifetime `'b` defined here | -- -- lifetime `'b` defined here

View file

@ -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() {}

View file

@ -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

View file

@ -25,6 +25,10 @@ LL | self.enter_scope(|ctx| {
| has type `&mut FooImpl<'2, '_, T>` | has type `&mut FooImpl<'2, '_, T>`
LL | BarImpl(ctx); LL | BarImpl(ctx);
| ^^^ this usage requires that `'1` must outlive `'2` | ^^^ 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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: lifetime may not live long enough error: lifetime may not live long enough
--> $DIR/lifetime-not-long-enough-suggestion-regression-test-124563.rs:22:9 --> $DIR/lifetime-not-long-enough-suggestion-regression-test-124563.rs:22:9

View file

@ -3,7 +3,7 @@
// over time, but this test used to exhibit some pretty bogus messages // over time, but this test used to exhibit some pretty bogus messages
// that were not remotely helpful. // 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 ()>); struct Invariant<'a>(Option<&'a mut &'a mut ()>);
@ -11,9 +11,9 @@ fn mk_static() -> Invariant<'static> { Invariant(None) }
fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) { fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
let bad = if x.is_some() { let bad = if x.is_some() {
x.unwrap() //~ ERROR borrowed data escapes outside of function [E0521] x.unwrap()
} else { } else {
mk_static() mk_static() //~ ERROR lifetime may not live long enough
}; };
f(bad); f(bad);
} }

View file

@ -1,16 +1,11 @@
error[E0521]: borrowed data escapes outside of function error: lifetime may not live long enough
--> $DIR/region-invariant-static-error-reporting.rs:14:9 --> $DIR/region-invariant-static-error-reporting.rs:16:9
| |
LL | fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) { LL | fn unify<'a>(x: Option<Invariant<'a>>, f: fn(Invariant<'a>)) {
| -- - `x` is a reference that is only valid in the function body | -- lifetime `'a` defined here
| | ...
| lifetime `'a` defined here LL | mk_static()
LL | let bad = if x.is_some() { | ^^^^^^^^^^^ assignment requires that `'a` must outlive `'static`
LL | x.unwrap()
| ^^^^^^^^^^
| |
| `x` escapes the function body here
| argument requires that `'a` must outlive `'static`
| |
= note: requirement occurs because of the type `Invariant<'_>`, which makes the generic argument `'_` invariant = 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` = 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 error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0521`.

View file

@ -4,11 +4,9 @@ error[E0597]: `person` does not live long enough
LL | let person = "Fred".to_string(); LL | let person = "Fred".to_string();
| ------ binding `person` declared here | ------ binding `person` declared here
LL | let person: &str = &person; LL | let person: &str = &person;
| ^^^^^^^ | ^^^^^^^ borrowed value does not live long enough
| |
| borrowed value does not live long enough
| assignment requires that `person` is borrowed for `'static`
LL | let s: Box<dyn Trait<&'static str>> = Box::new(Struct { person: person }); LL | let s: Box<dyn Trait<&'static str>> = Box::new(Struct { person: person });
| ------ this usage requires that `person` is borrowed for `'static`
LL | } LL | }
| - `person` dropped here while still borrowed | - `person` dropped here while still borrowed

View file

@ -1,10 +1,10 @@
error: lifetime may not live long enough 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) { LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
LL | let _ = x as &dyn Bar<'a>; // Error 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 error: lifetime may not live long enough
--> $DIR/type-checking-test-3.rs:16:18 --> $DIR/type-checking-test-3.rs:16:18

View file

@ -1,10 +1,10 @@
error: lifetime may not live long enough 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) { LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
LL | let _ = x as &dyn Bar<'static, 'a>; // Error 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 error: lifetime may not live long enough
--> $DIR/type-checking-test-4.rs:24:18 --> $DIR/type-checking-test-4.rs:24:18

View file

@ -7,6 +7,10 @@ LL | doit(0, &|x, y| {
| has type `&Cell<&'2 i32>` | has type `&Cell<&'2 i32>`
LL | x.set(y); LL | x.set(y);
| ^^^^^^^^ argument requires that `'1` must outlive `'2` | ^^^^^^^^ 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<T>` is invariant over the parameter `T`
= help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
error: aborting due to 1 previous error error: aborting due to 1 previous error

View file

@ -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 `'1`
| let's call the lifetime of this reference `'2` | 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 <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
help: consider introducing a named lifetime parameter help: consider introducing a named lifetime parameter
| |
LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); } LL | fn foo<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { x.push(y); }

View file

@ -1,10 +1,10 @@
error: lifetime may not live long enough 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) { LL | fn take<'a>(_: &'a u32) {
| -- lifetime `'a` defined here | -- lifetime `'a` defined here
LL | let _: Box<dyn Foo<Bar = &'a u32>> = make(); LL | let _: Box<dyn Foo<Bar = &'a u32>> = make();
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static` | ^^^^^^ coercion requires that `'a` must outlive `'static`
error: aborting due to 1 previous error error: aborting due to 1 previous error