@@ -15,7 +15,7 @@ use rustc_middle::ty::{
15
15
self , suggest_constraining_type_param, AdtKind , DefIdTree , Infer , InferTy , ToPredicate , Ty ,
16
16
TyCtxt , TypeFoldable , WithConstness ,
17
17
} ;
18
- use rustc_span:: symbol:: { kw, sym, Symbol } ;
18
+ use rustc_span:: symbol:: { kw, sym, Ident , Symbol } ;
19
19
use rustc_span:: { MultiSpan , Span , DUMMY_SP } ;
20
20
use std:: fmt;
21
21
@@ -173,6 +173,7 @@ fn suggest_restriction(
173
173
fn_sig : Option < & hir:: FnSig < ' _ > > ,
174
174
projection : Option < & ty:: ProjectionTy < ' _ > > ,
175
175
trait_ref : ty:: PolyTraitRef < ' _ > ,
176
+ super_traits : Option < ( & Ident , & hir:: GenericBounds < ' _ > ) > ,
176
177
) {
177
178
let span = generics. where_clause . span_for_predicates_or_empty_place ( ) ;
178
179
if span. from_expansion ( ) || span. desugaring_kind ( ) . is_some ( ) {
@@ -262,8 +263,22 @@ fn suggest_restriction(
262
263
) ;
263
264
} else {
264
265
// Trivial case: `T` needs an extra bound: `T: Bound`.
265
- let ( sp, sugg) =
266
- predicate_constraint ( generics, trait_ref. without_const ( ) . to_predicate ( ) . to_string ( ) ) ;
266
+ let ( sp, sugg) = match super_traits {
267
+ None => {
268
+ predicate_constraint ( generics, trait_ref. without_const ( ) . to_predicate ( ) . to_string ( ) )
269
+ }
270
+ Some ( ( ident, bounds) ) => match bounds {
271
+ [ .., bound] => (
272
+ bound. span ( ) . shrink_to_hi ( ) ,
273
+ format ! ( " + {}" , trait_ref. print_only_trait_path( ) . to_string( ) ) ,
274
+ ) ,
275
+ [ ] => (
276
+ ident. span . shrink_to_hi ( ) ,
277
+ format ! ( ": {}" , trait_ref. print_only_trait_path( ) . to_string( ) ) ,
278
+ ) ,
279
+ } ,
280
+ } ;
281
+
267
282
let appl = Applicability :: MachineApplicable ;
268
283
err. span_suggestion ( sp, & format ! ( "consider further restricting {}" , msg) , sugg, appl) ;
269
284
}
@@ -288,13 +303,33 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
288
303
let mut hir_id = body_id;
289
304
while let Some ( node) = self . tcx . hir ( ) . find ( hir_id) {
290
305
match node {
306
+ hir:: Node :: Item ( hir:: Item {
307
+ ident,
308
+ kind : hir:: ItemKind :: Trait ( _, _, generics, bounds, _) ,
309
+ ..
310
+ } ) if param_ty && self_ty == self . tcx . types . self_param => {
311
+ // Restricting `Self` for a single method.
312
+ suggest_restriction (
313
+ & generics,
314
+ "`Self`" ,
315
+ err,
316
+ None ,
317
+ projection,
318
+ trait_ref,
319
+ Some ( ( ident, bounds) ) ,
320
+ ) ;
321
+ return ;
322
+ }
323
+
291
324
hir:: Node :: TraitItem ( hir:: TraitItem {
292
325
generics,
293
326
kind : hir:: TraitItemKind :: Fn ( ..) ,
294
327
..
295
328
} ) if param_ty && self_ty == self . tcx . types . self_param => {
296
329
// Restricting `Self` for a single method.
297
- suggest_restriction ( & generics, "`Self`" , err, None , projection, trait_ref) ;
330
+ suggest_restriction (
331
+ & generics, "`Self`" , err, None , projection, trait_ref, None ,
332
+ ) ;
298
333
return ;
299
334
}
300
335
@@ -319,6 +354,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
319
354
Some ( fn_sig) ,
320
355
projection,
321
356
trait_ref,
357
+ None ,
322
358
) ;
323
359
return ;
324
360
}
@@ -336,6 +372,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
336
372
None ,
337
373
projection,
338
374
trait_ref,
375
+ None ,
339
376
) ;
340
377
return ;
341
378
}
0 commit comments