1
+ use crate :: errors:: { ActualImplExplNotes , TraitPlaceholderMismatch } ;
1
2
use crate :: infer:: error_reporting:: nice_region_error:: NiceRegionError ;
2
3
use crate :: infer:: lexical_region_resolve:: RegionResolutionError ;
3
4
use crate :: infer:: ValuePairs ;
4
5
use crate :: infer:: { SubregionOrigin , TypeTrace } ;
5
6
use crate :: traits:: { ObligationCause , ObligationCauseCode } ;
6
7
use rustc_data_structures:: intern:: Interned ;
7
- use rustc_errors:: { Diagnostic , DiagnosticBuilder , ErrorGuaranteed } ;
8
+ use rustc_errors:: { DiagnosticBuilder , ErrorGuaranteed } ;
8
9
use rustc_hir:: def:: Namespace ;
9
10
use rustc_hir:: def_id:: DefId ;
10
11
use rustc_middle:: ty:: error:: ExpectedFound ;
11
12
use rustc_middle:: ty:: print:: { FmtPrinter , Print , RegionHighlightMode } ;
12
13
use rustc_middle:: ty:: subst:: SubstsRef ;
13
14
use rustc_middle:: ty:: { self , RePlaceholder , ReVar , Region , TyCtxt } ;
14
15
15
- use std:: fmt:: { self , Write } ;
16
+ use std:: fmt;
16
17
17
18
impl < ' tcx > NiceRegionError < ' _ , ' tcx > {
18
19
/// When given a `ConcreteFailure` for a function with arguments containing a named region and
@@ -205,26 +206,21 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
205
206
actual_substs : SubstsRef < ' tcx > ,
206
207
) -> DiagnosticBuilder < ' tcx , ErrorGuaranteed > {
207
208
let span = cause. span ( ) ;
208
- let msg = format ! (
209
- "implementation of `{}` is not general enough" ,
210
- self . tcx( ) . def_path_str( trait_def_id) ,
211
- ) ;
212
- let mut err = self . tcx ( ) . sess . struct_span_err ( span, & msg) ;
213
209
214
- let leading_ellipsis = if let ObligationCauseCode :: ItemObligation ( def_id)
215
- | ObligationCauseCode :: ExprItemObligation ( def_id, .. ) =
216
- * cause. code ( )
217
- {
218
- err . span_label ( span , "doesn't satisfy where-clause" ) ;
219
- err . span_label (
220
- self . tcx ( ) . def_span ( def_id ) ,
221
- & format ! ( "due to a where-clause on `{}`..." , self . tcx( ) . def_path_str ( def_id) ) ,
222
- ) ;
223
- true
224
- } else {
225
- err . span_label ( span , & msg ) ;
226
- false
227
- } ;
210
+ let ( leading_ellipsis, satisfy_span , where_span , dup_span , def_id) =
211
+ if let ObligationCauseCode :: ItemObligation ( def_id)
212
+ | ObligationCauseCode :: ExprItemObligation ( def_id , .. ) = * cause. code ( )
213
+ {
214
+ (
215
+ true ,
216
+ Some ( span ) ,
217
+ Some ( self . tcx ( ) . def_span ( def_id) ) ,
218
+ None ,
219
+ self . tcx ( ) . def_path_str ( def_id ) ,
220
+ )
221
+ } else {
222
+ ( false , None , None , Some ( span ) , String :: new ( ) )
223
+ } ;
228
224
229
225
let expected_trait_ref = self
230
226
. cx
@@ -284,8 +280,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
284
280
?expected_self_ty_has_vid,
285
281
) ;
286
282
287
- self . explain_actual_impl_that_was_found (
288
- & mut err,
283
+ let actual_impl_expl_notes = self . explain_actual_impl_that_was_found (
289
284
sub_placeholder,
290
285
sup_placeholder,
291
286
has_sub,
@@ -299,7 +294,17 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
299
294
leading_ellipsis,
300
295
) ;
301
296
302
- err
297
+ let diag = TraitPlaceholderMismatch {
298
+ span,
299
+ satisfy_span,
300
+ where_span,
301
+ dup_span,
302
+ def_id,
303
+ trait_def_id : self . tcx ( ) . def_path_str ( trait_def_id) ,
304
+ actual_impl_expl_notes,
305
+ } ;
306
+
307
+ self . tcx ( ) . sess . create_err ( diag)
303
308
}
304
309
305
310
/// Add notes with details about the expected and actual trait refs, with attention to cases
@@ -309,7 +314,6 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
309
314
/// due to the number of combinations we have to deal with.
310
315
fn explain_actual_impl_that_was_found (
311
316
& self ,
312
- err : & mut Diagnostic ,
313
317
sub_placeholder : Option < Region < ' tcx > > ,
314
318
sup_placeholder : Option < Region < ' tcx > > ,
315
319
has_sub : Option < usize > ,
@@ -321,7 +325,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
321
325
actual_has_vid : Option < usize > ,
322
326
any_self_ty_has_vid : bool ,
323
327
leading_ellipsis : bool ,
324
- ) {
328
+ ) -> Vec < ActualImplExplNotes > {
325
329
// HACK(eddyb) maybe move this in a more central location.
326
330
#[ derive( Copy , Clone ) ]
327
331
struct Highlighted < ' tcx , T > {
@@ -380,120 +384,107 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
380
384
let mut expected_trait_ref = highlight_trait_ref ( expected_trait_ref) ;
381
385
expected_trait_ref. highlight . maybe_highlighting_region ( sub_placeholder, has_sub) ;
382
386
expected_trait_ref. highlight . maybe_highlighting_region ( sup_placeholder, has_sup) ;
383
- err. note ( & {
384
- let passive_voice = match ( has_sub, has_sup) {
385
- ( Some ( _) , _) | ( _, Some ( _) ) => any_self_ty_has_vid,
386
- ( None , None ) => {
387
- expected_trait_ref. highlight . maybe_highlighting_region ( vid, expected_has_vid) ;
388
- match expected_has_vid {
389
- Some ( _) => true ,
390
- None => any_self_ty_has_vid,
391
- }
392
- }
393
- } ;
394
387
395
- let mut note = if same_self_type {
396
- let mut self_ty = expected_trait_ref. map ( |tr| tr. self_ty ( ) ) ;
397
- self_ty. highlight . maybe_highlighting_region ( vid, actual_has_vid) ;
398
-
399
- if self_ty. value . is_closure ( )
400
- && self . tcx ( ) . is_fn_trait ( expected_trait_ref. value . def_id )
401
- {
402
- let closure_sig = self_ty. map ( |closure| {
403
- if let ty:: Closure ( _, substs) = closure. kind ( ) {
404
- self . tcx ( ) . signature_unclosure (
405
- substs. as_closure ( ) . sig ( ) ,
406
- rustc_hir:: Unsafety :: Normal ,
407
- )
408
- } else {
409
- bug ! ( "type is not longer closure" ) ;
410
- }
411
- } ) ;
412
-
413
- format ! (
414
- "{}closure with signature `{}` must implement `{}`" ,
415
- if leading_ellipsis { "..." } else { "" } ,
416
- closure_sig,
417
- expected_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
418
- )
419
- } else {
420
- format ! (
421
- "{}`{}` must implement `{}`" ,
422
- if leading_ellipsis { "..." } else { "" } ,
423
- self_ty,
424
- expected_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
425
- )
388
+ let passive_voice = match ( has_sub, has_sup) {
389
+ ( Some ( _) , _) | ( _, Some ( _) ) => any_self_ty_has_vid,
390
+ ( None , None ) => {
391
+ expected_trait_ref. highlight . maybe_highlighting_region ( vid, expected_has_vid) ;
392
+ match expected_has_vid {
393
+ Some ( _) => true ,
394
+ None => any_self_ty_has_vid,
426
395
}
427
- } else if passive_voice {
428
- format ! (
429
- "{}`{}` would have to be implemented for the type `{}`" ,
430
- if leading_ellipsis { "..." } else { "" } ,
431
- expected_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
432
- expected_trait_ref. map( |tr| tr. self_ty( ) ) ,
396
+ }
397
+ } ;
398
+
399
+ let ( kind, ty_or_sig, trait_path) = if same_self_type {
400
+ let mut self_ty = expected_trait_ref. map ( |tr| tr. self_ty ( ) ) ;
401
+ self_ty. highlight . maybe_highlighting_region ( vid, actual_has_vid) ;
402
+
403
+ if self_ty. value . is_closure ( )
404
+ && self . tcx ( ) . is_fn_trait ( expected_trait_ref. value . def_id )
405
+ {
406
+ let closure_sig = self_ty. map ( |closure| {
407
+ if let ty:: Closure ( _, substs) = closure. kind ( ) {
408
+ self . tcx ( ) . signature_unclosure (
409
+ substs. as_closure ( ) . sig ( ) ,
410
+ rustc_hir:: Unsafety :: Normal ,
411
+ )
412
+ } else {
413
+ bug ! ( "type is not longer closure" ) ;
414
+ }
415
+ } ) ;
416
+ (
417
+ "signature" ,
418
+ closure_sig. to_string ( ) ,
419
+ expected_trait_ref. map ( |tr| tr. print_only_trait_path ( ) ) . to_string ( ) ,
433
420
)
434
421
} else {
435
- format ! (
436
- "{}`{}` must implement `{}`" ,
437
- if leading_ellipsis { "..." } else { "" } ,
438
- expected_trait_ref. map( |tr| tr. self_ty( ) ) ,
439
- expected_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
422
+ (
423
+ "other" ,
424
+ self_ty. to_string ( ) ,
425
+ expected_trait_ref. map ( |tr| tr. print_only_trait_path ( ) ) . to_string ( ) ,
440
426
)
441
- } ;
427
+ }
428
+ } else if passive_voice {
429
+ (
430
+ "passive" ,
431
+ expected_trait_ref. map ( |tr| tr. self_ty ( ) ) . to_string ( ) ,
432
+ expected_trait_ref. map ( |tr| tr. print_only_trait_path ( ) ) . to_string ( ) ,
433
+ )
434
+ } else {
435
+ (
436
+ "other" ,
437
+ expected_trait_ref. map ( |tr| tr. self_ty ( ) ) . to_string ( ) ,
438
+ expected_trait_ref. map ( |tr| tr. print_only_trait_path ( ) ) . to_string ( ) ,
439
+ )
440
+ } ;
442
441
443
- match ( has_sub, has_sup) {
444
- ( Some ( n1) , Some ( n2) ) => {
445
- let _ = write ! (
446
- note,
447
- ", for any two lifetimes `'{}` and `'{}`..." ,
448
- std:: cmp:: min( n1, n2) ,
449
- std:: cmp:: max( n1, n2) ,
450
- ) ;
451
- }
452
- ( Some ( n) , _) | ( _, Some ( n) ) => {
453
- let _ = write ! ( note, ", for any lifetime `'{}`..." , n, ) ;
454
- }
455
- ( None , None ) => {
456
- if let Some ( n) = expected_has_vid {
457
- let _ = write ! ( note, ", for some specific lifetime `'{}`..." , n, ) ;
458
- }
442
+ let ( lt_kind, lifetime_1, lifetime_2) = match ( has_sub, has_sup) {
443
+ ( Some ( n1) , Some ( n2) ) => ( "two" , std:: cmp:: min ( n1, n2) , std:: cmp:: max ( n1, n2) ) ,
444
+ ( Some ( n) , _) | ( _, Some ( n) ) => ( "any" , n, 0 ) ,
445
+ ( None , None ) => {
446
+ if let Some ( n) = expected_has_vid {
447
+ ( "some" , n, 0 )
448
+ } else {
449
+ ( "nothing" , 0 , 0 )
459
450
}
460
451
}
452
+ } ;
461
453
462
- note
463
- } ) ;
454
+ let note_1 = ActualImplExplNotes :: NoteOne {
455
+ leading_ellipsis,
456
+ kind,
457
+ ty_or_sig,
458
+ trait_path,
459
+ lt_kind,
460
+ lifetime_1,
461
+ lifetime_2,
462
+ } ;
464
463
465
464
let mut actual_trait_ref = highlight_trait_ref ( actual_trait_ref) ;
466
465
actual_trait_ref. highlight . maybe_highlighting_region ( vid, actual_has_vid) ;
467
- err. note ( & {
468
- let passive_voice = match actual_has_vid {
469
- Some ( _) => any_self_ty_has_vid,
470
- None => true ,
471
- } ;
472
466
473
- let mut note = if same_self_type {
474
- format ! (
475
- "...but it actually implements `{}`" ,
476
- actual_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
477
- )
478
- } else if passive_voice {
479
- format ! (
480
- "...but `{}` is actually implemented for the type `{}`" ,
481
- actual_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
482
- actual_trait_ref. map( |tr| tr. self_ty( ) ) ,
483
- )
484
- } else {
485
- format ! (
486
- "...but `{}` actually implements `{}`" ,
487
- actual_trait_ref. map( |tr| tr. self_ty( ) ) ,
488
- actual_trait_ref. map( |tr| tr. print_only_trait_path( ) ) ,
489
- )
490
- } ;
467
+ let passive_voice = match actual_has_vid {
468
+ Some ( _) => any_self_ty_has_vid,
469
+ None => true ,
470
+ } ;
491
471
492
- if let Some ( n) = actual_has_vid {
493
- let _ = write ! ( note, ", for some specific lifetime `'{}`" , n) ;
494
- }
472
+ let trait_path_2 = actual_trait_ref. map ( |tr| tr. print_only_trait_path ( ) ) . to_string ( ) ;
473
+ let ty = actual_trait_ref. map ( |tr| tr. self_ty ( ) ) . to_string ( ) ;
474
+ let kind_2 = if same_self_type {
475
+ "implements_trait"
476
+ } else if passive_voice {
477
+ "implemented_for_ty"
478
+ } else {
479
+ "ty_implements"
480
+ } ;
495
481
496
- note
497
- } ) ;
482
+ let has_lifetime = actual_has_vid. is_some ( ) ;
483
+ let lifetime = actual_has_vid. unwrap_or_default ( ) ;
484
+
485
+ let note_2 =
486
+ ActualImplExplNotes :: NoteTwo { kind_2, trait_path_2, ty, has_lifetime, lifetime } ;
487
+
488
+ vec ! [ note_1, note_2]
498
489
}
499
490
}
0 commit comments