Skip to content
This repository was archived by the owner on May 28, 2025. It is now read-only.

Commit c8b8378

Browse files
committedOct 31, 2024·
Auto merge of rust-lang#131186 - compiler-errors:precise-capturing-borrowck, r=estebank
Try to point out when edition 2024 lifetime capture rules cause borrowck issues Lifetime capture rules in 2024 are modified to capture more lifetimes, which sometimes lead to some non-local borrowck errors. This PR attempts to link these back together with a useful note pointing out the capture rule changes. This is not a blocking concern, but I'd appreciate feedback (though, again, I'd like to stress that I don't want to block this PR on this): I'm worried about this note drowning in the sea of other diagnostics that borrowck emits. I was tempted to change the level of the note to `.span_warn` just so it would show up in a different color. Thoughts? Fixes rust-lang#130545 Opening as a draft first since it's stacked on rust-lang#131183. r? `@ghost`
2 parents 75eff9a + c145779 commit c8b8378

File tree

27 files changed

+807
-45
lines changed

27 files changed

+807
-45
lines changed
 

‎compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -272,7 +272,7 @@ enum ImplTraitContext {
272272
/// Example: `fn foo() -> impl Debug`, where `impl Debug` is conceptually
273273
/// equivalent to a new opaque type like `type T = impl Debug; fn foo() -> T`.
274274
///
275-
OpaqueTy { origin: hir::OpaqueTyOrigin },
275+
OpaqueTy { origin: hir::OpaqueTyOrigin<LocalDefId> },
276276
/// `impl Trait` is unstably accepted in this position.
277277
FeatureGated(ImplTraitPosition, Symbol),
278278
/// `impl Trait` is not accepted in this position.
@@ -1416,7 +1416,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14161416
fn lower_opaque_impl_trait(
14171417
&mut self,
14181418
span: Span,
1419-
origin: hir::OpaqueTyOrigin,
1419+
origin: hir::OpaqueTyOrigin<LocalDefId>,
14201420
opaque_ty_node_id: NodeId,
14211421
bounds: &GenericBounds,
14221422
itctx: ImplTraitContext,
@@ -1458,7 +1458,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
14581458
fn lower_opaque_inner(
14591459
&mut self,
14601460
opaque_ty_node_id: NodeId,
1461-
origin: hir::OpaqueTyOrigin,
1461+
origin: hir::OpaqueTyOrigin<LocalDefId>,
14621462
opaque_ty_span: Span,
14631463
lower_item_bounds: impl FnOnce(&mut Self) -> &'hir [hir::GenericBound<'hir>],
14641464
) -> hir::TyKind<'hir> {

‎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 RPITITs.
27+
pub(crate) fn note_due_to_edition_2024_opaque_capture_rules(
28+
&self,
29+
borrow: &BorrowData<'tcx>,
30+
diag: &mut Diag<'_>,
31+
) {
32+
// We look at all the locals. Why locals? Because it's the best thing
33+
// I could think of that's correlated with the *instantiated* higer-ranked
34+
// binder for calls, since we don't really store those anywhere else.
35+
for ty in self.body.local_decls.iter().map(|local| local.ty) {
36+
if !ty.has_opaque_types() {
37+
continue;
38+
}
39+
40+
let tcx = self.infcx.tcx;
41+
let ControlFlow::Break((opaque_def_id, offending_region_idx, location)) = ty
42+
.visit_with(&mut FindOpaqueRegion {
43+
regioncx: &self.regioncx,
44+
tcx,
45+
borrow_region: borrow.region,
46+
})
47+
else {
48+
continue;
49+
};
50+
51+
// If an opaque explicitly captures a lifetime, then no need to point it out.
52+
// FIXME: We should be using a better heuristic for `use<>`.
53+
if tcx.rendered_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 than intended, \
84+
because Rust 2024 has adjusted the `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 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 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+
}

‎compiler/rustc_borrowck/src/region_infer/opaque_types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -502,7 +502,7 @@ impl<'tcx> LazyOpaqueTyEnv<'tcx> {
502502
}
503503

504504
let &Self { tcx, def_id, .. } = self;
505-
let origin = tcx.opaque_type_origin(def_id);
505+
let origin = tcx.local_opaque_ty_origin(def_id);
506506
let parent = match origin {
507507
hir::OpaqueTyOrigin::FnReturn { parent, .. }
508508
| hir::OpaqueTyOrigin::AsyncFn { parent, .. }

‎compiler/rustc_hir/src/hir.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2746,7 +2746,7 @@ pub struct OpaqueTy<'hir> {
27462746
pub hir_id: HirId,
27472747
pub def_id: LocalDefId,
27482748
pub bounds: GenericBounds<'hir>,
2749-
pub origin: OpaqueTyOrigin,
2749+
pub origin: OpaqueTyOrigin<LocalDefId>,
27502750
pub span: Span,
27512751
}
27522752

@@ -2784,33 +2784,35 @@ pub struct PreciseCapturingNonLifetimeArg {
27842784
pub res: Res,
27852785
}
27862786

2787-
#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)]
2787+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
2788+
#[derive(HashStable_Generic, Encodable, Decodable)]
27882789
pub enum RpitContext {
27892790
Trait,
27902791
TraitImpl,
27912792
}
27922793

27932794
/// From whence the opaque type came.
2794-
#[derive(Copy, Clone, PartialEq, Eq, Debug, HashStable_Generic)]
2795-
pub enum OpaqueTyOrigin {
2795+
#[derive(Copy, Clone, PartialEq, Eq, Debug)]
2796+
#[derive(HashStable_Generic, Encodable, Decodable)]
2797+
pub enum OpaqueTyOrigin<D> {
27962798
/// `-> impl Trait`
27972799
FnReturn {
27982800
/// The defining function.
2799-
parent: LocalDefId,
2801+
parent: D,
28002802
// Whether this is an RPITIT (return position impl trait in trait)
28012803
in_trait_or_impl: Option<RpitContext>,
28022804
},
28032805
/// `async fn`
28042806
AsyncFn {
28052807
/// The defining function.
2806-
parent: LocalDefId,
2808+
parent: D,
28072809
// Whether this is an AFIT (async fn in trait)
28082810
in_trait_or_impl: Option<RpitContext>,
28092811
},
28102812
/// type aliases: `type Foo = impl Trait;`
28112813
TyAlias {
28122814
/// The type alias or associated type parent of the TAIT/ATPIT
2813-
parent: LocalDefId,
2815+
parent: D,
28142816
/// associated types in impl blocks for traits.
28152817
in_assoc_ty: bool,
28162818
},

‎compiler/rustc_hir_analysis/src/check/check.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ fn check_opaque_meets_bounds<'tcx>(
268268
tcx: TyCtxt<'tcx>,
269269
def_id: LocalDefId,
270270
span: Span,
271-
origin: &hir::OpaqueTyOrigin,
271+
origin: &hir::OpaqueTyOrigin<LocalDefId>,
272272
) -> Result<(), ErrorGuaranteed> {
273273
let defining_use_anchor = match *origin {
274274
hir::OpaqueTyOrigin::FnReturn { parent, .. }
@@ -677,7 +677,7 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) {
677677
DefKind::OpaqueTy => {
678678
check_opaque_precise_captures(tcx, def_id);
679679

680-
let origin = tcx.opaque_type_origin(def_id);
680+
let origin = tcx.local_opaque_ty_origin(def_id);
681681
if let hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
682682
| hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. } = origin
683683
&& let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(fn_def_id)

‎compiler/rustc_hir_analysis/src/collect.rs

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ pub fn provide(providers: &mut Providers) {
8686
impl_trait_header,
8787
coroutine_kind,
8888
coroutine_for_closure,
89-
is_type_alias_impl_trait,
89+
opaque_ty_origin,
9090
rendered_precise_capturing_args,
9191
..*providers
9292
};
@@ -1759,9 +1759,18 @@ fn coroutine_for_closure(tcx: TyCtxt<'_>, def_id: LocalDefId) -> DefId {
17591759
def_id.to_def_id()
17601760
}
17611761

1762-
fn is_type_alias_impl_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> bool {
1763-
let opaque = tcx.hir().expect_opaque_ty(def_id);
1764-
matches!(opaque.origin, hir::OpaqueTyOrigin::TyAlias { .. })
1762+
fn opaque_ty_origin<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> hir::OpaqueTyOrigin<DefId> {
1763+
match tcx.hir_node_by_def_id(def_id).expect_opaque_ty().origin {
1764+
hir::OpaqueTyOrigin::FnReturn { parent, in_trait_or_impl } => {
1765+
hir::OpaqueTyOrigin::FnReturn { parent: parent.to_def_id(), in_trait_or_impl }
1766+
}
1767+
hir::OpaqueTyOrigin::AsyncFn { parent, in_trait_or_impl } => {
1768+
hir::OpaqueTyOrigin::AsyncFn { parent: parent.to_def_id(), in_trait_or_impl }
1769+
}
1770+
hir::OpaqueTyOrigin::TyAlias { parent, in_assoc_ty } => {
1771+
hir::OpaqueTyOrigin::TyAlias { parent: parent.to_def_id(), in_assoc_ty }
1772+
}
1773+
}
17651774
}
17661775

17671776
fn rendered_precise_capturing_args<'tcx>(

‎compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ pub mod errors;
2020
pub mod generics;
2121
mod lint;
2222

23+
use std::assert_matches::assert_matches;
2324
use std::slice;
2425

2526
use rustc_ast::TraitObjectSyntax;
@@ -1811,7 +1812,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
18111812
match path.res {
18121813
Res::Def(DefKind::OpaqueTy, did) => {
18131814
// Check for desugared `impl Trait`.
1814-
assert!(tcx.is_type_alias_impl_trait(did));
1815+
assert_matches!(tcx.opaque_ty_origin(did), hir::OpaqueTyOrigin::TyAlias { .. });
18151816
let item_segment = path.segments.split_last().unwrap();
18161817
let _ = self
18171818
.prohibit_generic_args(item_segment.1.iter(), GenericsArgsErrExtend::OpaqueTy);

‎compiler/rustc_hir_typeck/src/_match.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -601,7 +601,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
601601
_ => return None,
602602
};
603603
let hir::OpaqueTyOrigin::FnReturn { parent: parent_def_id, .. } =
604-
self.tcx.opaque_type_origin(def_id)
604+
self.tcx.local_opaque_ty_origin(def_id)
605605
else {
606606
return None;
607607
};

‎compiler/rustc_infer/src/infer/opaque_types/mod.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,10 @@ impl<'tcx> InferCtxt<'tcx> {
155155
// however in `fn fut() -> impl Future<Output = i32> { async { 42 } }`, where
156156
// it is of no concern, so we only check for TAITs.
157157
if self.can_define_opaque_ty(b_def_id)
158-
&& self.tcx.is_type_alias_impl_trait(b_def_id)
158+
&& matches!(
159+
self.tcx.opaque_ty_origin(b_def_id),
160+
hir::OpaqueTyOrigin::TyAlias { .. }
161+
)
159162
{
160163
self.dcx().emit_err(OpaqueHiddenTypeDiag {
161164
span,

‎compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -316,10 +316,7 @@ provide! { tcx, def_id, other, cdata,
316316
})
317317
.unwrap_or_default()
318318
}
319-
is_type_alias_impl_trait => {
320-
debug_assert_eq!(tcx.def_kind(def_id), DefKind::OpaqueTy);
321-
cdata.root.tables.is_type_alias_impl_trait.get(cdata, def_id.index)
322-
}
319+
opaque_ty_origin => { table }
323320
assumed_wf_types_for_rpitit => { table }
324321
collect_return_position_impl_trait_in_trait_tys => {
325322
Ok(cdata

‎compiler/rustc_metadata/src/rmeta/encoder.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,7 +1188,7 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
11881188
| DefKind::SyntheticCoroutineBody => true,
11891189

11901190
DefKind::OpaqueTy => {
1191-
let origin = tcx.opaque_type_origin(def_id);
1191+
let origin = tcx.local_opaque_ty_origin(def_id);
11921192
if let hir::OpaqueTyOrigin::FnReturn { parent, .. }
11931193
| hir::OpaqueTyOrigin::AsyncFn { parent, .. } = origin
11941194
&& let hir::Node::TraitItem(trait_item) = tcx.hir_node_by_def_id(parent)
@@ -1530,9 +1530,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
15301530
if let DefKind::OpaqueTy = def_kind {
15311531
self.encode_explicit_item_bounds(def_id);
15321532
self.encode_explicit_item_super_predicates(def_id);
1533-
self.tables
1534-
.is_type_alias_impl_trait
1535-
.set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
1533+
record!(self.tables.opaque_ty_origin[def_id] <- self.tcx.opaque_ty_origin(def_id));
15361534
self.encode_precise_capturing_args(def_id);
15371535
}
15381536
if tcx.impl_method_has_trait_impl_trait_tys(def_id)

‎compiler/rustc_metadata/src/rmeta/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,6 @@ define_tables! {
378378
- defaulted:
379379
intrinsic: Table<DefIndex, Option<LazyValue<ty::IntrinsicDef>>>,
380380
is_macro_rules: Table<DefIndex, bool>,
381-
is_type_alias_impl_trait: Table<DefIndex, bool>,
382381
type_alias_is_lazy: Table<DefIndex, bool>,
383382
attr_flags: Table<DefIndex, AttrFlags>,
384383
// The u64 is the crate-local part of the DefPathHash. All hashes in this crate have the same
@@ -468,6 +467,7 @@ define_tables! {
468467
doc_link_resolutions: Table<DefIndex, LazyValue<DocLinkResMap>>,
469468
doc_link_traits_in_scope: Table<DefIndex, LazyArray<DefId>>,
470469
assumed_wf_types_for_rpitit: Table<DefIndex, LazyArray<(Ty<'static>, Span)>>,
470+
opaque_ty_origin: Table<DefIndex, LazyValue<hir::OpaqueTyOrigin<DefId>>>,
471471
}
472472

473473
#[derive(TyEncodable, TyDecodable)]

‎compiler/rustc_middle/src/query/erase.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,7 @@ trivial! {
280280
rustc_hir::IsAsync,
281281
rustc_hir::ItemLocalId,
282282
rustc_hir::LangItem,
283+
rustc_hir::OpaqueTyOrigin<rustc_hir::def_id::DefId>,
283284
rustc_hir::OwnerId,
284285
rustc_hir::Upvar,
285286
rustc_index::bit_set::FiniteBitSet<u32>,

‎compiler/rustc_middle/src/query/mod.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -260,11 +260,10 @@ rustc_queries! {
260260
separate_provide_extern
261261
}
262262

263-
query is_type_alias_impl_trait(key: DefId) -> bool
263+
query opaque_ty_origin(key: DefId) -> hir::OpaqueTyOrigin<DefId>
264264
{
265-
desc { "determine whether the opaque is a type-alias impl trait" }
265+
desc { "determine where the opaque originates from" }
266266
separate_provide_extern
267-
feedable
268267
}
269268

270269
query unsizing_params_for_adt(key: DefId) -> &'tcx rustc_index::bit_set::BitSet<u32>

‎compiler/rustc_middle/src/ty/context.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ use rustc_type_ir::fold::TypeFoldable;
5555
use rustc_type_ir::lang_items::TraitSolverLangItem;
5656
pub use rustc_type_ir::lift::Lift;
5757
use rustc_type_ir::{CollectAndApply, Interner, TypeFlags, WithCachedTypeInfo, search_graph};
58-
use tracing::{debug, trace};
58+
use tracing::{debug, instrument};
5959

6060
use crate::arena::Arena;
6161
use crate::dep_graph::{DepGraph, DepKindStruct};
@@ -2103,11 +2103,9 @@ impl<'tcx> TyCtxt<'tcx> {
21032103
}
21042104

21052105
/// Returns the origin of the opaque type `def_id`.
2106-
#[track_caller]
2107-
pub fn opaque_type_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin {
2108-
let origin = self.hir().expect_opaque_ty(def_id).origin;
2109-
trace!("opaque_type_origin({def_id:?}) => {origin:?}");
2110-
origin
2106+
#[instrument(skip(self), level = "trace", ret)]
2107+
pub fn local_opaque_ty_origin(self, def_id: LocalDefId) -> hir::OpaqueTyOrigin<LocalDefId> {
2108+
self.hir().expect_opaque_ty(def_id).origin
21112109
}
21122110
}
21132111

‎compiler/rustc_middle/src/ty/parameterized.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ trivially_parameterized_over_tcx! {
9494
rustc_hir::def_id::DefId,
9595
rustc_hir::def_id::DefIndex,
9696
rustc_hir::definitions::DefKey,
97+
rustc_hir::OpaqueTyOrigin<rustc_hir::def_id::DefId>,
9798
rustc_index::bit_set::BitSet<u32>,
9899
rustc_index::bit_set::FiniteBitSet<u32>,
99100
rustc_session::cstore::ForeignModule,

‎compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,10 @@ impl<T> Trait<T> for X {
384384
| DefKind::AssocFn
385385
| DefKind::AssocConst
386386
)
387-
&& tcx.is_type_alias_impl_trait(opaque_ty.def_id)
387+
&& matches!(
388+
tcx.opaque_ty_origin(opaque_ty.def_id),
389+
hir::OpaqueTyOrigin::TyAlias { .. }
390+
)
388391
&& !tcx
389392
.opaque_types_defined_by(body_owner_def_id.expect_local())
390393
.contains(&opaque_ty.def_id.expect_local())

‎compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2648,7 +2648,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
26482648
obligation: &PredicateObligation<'tcx>,
26492649
def_id: DefId,
26502650
) -> ErrorGuaranteed {
2651-
let name = match self.tcx.opaque_type_origin(def_id.expect_local()) {
2651+
let name = match self.tcx.local_opaque_ty_origin(def_id.expect_local()) {
26522652
hir::OpaqueTyOrigin::FnReturn { .. } | hir::OpaqueTyOrigin::AsyncFn { .. } => {
26532653
"opaque type".to_string()
26542654
}

‎compiler/rustc_ty_utils/src/assoc.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,7 @@ fn associated_type_for_impl_trait_in_trait(
244244
) -> LocalDefId {
245245
let (hir::OpaqueTyOrigin::FnReturn { parent: fn_def_id, .. }
246246
| hir::OpaqueTyOrigin::AsyncFn { parent: fn_def_id, .. }) =
247-
tcx.opaque_type_origin(opaque_ty_def_id)
247+
tcx.local_opaque_ty_origin(opaque_ty_def_id)
248248
else {
249249
bug!("expected opaque for {opaque_ty_def_id:?}");
250250
};
@@ -281,8 +281,6 @@ fn associated_type_for_impl_trait_in_trait(
281281
// Copy defaultness of the containing function.
282282
trait_assoc_ty.defaultness(tcx.defaultness(fn_def_id));
283283

284-
trait_assoc_ty.is_type_alias_impl_trait(false);
285-
286284
// There are no inferred outlives for the synthesized associated type.
287285
trait_assoc_ty.inferred_outlives_of(&[]);
288286

‎compiler/rustc_ty_utils/src/opaque_types.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
139139
}
140140

141141
// TAITs outside their defining scopes are ignored.
142-
let origin = self.tcx.opaque_type_origin(alias_ty.def_id.expect_local());
142+
let origin = self.tcx.local_opaque_ty_origin(alias_ty.def_id.expect_local());
143143
trace!(?origin);
144144
match origin {
145145
rustc_hir::OpaqueTyOrigin::FnReturn { .. }
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 than intended
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 than intended, because Rust 2024 has adjusted the `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 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 than intended
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 than intended
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 than intended
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 than intended
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 than intended
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 than intended
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 than intended
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 than intended
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 than intended
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 than intended
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 than intended
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 than intended, because Rust 2024 has adjusted the `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 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 than intended, because Rust 2024 has adjusted the `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 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 than intended, because Rust 2024 has adjusted the `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 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 than intended, because Rust 2024 has adjusted the `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 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 than intended, because Rust 2024 has adjusted the `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 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 than intended, because Rust 2024 has adjusted the `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 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 than intended, because Rust 2024 has adjusted the `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 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 than intended, because Rust 2024 has adjusted the `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 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 than intended, because Rust 2024 has adjusted the `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 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 than intended, because Rust 2024 has adjusted the `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 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 than intended, because Rust 2024 has adjusted the `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 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)
This repository has been archived.