@@ -24,8 +24,8 @@ declare_lint! {
24
24
}
25
25
26
26
declare_lint_pass ! (
27
- /// Lint for use of `async fn` in the definition of a publicly-reachable
28
- /// trait .
27
+ /// Lint for opaque types that will begin capturing in-scope but unmentioned lifetimes
28
+ /// in edition 2024 .
29
29
ImplTraitOvercaptures => [ IMPL_TRAIT_OVERCAPTURES ]
30
30
) ;
31
31
@@ -50,7 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplTraitOvercaptures {
50
50
}
51
51
}
52
52
DefKind :: Fn => {
53
- // All freee functions need to check for overcaptures.
53
+ // All free functions need to check for overcaptures.
54
54
}
55
55
DefKind :: Closure => return ,
56
56
kind => {
@@ -64,6 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplTraitOvercaptures {
64
64
let sig = cx. tcx . fn_sig ( parent_def_id) . instantiate_identity ( ) ;
65
65
66
66
let mut in_scope_parameters = FxIndexSet :: default ( ) ;
67
+ // Populate the in_scope_parameters list first with all of the generics in scope
67
68
let mut current_def_id = Some ( parent_def_id. to_def_id ( ) ) ;
68
69
while let Some ( def_id) = current_def_id {
69
70
let generics = cx. tcx . generics_of ( def_id) ;
@@ -73,6 +74,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplTraitOvercaptures {
73
74
current_def_id = generics. parent ;
74
75
}
75
76
77
+ // Then visit the signature to walk through all the binders (incl. the late-bound
78
+ // vars on the function itself, which we need to count too).
76
79
sig. visit_with ( & mut VisitOpaqueTypes {
77
80
tcx : cx. tcx ,
78
81
parent_def_id,
@@ -94,6 +97,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
94
97
& mut self ,
95
98
t : & ty:: Binder < ' tcx , T > ,
96
99
) -> Self :: Result {
100
+ // When we get into a binder, we need to add its own bound vars to the scope.
97
101
let mut added = vec ! [ ] ;
98
102
for arg in t. bound_vars ( ) {
99
103
let arg: ty:: BoundVariableKind = arg;
@@ -117,6 +121,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
117
121
118
122
t. super_visit_with ( self ) ;
119
123
124
+ // And remove them. The `shift_remove` should be `O(1)` since we're popping
125
+ // them off from the end.
120
126
for arg in added. into_iter ( ) . rev ( ) {
121
127
self . in_scope_parameters . shift_remove ( & arg) ;
122
128
}
@@ -129,22 +135,29 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
129
135
130
136
if let ty:: Alias ( ty:: Opaque , opaque_ty) = * t. kind ( )
131
137
&& let Some ( opaque_def_id) = opaque_ty. def_id . as_local ( )
138
+ // Don't recurse infinitely on an opaque
132
139
&& self . seen . insert ( opaque_def_id)
140
+ // If it's owned by this function
133
141
&& let opaque =
134
142
self . tcx . hir_node_by_def_id ( opaque_def_id) . expect_item ( ) . expect_opaque_ty ( )
135
143
&& let hir:: OpaqueTyOrigin :: FnReturn ( parent_def_id) = opaque. origin
136
144
&& parent_def_id == self . parent_def_id
145
+ // And if the opaque doesn't already have `use<>` syntax on it...
137
146
&& opaque. precise_capturing_args . is_none ( )
138
147
{
148
+ // Compute the set of args that are captured by the opaque...
139
149
let mut captured = UnordSet :: default ( ) ;
140
150
let variances = self . tcx . variances_of ( opaque_def_id) ;
141
151
let mut current_def_id = Some ( opaque_def_id. to_def_id ( ) ) ;
142
152
while let Some ( def_id) = current_def_id {
143
153
let generics = self . tcx . generics_of ( def_id) ;
144
- for param in & generics. params {
154
+ for param in & generics. own_params {
155
+ // A param is captured if it's invariant.
145
156
if variances[ param. index as usize ] != ty:: Invariant {
146
157
continue ;
147
158
}
159
+ // We need to turn all `ty::Param`/`ConstKind::Param` and
160
+ // `ReEarlyParam`/`ReBound` into def ids.
148
161
captured. insert ( extract_def_id_from_arg (
149
162
self . tcx ,
150
163
generics,
@@ -154,6 +167,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
154
167
current_def_id = generics. parent ;
155
168
}
156
169
170
+ // Compute the set of in scope params that are not captured. Get their spans,
171
+ // since that's all we really care about them for emitting the diagnostic.
157
172
let uncaptured_spans: Vec < _ > = self
158
173
. in_scope_parameters
159
174
. iter ( )
@@ -174,6 +189,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
174
189
) ;
175
190
}
176
191
192
+ // Walk into the bounds of the opaque, too, since we want to get nested opaques
193
+ // in this lint as well. Interestingly, one place that I expect this lint to fire
194
+ // is for `impl for<'a> Bound<Out = impl Other>`, since `impl Other` will begin
195
+ // to capture `'a` in e2024 (even though late-bound vars in opaques are not allowed).
177
196
for clause in
178
197
self . tcx . item_bounds ( opaque_ty. def_id ) . iter_instantiated ( self . tcx , opaque_ty. args )
179
198
{
0 commit comments