Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit fd49086

Browse files
committedOct 3, 2024·
Try to point out when edition 2024 lifetime capture rules cause borrowck issues
1 parent d4f016d commit fd49086

File tree

8 files changed

+753
-1
lines changed

8 files changed

+753
-1
lines changed
 

‎compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
14891489
&borrow_msg,
14901490
&value_msg,
14911491
);
1492+
self.note_due_to_edition_2024_opaque_capture_rules(borrow, &mut err);
14921493

14931494
borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow);
14941495

@@ -1561,6 +1562,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
15611562
borrow_span,
15621563
&self.describe_any_place(borrow.borrowed_place.as_ref()),
15631564
);
1565+
self.note_due_to_edition_2024_opaque_capture_rules(borrow, &mut err);
1566+
15641567
borrow_spans.var_subdiag(&mut err, Some(borrow.kind), |kind, var_span| {
15651568
use crate::session_diagnostics::CaptureVarCause::*;
15661569
let place = &borrow.borrowed_place;
@@ -1820,6 +1823,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
18201823
unreachable!()
18211824
}
18221825
};
1826+
self.note_due_to_edition_2024_opaque_capture_rules(issued_borrow, &mut err);
18231827

18241828
if issued_spans == borrow_spans {
18251829
borrow_spans.var_subdiag(&mut err, Some(gen_borrow_kind), |kind, var_span| {
@@ -2860,7 +2864,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
28602864

28612865
debug!(?place_desc, ?explanation);
28622866

2863-
let err = match (place_desc, explanation) {
2867+
let mut err = match (place_desc, explanation) {
28642868
// If the outlives constraint comes from inside the closure,
28652869
// for example:
28662870
//
@@ -2939,6 +2943,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
29392943
explanation,
29402944
),
29412945
};
2946+
self.note_due_to_edition_2024_opaque_capture_rules(borrow, &mut err);
29422947

29432948
self.buffer_error(err);
29442949
}
@@ -3777,6 +3782,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
37773782
}
37783783

37793784
let mut err = self.cannot_assign_to_borrowed(span, loan_span, &descr_place);
3785+
self.note_due_to_edition_2024_opaque_capture_rules(loan, &mut err);
37803786

37813787
loan_spans.var_subdiag(&mut err, Some(loan.kind), |kind, var_span| {
37823788
use crate::session_diagnostics::CaptureVarCause::*;

‎compiler/rustc_borrowck/src/diagnostics/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ mod conflict_errors;
4848
mod explain_borrow;
4949
mod move_errors;
5050
mod mutability_errors;
51+
mod opaque_suggestions;
5152
mod region_errors;
5253

5354
pub(crate) use bound_region_errors::{ToUniverseInfo, UniverseInfo};
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
#![allow(rustc::diagnostic_outside_of_impl)]
2+
#![allow(rustc::untranslatable_diagnostic)]
3+
4+
use std::ops::ControlFlow;
5+
6+
use either::Either;
7+
use rustc_data_structures::fx::FxIndexSet;
8+
use rustc_errors::{Applicability, Diag};
9+
use rustc_hir as hir;
10+
use rustc_hir::def_id::DefId;
11+
use rustc_middle::mir::{self, ConstraintCategory, Location};
12+
use rustc_middle::ty::{
13+
self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
14+
};
15+
use rustc_span::Symbol;
16+
17+
use crate::MirBorrowckCtxt;
18+
use crate::borrow_set::BorrowData;
19+
use crate::consumers::RegionInferenceContext;
20+
use crate::type_check::Locations;
21+
22+
impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
23+
/// Try to note when an opaque is involved in a borrowck error and that
24+
/// opaque captures lifetimes due to edition 2024.
25+
// FIXME: This code is otherwise somewhat general, and could easily be adapted
26+
// to explain why other things overcapture... like async fn and opaques with
27+
// explicit `use<'_>` statements.
28+
pub(crate) fn note_due_to_edition_2024_opaque_capture_rules(
29+
&self,
30+
borrow: &BorrowData<'tcx>,
31+
diag: &mut Diag<'_>,
32+
) {
33+
// We look at all the locals. Why locals? Because it's the best thing
34+
// I could think of that's correlated with the *instantiated* higer-ranked
35+
// binder for calls, since we don't really store those anywhere else.
36+
for ty in self.body.local_decls.iter().map(|local| local.ty) {
37+
if !ty.has_opaque_types() {
38+
continue;
39+
}
40+
41+
let tcx = self.infcx.tcx;
42+
let ControlFlow::Break((opaque_def_id, offending_region_idx, location)) = ty
43+
.visit_with(&mut FindOpaqueRegion {
44+
regioncx: &self.regioncx,
45+
tcx,
46+
borrow_region: borrow.region,
47+
})
48+
else {
49+
continue;
50+
};
51+
52+
// If an opaque explicitly captures a lifetime, then no need to point it out.
53+
if tcx.opt_precise_capturing_args(opaque_def_id).is_some() {
54+
continue;
55+
}
56+
57+
// If one of the opaque's bounds mentions the region, then no need to
58+
// point it out, since it would've been captured on edition 2021 as well.
59+
//
60+
// Also, while we're at it, collect all the lifetimes that the opaque
61+
// *does* mention. We'll use that for the `+ use<'a>` suggestion below.
62+
let mut visitor = CheckExplicitRegionMentionAndCollectGenerics {
63+
tcx,
64+
offending_region_idx,
65+
seen_opaques: [opaque_def_id].into_iter().collect(),
66+
seen_lifetimes: Default::default(),
67+
};
68+
if tcx
69+
.explicit_item_bounds(opaque_def_id)
70+
.skip_binder()
71+
.visit_with(&mut visitor)
72+
.is_break()
73+
{
74+
continue;
75+
}
76+
77+
// If we successfully located a terminator, then point it out
78+
// and provide a suggestion if it's local.
79+
match self.body.stmt_at(location) {
80+
Either::Right(mir::Terminator { source_info, .. }) => {
81+
diag.span_note(
82+
source_info.span,
83+
"this call may capture more lifetimes since Rust 2024 \
84+
has adjusted `impl Trait` lifetime capture rules",
85+
);
86+
let mut seen_generics: Vec<_> =
87+
visitor.seen_lifetimes.iter().map(ToString::to_string).collect();
88+
// Capture all in-scope ty/const params.
89+
seen_generics.extend(
90+
ty::GenericArgs::identity_for_item(tcx, opaque_def_id)
91+
.iter()
92+
.filter(|arg| {
93+
matches!(
94+
arg.unpack(),
95+
ty::GenericArgKind::Type(_) | ty::GenericArgKind::Const(_)
96+
)
97+
})
98+
.map(|arg| arg.to_string()),
99+
);
100+
if opaque_def_id.is_local() {
101+
diag.span_suggestion_verbose(
102+
tcx.def_span(opaque_def_id).shrink_to_hi(),
103+
"add a `use<..>` precise capturing bound to avoid overcapturing",
104+
format!(" + use<{}>", seen_generics.join(", ")),
105+
Applicability::MaybeIncorrect,
106+
);
107+
} else {
108+
diag.span_help(
109+
tcx.def_span(opaque_def_id),
110+
format!(
111+
"if you can modify this crate, add a `use<..>` precise \
112+
capturing bound to avoid overcapturing: `+ use<{}>`",
113+
seen_generics.join(", ")
114+
),
115+
);
116+
}
117+
return;
118+
}
119+
Either::Left(_) => {}
120+
}
121+
}
122+
}
123+
}
124+
125+
/// This visitor contains the bulk of the logic for this lint.
126+
struct FindOpaqueRegion<'a, 'tcx> {
127+
tcx: TyCtxt<'tcx>,
128+
regioncx: &'a RegionInferenceContext<'tcx>,
129+
borrow_region: ty::RegionVid,
130+
}
131+
132+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for FindOpaqueRegion<'_, 'tcx> {
133+
type Result = ControlFlow<(DefId, usize, Location), ()>;
134+
135+
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
136+
// If we find an opaque in a local ty, then for each of its captured regions,
137+
// try to find a path between that captured regions and our borrow region...
138+
if let ty::Alias(ty::Opaque, opaque) = *ty.kind()
139+
&& let hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl: None } =
140+
self.tcx.opaque_ty_origin(opaque.def_id)
141+
{
142+
let variances = self.tcx.variances_of(opaque.def_id);
143+
for (idx, (arg, variance)) in std::iter::zip(opaque.args, variances).enumerate() {
144+
// Skip uncaptured args.
145+
if *variance == ty::Bivariant {
146+
continue;
147+
}
148+
// We only care about regions.
149+
let Some(opaque_region) = arg.as_region() else {
150+
continue;
151+
};
152+
// Don't try to convert a late-bound region, which shouldn't exist anyways (yet).
153+
if opaque_region.is_bound() {
154+
continue;
155+
}
156+
let opaque_region_vid = self.regioncx.to_region_vid(opaque_region);
157+
158+
// Find a path between the borrow region and our opaque capture.
159+
if let Some((path, _)) =
160+
self.regioncx.find_constraint_paths_between_regions(self.borrow_region, |r| {
161+
r == opaque_region_vid
162+
})
163+
{
164+
for constraint in path {
165+
// If we find a call in this path, then check if it defines the opaque.
166+
if let ConstraintCategory::CallArgument(Some(call_ty)) = constraint.category
167+
&& let ty::FnDef(call_def_id, _) = *call_ty.kind()
168+
// This function defines the opaque :D
169+
&& call_def_id == parent
170+
&& let Locations::Single(location) = constraint.locations
171+
{
172+
return ControlFlow::Break((opaque.def_id, idx, location));
173+
}
174+
}
175+
}
176+
}
177+
}
178+
179+
ty.super_visit_with(self)
180+
}
181+
}
182+
183+
struct CheckExplicitRegionMentionAndCollectGenerics<'tcx> {
184+
tcx: TyCtxt<'tcx>,
185+
offending_region_idx: usize,
186+
seen_opaques: FxIndexSet<DefId>,
187+
seen_lifetimes: FxIndexSet<Symbol>,
188+
}
189+
190+
impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for CheckExplicitRegionMentionAndCollectGenerics<'tcx> {
191+
type Result = ControlFlow<(), ()>;
192+
193+
fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
194+
match *ty.kind() {
195+
ty::Alias(ty::Opaque, opaque) => {
196+
if self.seen_opaques.insert(opaque.def_id) {
197+
for (bound, _) in self
198+
.tcx
199+
.explicit_item_bounds(opaque.def_id)
200+
.iter_instantiated_copied(self.tcx, opaque.args)
201+
{
202+
bound.visit_with(self)?;
203+
}
204+
}
205+
ControlFlow::Continue(())
206+
}
207+
_ => ty.super_visit_with(self),
208+
}
209+
}
210+
211+
fn visit_region(&mut self, r: ty::Region<'tcx>) -> Self::Result {
212+
match r.kind() {
213+
ty::ReEarlyParam(param) => {
214+
if param.index as usize == self.offending_region_idx {
215+
ControlFlow::Break(())
216+
} else {
217+
self.seen_lifetimes.insert(param.name);
218+
ControlFlow::Continue(())
219+
}
220+
}
221+
_ => ControlFlow::Continue(()),
222+
}
223+
}
224+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
//@ edition: 2024
2+
//@ compile-flags: -Zunstable-options
3+
4+
use std::fmt::Display;
5+
6+
pub fn hello(x: &Vec<i32>) -> impl Display { 0 }
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ aux-build: foreign.rs
2+
3+
extern crate foreign;
4+
5+
fn main() {
6+
let mut x = vec![];
7+
let h = foreign::hello(&x);
8+
//~^ NOTE this call may capture more lifetimes since Rust 2024
9+
//~| NOTE immutable borrow occurs here
10+
x.push(0);
11+
//~^ ERROR cannot borrow `x` as mutable
12+
//~| NOTE mutable borrow occurs here
13+
println!("{h}");
14+
//~^ NOTE immutable borrow later used here
15+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
2+
--> $DIR/foreign-2021.rs:10:5
3+
|
4+
LL | let h = foreign::hello(&x);
5+
| -- immutable borrow occurs here
6+
...
7+
LL | x.push(0);
8+
| ^^^^^^^^^ mutable borrow occurs here
9+
...
10+
LL | println!("{h}");
11+
| --- immutable borrow later used here
12+
|
13+
note: this call may capture more lifetimes since Rust 2024 has adjusted `impl Trait` lifetime capture rules
14+
--> $DIR/foreign-2021.rs:7:13
15+
|
16+
LL | let h = foreign::hello(&x);
17+
| ^^^^^^^^^^^^^^^^^^
18+
help: if you can modify this crate, add a `use<..>` precise capturing bound to avoid overcapturing: `+ use<>`
19+
--> $DIR/auxiliary/foreign.rs:6:31
20+
|
21+
LL | pub fn hello(x: &Vec<i32>) -> impl Display { 0 }
22+
| ^^^^^^^^^^^^
23+
24+
error: aborting due to 1 previous error
25+
26+
For more information about this error, try `rustc --explain E0502`.
Lines changed: 190 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,190 @@
1+
//@ edition: 2024
2+
//@ compile-flags: -Zunstable-options
3+
4+
use std::fmt::Display;
5+
6+
fn display_len<T>(x: &Vec<T>) -> impl Display {
7+
//~^ NOTE in this expansion of desugaring of `impl Trait`
8+
//~| NOTE in this expansion of desugaring of `impl Trait`
9+
//~| NOTE in this expansion of desugaring of `impl Trait`
10+
//~| NOTE in this expansion of desugaring of `impl Trait`
11+
//~| NOTE in this expansion of desugaring of `impl Trait`
12+
x.len()
13+
}
14+
15+
fn conflicting_borrow() {
16+
let mut x = vec![];
17+
let a = display_len(&x);
18+
//~^ NOTE this call may capture more lifetimes since Rust 2024
19+
//~| NOTE immutable borrow occurs here
20+
x.push(1);
21+
//~^ ERROR cannot borrow `x` as mutable because it is also borrowed as immutable
22+
//~| NOTE mutable borrow occurs here
23+
println!("{a}");
24+
//~^ NOTE immutable borrow later used here
25+
}
26+
27+
fn needs_static() {
28+
let x = vec![1];
29+
//~^ NOTE binding `x` declared here
30+
let a = display_len(&x);
31+
//~^ ERROR `x` does not live long enough
32+
//~| NOTE this call may capture more lifetimes since Rust 2024
33+
//~| NOTE argument requires that `x` is borrowed for `'static`
34+
//~| NOTE borrowed value does not live long enoug
35+
36+
fn needs_static(_: impl Sized + 'static) {}
37+
needs_static(a);
38+
}
39+
//~^ NOTE `x` dropped here while still borrowed
40+
41+
fn is_moved() {
42+
let x = vec![1];
43+
//~^ NOTE binding `x` declared here
44+
let a = display_len(&x);
45+
//~^ NOTE this call may capture more lifetimes since Rust 2024
46+
//~| NOTE borrow of `x` occurs here
47+
48+
fn mv(_: impl Sized) {}
49+
mv(x);
50+
//~^ ERROR cannot move out of `x` because it is borrowed
51+
//~| NOTE move out of `x` occurs here
52+
}
53+
//~^ NOTE borrow might be used here, when `a` is dropped
54+
55+
fn display_len_mut<T>(x: &mut Vec<T>) -> impl Display {
56+
//~^ NOTE in this expansion of desugaring of `impl Trait`
57+
//~| NOTE in this expansion of desugaring of `impl Trait`
58+
//~| NOTE in this expansion of desugaring of `impl Trait`
59+
x.len()
60+
}
61+
62+
fn conflicting_borrow_mut() {
63+
let mut x = vec![];
64+
let a = display_len_mut(&mut x);
65+
//~^ NOTE this call may capture more lifetimes since Rust 2024
66+
//~| NOTE first mutable borrow occurs here
67+
x.push(1);
68+
//~^ ERROR cannot borrow `x` as mutable more than once
69+
//~| NOTE second mutable borrow occurs here
70+
println!("{a}");
71+
//~^ NOTE first borrow later used here
72+
}
73+
74+
fn needs_static_mut() {
75+
let mut x = vec![1];
76+
//~^ NOTE binding `x` declared here
77+
let a = display_len_mut(&mut x);
78+
//~^ ERROR `x` does not live long enough
79+
//~| NOTE this call may capture more lifetimes since Rust 2024
80+
//~| NOTE argument requires that `x` is borrowed for `'static`
81+
//~| NOTE borrowed value does not live long enough
82+
83+
fn needs_static(_: impl Sized + 'static) {}
84+
needs_static(a);
85+
}
86+
//~^ NOTE `x` dropped here while still borrowed
87+
88+
fn is_move_mut() {
89+
let mut x = vec![1];
90+
//~^ NOTE binding `x` declared here
91+
let a = display_len_mut(&mut x);
92+
//~^ NOTE this call may capture more lifetimes since Rust 2024
93+
//~| NOTE borrow of `x` occurs here
94+
95+
fn mv(_: impl Sized) {}
96+
mv(x);
97+
//~^ ERROR cannot move out of `x` because it is borrowed
98+
//~| NOTE move out of `x` occurs here
99+
}
100+
//~^ NOTE borrow might be used here, when `a` is dropped
101+
102+
struct S { f: i32 }
103+
104+
fn display_field<T: Copy + Display>(t: &T) -> impl Display {
105+
//~^ NOTE in this expansion of desugaring of `impl Trait`
106+
//~| NOTE in this expansion of desugaring of `impl Trait`
107+
//~| NOTE in this expansion of desugaring of `impl Trait`
108+
*t
109+
}
110+
111+
fn conflicting_borrow_field() {
112+
let mut s = S { f: 0 };
113+
let a = display_field(&s.f);
114+
//~^ NOTE this call may capture more lifetimes since Rust 2024
115+
//~| NOTE `s.f` is borrowed here
116+
s.f = 1;
117+
//~^ ERROR cannot assign to `s.f` because it is borrowed
118+
//~| NOTE `s.f` is assigned to here but it was already borrowed
119+
println!("{a}");
120+
//~^ NOTE borrow later used here
121+
}
122+
123+
fn display_field_mut<T: Copy + Display>(t: &mut T) -> impl Display {
124+
*t
125+
}
126+
127+
fn conflicting_borrow_field_mut() {
128+
let mut s = S { f: 0 };
129+
let a = display_field(&mut s.f);
130+
//~^ NOTE this call may capture more lifetimes since Rust 2024
131+
//~| NOTE `s.f` is borrowed here
132+
s.f = 1;
133+
//~^ ERROR cannot assign to `s.f` because it is borrowed
134+
//~| NOTE `s.f` is assigned to here but it was already borrowed
135+
println!("{a}");
136+
//~^ NOTE borrow later used here
137+
}
138+
139+
fn field_move() {
140+
let mut s = S { f: 0 };
141+
let a = display_field(&mut s.f);
142+
//~^ NOTE this call may capture more lifetimes since Rust 2024
143+
//~| NOTE `s.f` is borrowed here
144+
s.f;
145+
//~^ ERROR cannot use `s.f` because it was mutably borrowed
146+
//~| NOTE use of borrowed `s.f`
147+
println!("{a}");
148+
//~^ NOTE borrow later used here
149+
}
150+
151+
struct Z {
152+
f: Vec<i32>,
153+
}
154+
155+
fn live_long() {
156+
let x;
157+
{
158+
let z = Z { f: vec![1] };
159+
//~^ NOTE binding `z` declared here
160+
x = display_len(&z.f);
161+
//~^ ERROR `z.f` does not live long enough
162+
//~| NOTE this call may capture more lifetimes since Rust 2024
163+
//~| NOTE values in a scope are dropped in the opposite order they are defined
164+
//~| NOTE borrowed value does not live long enough
165+
}
166+
//~^ NOTE `z.f` dropped here while still borrowed
167+
}
168+
//~^ NOTE borrow might be used here, when `x` is dropped
169+
170+
fn temp() {
171+
let x = { let x = display_len(&mut vec![0]); x };
172+
//~^ ERROR temporary value dropped while borrowed
173+
//~| NOTE this call may capture more lifetimes since Rust 2024
174+
//~| NOTE consider using a `let` binding to create a longer lived value
175+
//~| NOTE borrow later used here
176+
//~| NOTE temporary value is freed at the end of this statement
177+
}
178+
179+
// FIXME: This doesn't display a useful Rust 2024 suggestion :(
180+
fn returned() -> impl Sized {
181+
let x = vec![0];
182+
//~^ NOTE binding `x` declared here
183+
display_len(&x)
184+
//~^ ERROR `x` does not live long enough
185+
//~| NOTE borrowed value does not live long enough
186+
//~| NOTE argument requires that `x` is borrowed for `'static`
187+
}
188+
//~^ NOTE `x` dropped here while still borrowed
189+
190+
fn main() {}
Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
error[E0597]: `x` does not live long enough
2+
--> $DIR/migration-note.rs:183:17
3+
|
4+
LL | let x = vec![0];
5+
| - binding `x` declared here
6+
LL |
7+
LL | display_len(&x)
8+
| ------------^^-
9+
| | |
10+
| | borrowed value does not live long enough
11+
| argument requires that `x` is borrowed for `'static`
12+
...
13+
LL | }
14+
| - `x` dropped here while still borrowed
15+
16+
error[E0502]: cannot borrow `x` as mutable because it is also borrowed as immutable
17+
--> $DIR/migration-note.rs:20:5
18+
|
19+
LL | let a = display_len(&x);
20+
| -- immutable borrow occurs here
21+
...
22+
LL | x.push(1);
23+
| ^^^^^^^^^ mutable borrow occurs here
24+
...
25+
LL | println!("{a}");
26+
| --- immutable borrow later used here
27+
|
28+
note: this call may capture more lifetimes since Rust 2024 has adjusted `impl Trait` lifetime capture rules
29+
--> $DIR/migration-note.rs:17:13
30+
|
31+
LL | let a = display_len(&x);
32+
| ^^^^^^^^^^^^^^^
33+
help: add a `use<..>` precise capturing bound to avoid overcapturing
34+
|
35+
LL | fn display_len<T>(x: &Vec<T>) -> impl Display + use<T> {
36+
| ++++++++
37+
38+
error[E0597]: `x` does not live long enough
39+
--> $DIR/migration-note.rs:30:25
40+
|
41+
LL | let x = vec![1];
42+
| - binding `x` declared here
43+
LL |
44+
LL | let a = display_len(&x);
45+
| ------------^^-
46+
| | |
47+
| | borrowed value does not live long enough
48+
| argument requires that `x` is borrowed for `'static`
49+
...
50+
LL | }
51+
| - `x` dropped here while still borrowed
52+
|
53+
note: this call may capture more lifetimes since Rust 2024 has adjusted `impl Trait` lifetime capture rules
54+
--> $DIR/migration-note.rs:30:13
55+
|
56+
LL | let a = display_len(&x);
57+
| ^^^^^^^^^^^^^^^
58+
help: add a `use<..>` precise capturing bound to avoid overcapturing
59+
|
60+
LL | fn display_len<T>(x: &Vec<T>) -> impl Display + use<T> {
61+
| ++++++++
62+
63+
error[E0505]: cannot move out of `x` because it is borrowed
64+
--> $DIR/migration-note.rs:49:8
65+
|
66+
LL | let x = vec![1];
67+
| - binding `x` declared here
68+
LL |
69+
LL | let a = display_len(&x);
70+
| -- borrow of `x` occurs here
71+
...
72+
LL | mv(x);
73+
| ^ move out of `x` occurs here
74+
...
75+
LL | }
76+
| - borrow might be used here, when `a` is dropped and runs the destructor for type `impl std::fmt::Display`
77+
|
78+
note: this call may capture more lifetimes since Rust 2024 has adjusted `impl Trait` lifetime capture rules
79+
--> $DIR/migration-note.rs:44:13
80+
|
81+
LL | let a = display_len(&x);
82+
| ^^^^^^^^^^^^^^^
83+
help: add a `use<..>` precise capturing bound to avoid overcapturing
84+
|
85+
LL | fn display_len<T>(x: &Vec<T>) -> impl Display + use<T> {
86+
| ++++++++
87+
help: consider cloning the value if the performance cost is acceptable
88+
|
89+
LL | let a = display_len(&x.clone());
90+
| ++++++++
91+
92+
error[E0499]: cannot borrow `x` as mutable more than once at a time
93+
--> $DIR/migration-note.rs:67:5
94+
|
95+
LL | let a = display_len_mut(&mut x);
96+
| ------ first mutable borrow occurs here
97+
...
98+
LL | x.push(1);
99+
| ^ second mutable borrow occurs here
100+
...
101+
LL | println!("{a}");
102+
| --- first borrow later used here
103+
|
104+
note: this call may capture more lifetimes since Rust 2024 has adjusted `impl Trait` lifetime capture rules
105+
--> $DIR/migration-note.rs:64:13
106+
|
107+
LL | let a = display_len_mut(&mut x);
108+
| ^^^^^^^^^^^^^^^^^^^^^^^
109+
help: add a `use<..>` precise capturing bound to avoid overcapturing
110+
|
111+
LL | fn display_len_mut<T>(x: &mut Vec<T>) -> impl Display + use<T> {
112+
| ++++++++
113+
114+
error[E0597]: `x` does not live long enough
115+
--> $DIR/migration-note.rs:77:29
116+
|
117+
LL | let mut x = vec![1];
118+
| ----- binding `x` declared here
119+
LL |
120+
LL | let a = display_len_mut(&mut x);
121+
| ----------------^^^^^^-
122+
| | |
123+
| | borrowed value does not live long enough
124+
| argument requires that `x` is borrowed for `'static`
125+
...
126+
LL | }
127+
| - `x` dropped here while still borrowed
128+
|
129+
note: this call may capture more lifetimes since Rust 2024 has adjusted `impl Trait` lifetime capture rules
130+
--> $DIR/migration-note.rs:77:13
131+
|
132+
LL | let a = display_len_mut(&mut x);
133+
| ^^^^^^^^^^^^^^^^^^^^^^^
134+
help: add a `use<..>` precise capturing bound to avoid overcapturing
135+
|
136+
LL | fn display_len_mut<T>(x: &mut Vec<T>) -> impl Display + use<T> {
137+
| ++++++++
138+
139+
error[E0505]: cannot move out of `x` because it is borrowed
140+
--> $DIR/migration-note.rs:96:8
141+
|
142+
LL | let mut x = vec![1];
143+
| ----- binding `x` declared here
144+
LL |
145+
LL | let a = display_len_mut(&mut x);
146+
| ------ borrow of `x` occurs here
147+
...
148+
LL | mv(x);
149+
| ^ move out of `x` occurs here
150+
...
151+
LL | }
152+
| - borrow might be used here, when `a` is dropped and runs the destructor for type `impl std::fmt::Display`
153+
|
154+
note: this call may capture more lifetimes since Rust 2024 has adjusted `impl Trait` lifetime capture rules
155+
--> $DIR/migration-note.rs:91:13
156+
|
157+
LL | let a = display_len_mut(&mut x);
158+
| ^^^^^^^^^^^^^^^^^^^^^^^
159+
help: add a `use<..>` precise capturing bound to avoid overcapturing
160+
|
161+
LL | fn display_len_mut<T>(x: &mut Vec<T>) -> impl Display + use<T> {
162+
| ++++++++
163+
help: consider cloning the value if the performance cost is acceptable
164+
|
165+
LL | let a = display_len_mut(&mut x.clone());
166+
| ++++++++
167+
168+
error[E0506]: cannot assign to `s.f` because it is borrowed
169+
--> $DIR/migration-note.rs:116:5
170+
|
171+
LL | let a = display_field(&s.f);
172+
| ---- `s.f` is borrowed here
173+
...
174+
LL | s.f = 1;
175+
| ^^^^^^^ `s.f` is assigned to here but it was already borrowed
176+
...
177+
LL | println!("{a}");
178+
| --- borrow later used here
179+
|
180+
note: this call may capture more lifetimes since Rust 2024 has adjusted `impl Trait` lifetime capture rules
181+
--> $DIR/migration-note.rs:113:13
182+
|
183+
LL | let a = display_field(&s.f);
184+
| ^^^^^^^^^^^^^^^^^^^
185+
help: add a `use<..>` precise capturing bound to avoid overcapturing
186+
|
187+
LL | fn display_field<T: Copy + Display>(t: &T) -> impl Display + use<T> {
188+
| ++++++++
189+
190+
error[E0506]: cannot assign to `s.f` because it is borrowed
191+
--> $DIR/migration-note.rs:132:5
192+
|
193+
LL | let a = display_field(&mut s.f);
194+
| -------- `s.f` is borrowed here
195+
...
196+
LL | s.f = 1;
197+
| ^^^^^^^ `s.f` is assigned to here but it was already borrowed
198+
...
199+
LL | println!("{a}");
200+
| --- borrow later used here
201+
|
202+
note: this call may capture more lifetimes since Rust 2024 has adjusted `impl Trait` lifetime capture rules
203+
--> $DIR/migration-note.rs:129:13
204+
|
205+
LL | let a = display_field(&mut s.f);
206+
| ^^^^^^^^^^^^^^^^^^^^^^^
207+
help: add a `use<..>` precise capturing bound to avoid overcapturing
208+
|
209+
LL | fn display_field<T: Copy + Display>(t: &T) -> impl Display + use<T> {
210+
| ++++++++
211+
212+
error[E0503]: cannot use `s.f` because it was mutably borrowed
213+
--> $DIR/migration-note.rs:144:5
214+
|
215+
LL | let a = display_field(&mut s.f);
216+
| -------- `s.f` is borrowed here
217+
...
218+
LL | s.f;
219+
| ^^^ use of borrowed `s.f`
220+
...
221+
LL | println!("{a}");
222+
| --- borrow later used here
223+
|
224+
note: this call may capture more lifetimes since Rust 2024 has adjusted `impl Trait` lifetime capture rules
225+
--> $DIR/migration-note.rs:141:13
226+
|
227+
LL | let a = display_field(&mut s.f);
228+
| ^^^^^^^^^^^^^^^^^^^^^^^
229+
help: add a `use<..>` precise capturing bound to avoid overcapturing
230+
|
231+
LL | fn display_field<T: Copy + Display>(t: &T) -> impl Display + use<T> {
232+
| ++++++++
233+
234+
error[E0597]: `z.f` does not live long enough
235+
--> $DIR/migration-note.rs:160:25
236+
|
237+
LL | let z = Z { f: vec![1] };
238+
| - binding `z` declared here
239+
LL |
240+
LL | x = display_len(&z.f);
241+
| ^^^^ borrowed value does not live long enough
242+
...
243+
LL | }
244+
| - `z.f` dropped here while still borrowed
245+
LL |
246+
LL | }
247+
| - borrow might be used here, when `x` is dropped and runs the destructor for type `impl std::fmt::Display`
248+
|
249+
= note: values in a scope are dropped in the opposite order they are defined
250+
note: this call may capture more lifetimes since Rust 2024 has adjusted `impl Trait` lifetime capture rules
251+
--> $DIR/migration-note.rs:160:13
252+
|
253+
LL | x = display_len(&z.f);
254+
| ^^^^^^^^^^^^^^^^^
255+
help: add a `use<..>` precise capturing bound to avoid overcapturing
256+
|
257+
LL | fn display_len<T>(x: &Vec<T>) -> impl Display + use<T> {
258+
| ++++++++
259+
260+
error[E0716]: temporary value dropped while borrowed
261+
--> $DIR/migration-note.rs:171:40
262+
|
263+
LL | let x = { let x = display_len(&mut vec![0]); x };
264+
| ^^^^^^^ - - borrow later used here
265+
| | |
266+
| | temporary value is freed at the end of this statement
267+
| creates a temporary value which is freed while still in use
268+
|
269+
= note: consider using a `let` binding to create a longer lived value
270+
note: this call may capture more lifetimes since Rust 2024 has adjusted `impl Trait` lifetime capture rules
271+
--> $DIR/migration-note.rs:171:23
272+
|
273+
LL | let x = { let x = display_len(&mut vec![0]); x };
274+
| ^^^^^^^^^^^^^^^^^^^^^^^^^
275+
= note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
276+
help: add a `use<..>` precise capturing bound to avoid overcapturing
277+
|
278+
LL | fn display_len<T>(x: &Vec<T>) -> impl Display + use<T> {
279+
| ++++++++
280+
281+
error: aborting due to 12 previous errors
282+
283+
Some errors have detailed explanations: E0499, E0502, E0503, E0505, E0506, E0597, E0716.
284+
For more information about an error, try `rustc --explain E0499`.

0 commit comments

Comments
 (0)
Please sign in to comment.