@@ -9,31 +9,87 @@ use rustc_middle::middle::resolve_bound_vars::ResolvedArg;
9
9
use rustc_middle:: ty:: {
10
10
self , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable , TypeVisitableExt , TypeVisitor ,
11
11
} ;
12
- use rustc_session:: lint:: FutureIncompatibilityReason ;
13
- use rustc_span:: edition:: Edition ;
14
- use rustc_span:: { BytePos , Span } ;
12
+ use rustc_span:: { sym, BytePos , Span } ;
15
13
16
14
use crate :: fluent_generated as fluent;
17
15
use crate :: { LateContext , LateLintPass } ;
18
16
19
- // TODO: feature gate these too
20
-
21
17
declare_lint ! {
22
- /// UwU
18
+ /// The `impl_trait_overcaptures` lint warns against cases where lifetime
19
+ /// capture behavior will differ in edition 2024.
20
+ ///
21
+ /// In the 2024 edition, `impl Trait`s will capture all lifetimes in scope,
22
+ /// rather than just the lifetimes that are mentioned in the bounds of the type.
23
+ /// Often these sets are equal, but if not, it means that the `impl Trait` may
24
+ /// cause erroneous borrow-checker errors.
25
+ ///
26
+ /// ### Example
27
+ ///
28
+ /// ```rust,compile_fail
29
+ /// # #![feature(precise_capturing)]
30
+ /// # #![allow(incomplete_features)]
31
+ /// # #![deny(impl_trait_overcaptures)]
32
+ /// # use std::fmt::Display;
33
+ /// let mut x = vec![];
34
+ /// x.push(1);
35
+ ///
36
+ /// fn test(x: &Vec<i32>) -> impl Display {
37
+ /// x[0]
38
+ /// }
39
+ ///
40
+ /// let element = test(&x);
41
+ /// x.push(2);
42
+ /// println!("{element}");
43
+ /// ```
44
+ ///
45
+ /// {{produces}}
46
+ ///
47
+ /// ### Explanation
48
+ ///
49
+ /// In edition < 2024, the returned `impl Display` doesn't capture the
50
+ /// lifetime from the `&Vec<i32>`, so the vector can be mutably borrowed
51
+ /// while the `impl Display` is live.
52
+ ///
53
+ /// To fix this, we can explicitly state that the `impl Display` doesn't
54
+ /// capture any lifetimes, using `impl use<> Display`.
23
55
pub IMPL_TRAIT_OVERCAPTURES ,
24
56
Allow ,
25
- "will capture more lifetimes than possibly intended in edition 2024" ,
26
- @future_incompatible = FutureIncompatibleInfo {
27
- reason: FutureIncompatibilityReason :: EditionSemanticsChange ( Edition :: Edition2024 ) ,
28
- reference: "<https://doc.rust-lang.org/nightly/edition-guide/rust-2021/IntoIterator-for-arrays.html>" ,
29
- } ;
57
+ "`impl Trait` will capture more lifetimes than possibly intended in edition 2024" ,
58
+ @feature_gate = sym:: precise_capturing;
59
+ //@future_incompatible = FutureIncompatibleInfo {
60
+ // reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
61
+ // reference: "<FIXME>",
62
+ //};
30
63
}
31
64
32
65
declare_lint ! {
33
- /// UwU
66
+ /// The `impl_trait_redundant_captures` lint warns against cases where use of the
67
+ /// precise capturing `use<...>` syntax is not needed.
68
+ ///
69
+ /// In the 2024 edition, `impl Trait`s will capture all lifetimes in scope.
70
+ /// If precise-capturing `use<...>` syntax is used, and the set of parameters
71
+ /// that are captures are *equal* to the set of parameters in scope, then
72
+ /// the syntax is redundant, and can be removed.
73
+ ///
74
+ /// ### Example
75
+ ///
76
+ /// ```rust,compile_fail
77
+ /// # #![feature(precise_capturing, lifetime_capture_rules_2024)]
78
+ /// # #![allow(incomplete_features)]
79
+ /// # #![deny(impl_trait_redundant_captures)]
80
+ /// fn test<'a>(x: &'a i32) -> impl use<'a> Sized { x }
81
+ /// ```
82
+ ///
83
+ /// {{produces}}
84
+ ///
85
+ /// ### Explanation
86
+ ///
87
+ /// To fix this, remove the `use<'a>`, since the lifetime is already captured
88
+ /// since it is in scope.
34
89
pub IMPL_TRAIT_REDUNDANT_CAPTURES ,
35
90
Warn ,
36
- "uwu 2"
91
+ "redundant precise-capturing `use<...>` syntax on an `impl Trait`" ,
92
+ @feature_gate = sym:: precise_capturing;
37
93
}
38
94
39
95
declare_lint_pass ! (
@@ -106,7 +162,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
106
162
for arg in t. bound_vars ( ) {
107
163
let arg: ty:: BoundVariableKind = arg;
108
164
match arg {
109
- ty:: BoundVariableKind :: Region ( ty:: BoundRegionKind :: BrNamed ( def_id, ..) ) => {
165
+ ty:: BoundVariableKind :: Region ( ty:: BoundRegionKind :: BrNamed ( def_id, ..) )
166
+ | ty:: BoundVariableKind :: Ty ( ty:: BoundTyKind :: Param ( def_id, _) ) => {
110
167
added. push ( def_id) ;
111
168
let unique = self . in_scope_parameters . insert ( def_id) ;
112
169
assert ! ( unique) ;
@@ -265,7 +322,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
265
322
}
266
323
_ => {
267
324
self . tcx . dcx ( ) . span_delayed_bug (
268
- self . tcx ( ) . hir ( ) . span ( arg. hir_id ( ) ) ,
325
+ self . tcx . hir ( ) . span ( arg. hir_id ( ) ) ,
269
326
"no valid for captured arg" ,
270
327
) ;
271
328
}
0 commit comments