@@ -2,11 +2,14 @@ use crate::errors::RegionOriginNote;
2
2
use crate :: infer:: error_reporting:: { note_and_explain_region, TypeErrCtxt } ;
3
3
use crate :: infer:: { self , SubregionOrigin } ;
4
4
use rustc_errors:: {
5
- fluent, struct_span_err, AddToDiagnostic , Diagnostic , DiagnosticBuilder , ErrorGuaranteed ,
5
+ fluent, struct_span_err, AddToDiagnostic , Applicability , Diagnostic , DiagnosticBuilder ,
6
+ ErrorGuaranteed ,
6
7
} ;
8
+ use rustc_hir:: def_id:: { DefId , LocalDefId } ;
7
9
use rustc_middle:: traits:: ObligationCauseCode ;
8
10
use rustc_middle:: ty:: error:: TypeError ;
9
- use rustc_middle:: ty:: { self , Region } ;
11
+ use rustc_middle:: ty:: { self , IsSuggestable , Region } ;
12
+ use rustc_span:: symbol:: kw;
10
13
11
14
use super :: ObligationCauseAsDiagArg ;
12
15
@@ -313,55 +316,43 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
313
316
) ;
314
317
err
315
318
}
316
- infer:: CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => self
317
- . report_extra_impl_obligation (
319
+ infer:: CompareImplItemObligation { span, impl_item_def_id, trait_item_def_id } => {
320
+ let mut err = self . report_extra_impl_obligation (
318
321
span,
319
322
impl_item_def_id,
320
323
trait_item_def_id,
321
324
& format ! ( "`{}: {}`" , sup, sub) ,
322
- ) ,
325
+ ) ;
326
+ // We should only suggest rewriting the `where` clause if the predicate is within that `where` clause
327
+ if self
328
+ . tcx
329
+ . hir ( )
330
+ . get_generics ( impl_item_def_id)
331
+ . unwrap ( )
332
+ . where_clause_span
333
+ . contains ( span)
334
+ {
335
+ self . suggest_copy_trait_method_bounds (
336
+ trait_item_def_id,
337
+ impl_item_def_id,
338
+ & mut err,
339
+ ) ;
340
+ }
341
+ err
342
+ }
323
343
infer:: CheckAssociatedTypeBounds { impl_item_def_id, trait_item_def_id, parent } => {
324
344
let mut err = self . report_concrete_failure ( * parent, sub, sup) ;
325
-
326
345
let trait_item_span = self . tcx . def_span ( trait_item_def_id) ;
327
346
let item_name = self . tcx . item_name ( impl_item_def_id. to_def_id ( ) ) ;
328
347
err. span_label (
329
348
trait_item_span,
330
349
format ! ( "definition of `{}` from trait" , item_name) ,
331
350
) ;
332
-
333
- let trait_predicates = self . tcx . explicit_predicates_of ( trait_item_def_id) ;
334
- let impl_predicates = self . tcx . explicit_predicates_of ( impl_item_def_id) ;
335
-
336
- let impl_predicates: rustc_data_structures:: fx:: FxHashSet < _ > =
337
- impl_predicates. predicates . into_iter ( ) . map ( |( pred, _) | pred) . collect ( ) ;
338
- let clauses: Vec < _ > = trait_predicates
339
- . predicates
340
- . into_iter ( )
341
- . filter ( |& ( pred, _) | !impl_predicates. contains ( pred) )
342
- . map ( |( pred, _) | format ! ( "{}" , pred) )
343
- . collect ( ) ;
344
-
345
- if !clauses. is_empty ( ) {
346
- let generics = self . tcx . hir ( ) . get_generics ( impl_item_def_id) . unwrap ( ) ;
347
- let where_clause_span = generics. tail_span_for_predicate_suggestion ( ) ;
348
-
349
- let suggestion = format ! (
350
- "{} {}" ,
351
- generics. add_where_or_trailing_comma( ) ,
352
- clauses. join( ", " ) ,
353
- ) ;
354
- err. span_suggestion (
355
- where_clause_span,
356
- & format ! (
357
- "try copying {} from the trait" ,
358
- if clauses. len( ) > 1 { "these clauses" } else { "this clause" }
359
- ) ,
360
- suggestion,
361
- rustc_errors:: Applicability :: MaybeIncorrect ,
362
- ) ;
363
- }
364
-
351
+ self . suggest_copy_trait_method_bounds (
352
+ trait_item_def_id,
353
+ impl_item_def_id,
354
+ & mut err,
355
+ ) ;
365
356
err
366
357
}
367
358
infer:: AscribeUserTypeProvePredicate ( span) => {
@@ -388,6 +379,66 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
388
379
}
389
380
}
390
381
382
+ pub fn suggest_copy_trait_method_bounds (
383
+ & self ,
384
+ trait_item_def_id : DefId ,
385
+ impl_item_def_id : LocalDefId ,
386
+ err : & mut Diagnostic ,
387
+ ) {
388
+ // FIXME(compiler-errors): Right now this is only being used for region
389
+ // predicate mismatches. Ideally, we'd use it for *all* predicate mismatches,
390
+ // but right now it's not really very smart when it comes to implicit `Sized`
391
+ // predicates and bounds on the trait itself.
392
+
393
+ let impl_def_id =
394
+ self . tcx . associated_item ( impl_item_def_id) . impl_container ( self . tcx ) . unwrap ( ) ;
395
+ let trait_substs = self
396
+ . tcx
397
+ . impl_trait_ref ( impl_def_id)
398
+ . unwrap ( )
399
+ // Replace the explicit self type with `Self` for better suggestion rendering
400
+ . with_self_ty ( self . tcx , self . tcx . mk_ty_param ( 0 , kw:: SelfUpper ) )
401
+ . substs ;
402
+ let trait_item_substs =
403
+ ty:: InternalSubsts :: identity_for_item ( self . tcx , impl_item_def_id. to_def_id ( ) )
404
+ . rebase_onto ( self . tcx , impl_def_id, trait_substs) ;
405
+
406
+ let mut is_suggestable = true ;
407
+ let trait_predicates = self
408
+ . tcx
409
+ . bound_explicit_predicates_of ( trait_item_def_id)
410
+ . map_bound ( |p| p. predicates )
411
+ . subst_iter_copied ( self . tcx , trait_item_substs)
412
+ . map ( |( pred, _) | {
413
+ if !pred. is_suggestable ( self . tcx , false ) {
414
+ is_suggestable = false ;
415
+ }
416
+ pred. to_string ( )
417
+ } )
418
+ . collect :: < Vec < _ > > ( ) ;
419
+
420
+ let generics = self . tcx . hir ( ) . get_generics ( impl_item_def_id) . unwrap ( ) ;
421
+
422
+ if is_suggestable {
423
+ if trait_predicates. is_empty ( ) {
424
+ err. span_suggestion_verbose (
425
+ generics. where_clause_span ,
426
+ "remove the `where` clause" ,
427
+ String :: new ( ) ,
428
+ Applicability :: MachineApplicable ,
429
+ ) ;
430
+ } else {
431
+ let space = if generics. where_clause_span . is_empty ( ) { " " } else { "" } ;
432
+ err. span_suggestion_verbose (
433
+ generics. where_clause_span ,
434
+ "copy the `where` clause predicates from the trait" ,
435
+ format ! ( "{space}where {}" , trait_predicates. join( ", " ) ) ,
436
+ Applicability :: MachineApplicable ,
437
+ ) ;
438
+ }
439
+ }
440
+ }
441
+
391
442
pub ( super ) fn report_placeholder_failure (
392
443
& self ,
393
444
placeholder_origin : SubregionOrigin < ' tcx > ,
0 commit comments