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 } ;
33use rustc_hir as hir;
44use rustc_hir:: def:: DefKind ;
55use rustc_hir:: def_id:: { DefId , LocalDefId } ;
66use rustc_hir:: intravisit;
77use rustc_middle:: ty:: {
88 self , Ty , TyCtxt , TypeSuperVisitable , TypeVisitable , TypeVisitableExt , TypeVisitor ,
99} ;
10- use rustc_span:: Span ;
10+ use rustc_session:: lint:: FutureIncompatibilityReason ;
11+ use rustc_span:: edition:: Edition ;
12+ use rustc_span:: { BytePos , Span } ;
1113
1214use crate :: fluent_generated as fluent;
1315use crate :: { LateContext , LateLintPass } ;
@@ -146,7 +148,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
146148 && opaque. precise_capturing_args . is_none ( )
147149 {
148150 // Compute the set of args that are captured by the opaque...
149- let mut captured = UnordSet :: default ( ) ;
151+ let mut captured = FxIndexSet :: default ( ) ;
150152 let variances = self . tcx . variances_of ( opaque_def_id) ;
151153 let mut current_def_id = Some ( opaque_def_id. to_def_id ( ) ) ;
152154 while let Some ( def_id) = current_def_id {
@@ -172,19 +174,43 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for VisitOpaqueTypes<'tcx> {
172174 let uncaptured_spans: Vec < _ > = self
173175 . in_scope_parameters
174176 . iter ( )
175- . filter ( |def_id| !captured. contains ( def_id) )
177+ . filter ( |def_id| !captured. contains ( * def_id) )
176178 . map ( |def_id| self . tcx . def_span ( def_id) )
177179 . collect ( ) ;
178180
179181 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+
180205 self . tcx . emit_node_lint (
181206 IMPL_TRAIT_OVERCAPTURES ,
182207 self . tcx . local_def_id_to_hir_id ( opaque_def_id) ,
183208 ImplTraitOvercapturesLint {
184- opaque_span : self . tcx . def_span ( opaque_def_id ) ,
209+ opaque_span,
185210 self_ty : t,
186211 num_captured : uncaptured_spans. len ( ) ,
187212 uncaptured_spans,
213+ suggestion,
188214 } ,
189215 ) ;
190216 }
@@ -209,6 +235,7 @@ struct ImplTraitOvercapturesLint<'tcx> {
209235 uncaptured_spans : Vec < Span > ,
210236 self_ty : Ty < ' tcx > ,
211237 num_captured : usize ,
238+ suggestion : Option < ( String , Span ) > ,
212239}
213240
214241impl < ' a > LintDiagnostic < ' a , ( ) > for ImplTraitOvercapturesLint < ' _ > {
@@ -218,6 +245,14 @@ impl<'a> LintDiagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> {
218245 . span ( self . opaque_span )
219246 . span_note ( self . uncaptured_spans , fluent:: lint_note)
220247 . 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+ }
221256 }
222257
223258 fn msg ( & self ) -> rustc_errors:: DiagMessage {
0 commit comments