1
- use rustc_data_structures:: { fx:: FxIndexSet , unord :: UnordSet } ;
2
- use rustc_errors:: LintDiagnostic ;
1
+ use rustc_data_structures:: fx:: FxIndexSet ;
2
+ use rustc_errors:: { Applicability , LintDiagnostic } ;
3
3
use rustc_hir as hir;
4
4
use rustc_hir:: def:: DefKind ;
5
5
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
6
6
use rustc_hir:: intravisit;
7
7
use rustc_middle:: ty:: {
8
8
self , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable , TypeVisitableExt , TypeVisitor ,
9
9
} ;
10
- use rustc_span:: Span ;
10
+ use rustc_session:: lint:: FutureIncompatibilityReason ;
11
+ use rustc_span:: edition:: Edition ;
12
+ use rustc_span:: { BytePos , Span } ;
11
13
12
14
use crate :: fluent_generated as fluent;
13
15
use crate :: { LateContext , LateLintPass } ;
@@ -146,7 +148,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
146
148
&& opaque. precise_capturing_args . is_none ( )
147
149
{
148
150
// Compute the set of args that are captured by the opaque...
149
- let mut captured = UnordSet :: default ( ) ;
151
+ let mut captured = FxIndexSet :: default ( ) ;
150
152
let variances = self . tcx . variances_of ( opaque_def_id) ;
151
153
let mut current_def_id = Some ( opaque_def_id. to_def_id ( ) ) ;
152
154
while let Some ( def_id) = current_def_id {
@@ -172,19 +174,43 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
172
174
let uncaptured_spans: Vec < _ > = self
173
175
. in_scope_parameters
174
176
. iter ( )
175
- . filter ( |def_id| !captured. contains ( def_id) )
177
+ . filter ( |def_id| !captured. contains ( * def_id) )
176
178
. map ( |def_id| self . tcx . def_span ( def_id) )
177
179
. collect ( ) ;
178
180
179
181
if !uncaptured_spans. is_empty ( ) {
182
+ let opaque_span = self . tcx . def_span ( opaque_def_id) ;
183
+
184
+ let suggestion = if let Ok ( snippet) =
185
+ self . tcx . sess . source_map ( ) . span_to_snippet ( opaque_span)
186
+ && snippet. starts_with ( "impl " )
187
+ {
188
+ let ( lifetimes, others) : ( Vec < _ > , Vec < _ > ) = captured
189
+ . into_iter ( )
190
+ . partition ( |def_id| self . tcx . def_kind ( * def_id) == DefKind :: LifetimeParam ) ;
191
+ // Take all lifetime params first, then all others (ty/ct).
192
+ let generics: Vec < _ > = lifetimes
193
+ . into_iter ( )
194
+ . chain ( others)
195
+ . map ( |def_id| self . tcx . item_name ( def_id) . to_string ( ) )
196
+ . collect ( ) ;
197
+ Some ( (
198
+ format ! ( " use<{}>" , generics. join( ", " ) ) ,
199
+ opaque_span. with_lo ( opaque_span. lo ( ) + BytePos ( 4 ) ) . shrink_to_lo ( ) ,
200
+ ) )
201
+ } else {
202
+ None
203
+ } ;
204
+
180
205
self . tcx . emit_node_lint (
181
206
IMPL_TRAIT_OVERCAPTURES ,
182
207
self . tcx . local_def_id_to_hir_id ( opaque_def_id) ,
183
208
ImplTraitOvercapturesLint {
184
- opaque_span : self . tcx . def_span ( opaque_def_id ) ,
209
+ opaque_span,
185
210
self_ty : t,
186
211
num_captured : uncaptured_spans. len ( ) ,
187
212
uncaptured_spans,
213
+ suggestion,
188
214
} ,
189
215
) ;
190
216
}
@@ -209,6 +235,7 @@ struct ImplTraitOvercapturesLint<'tcx> {
209
235
uncaptured_spans : Vec < Span > ,
210
236
self_ty : Ty < ' tcx > ,
211
237
num_captured : usize ,
238
+ suggestion : Option < ( String , Span ) > ,
212
239
}
213
240
214
241
impl < ' a > LintDiagnostic < ' a , ( ) > for ImplTraitOvercapturesLint < ' _ > {
@@ -218,6 +245,14 @@ impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> {
218
245
. span ( self . opaque_span )
219
246
. span_note ( self . uncaptured_spans , fluent:: lint_note)
220
247
. note ( fluent:: lint_note2) ;
248
+ if let Some ( ( suggestion, span) ) = self . suggestion {
249
+ diag. span_suggestion (
250
+ span,
251
+ fluent:: lint_suggestion,
252
+ suggestion,
253
+ Applicability :: MachineApplicable ,
254
+ ) ;
255
+ }
221
256
}
222
257
223
258
fn msg ( & self ) -> rustc_errors:: DiagMessage {
0 commit comments