@@ -24,8 +24,8 @@ declare_lint! {
2424}
2525
2626declare_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 .
2929 ImplTraitOvercaptures => [ IMPL_TRAIT_OVERCAPTURES ]
3030) ;
3131
@@ -50,7 +50,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplTraitOvercaptures {
5050 }
5151 }
5252 DefKind :: Fn => {
53- // All freee functions need to check for overcaptures.
53+ // All free functions need to check for overcaptures.
5454 }
5555 DefKind :: Closure => return ,
5656 kind => {
@@ -64,6 +64,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplTraitOvercaptures {
6464 let sig = cx. tcx . fn_sig ( parent_def_id) . instantiate_identity ( ) ;
6565
6666 let mut in_scope_parameters = FxIndexSet :: default ( ) ;
67+ // Populate the in_scope_parameters list first with all of the generics in scope
6768 let mut current_def_id = Some ( parent_def_id. to_def_id ( ) ) ;
6869 while let Some ( def_id) = current_def_id {
6970 let generics = cx. tcx . generics_of ( def_id) ;
@@ -73,6 +74,8 @@ impl<'tcx> LateLintPass<'tcx> for ImplTraitOvercaptures {
7374 current_def_id = generics. parent ;
7475 }
7576
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).
7679 sig. visit_with ( & mut VisitOpaqueTypes {
7780 tcx : cx. tcx ,
7881 parent_def_id,
@@ -94,6 +97,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
9497 & mut self ,
9598 t : & ty:: Binder < ' tcx , T > ,
9699 ) -> Self :: Result {
100+ // When we get into a binder, we need to add its own bound vars to the scope.
97101 let mut added = vec ! [ ] ;
98102 for arg in t. bound_vars ( ) {
99103 let arg: ty:: BoundVariableKind = arg;
@@ -117,6 +121,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
117121
118122 t. super_visit_with ( self ) ;
119123
124+ // And remove them. The `shift_remove` should be `O(1)` since we're popping
125+ // them off from the end.
120126 for arg in added. into_iter ( ) . rev ( ) {
121127 self . in_scope_parameters . shift_remove ( & arg) ;
122128 }
@@ -129,22 +135,29 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
129135
130136 if let ty:: Alias ( ty:: Opaque , opaque_ty) = * t. kind ( )
131137 && let Some ( opaque_def_id) = opaque_ty. def_id . as_local ( )
138+ // Don't recurse infinitely on an opaque
132139 && self . seen . insert ( opaque_def_id)
140+ // If it's owned by this function
133141 && let opaque =
134142 self . tcx . hir_node_by_def_id ( opaque_def_id) . expect_item ( ) . expect_opaque_ty ( )
135143 && let hir:: OpaqueTyOrigin :: FnReturn ( parent_def_id) = opaque. origin
136144 && parent_def_id == self . parent_def_id
145+ // And if the opaque doesn't already have `use<>` syntax on it...
137146 && opaque. precise_capturing_args . is_none ( )
138147 {
148+ // Compute the set of args that are captured by the opaque...
139149 let mut captured = UnordSet :: default ( ) ;
140150 let variances = self . tcx . variances_of ( opaque_def_id) ;
141151 let mut current_def_id = Some ( opaque_def_id. to_def_id ( ) ) ;
142152 while let Some ( def_id) = current_def_id {
143153 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.
145156 if variances[ param. index as usize ] != ty:: Invariant {
146157 continue ;
147158 }
159+ // We need to turn all `ty::Param`/`ConstKind::Param` and
160+ // `ReEarlyParam`/`ReBound` into def ids.
148161 captured. insert ( extract_def_id_from_arg (
149162 self . tcx ,
150163 generics,
@@ -154,6 +167,8 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
154167 current_def_id = generics. parent ;
155168 }
156169
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.
157172 let uncaptured_spans: Vec < _ > = self
158173 . in_scope_parameters
159174 . iter ( )
@@ -174,6 +189,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
174189 ) ;
175190 }
176191
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).
177196 for clause in
178197 self . tcx . item_bounds ( opaque_ty. def_id ) . iter_instantiated ( self . tcx , opaque_ty. args )
179198 {
0 commit comments