@@ -5,10 +5,12 @@ use crate::infer::lexical_region_resolve::RegionResolutionError;
5
5
use crate :: infer:: ValuePairs ;
6
6
use crate :: infer:: { SubregionOrigin , TypeTrace } ;
7
7
use crate :: traits:: { ObligationCause , ObligationCauseCode } ;
8
- use crate :: ty;
8
+ use crate :: ty:: { self , TyCtxt } ;
9
9
use crate :: ty:: error:: ExpectedFound ;
10
10
use crate :: ty:: subst:: SubstsRef ;
11
- use crate :: util:: ppaux:: RegionHighlightMode ;
11
+ use crate :: ty:: print:: { Print , RegionHighlightMode , FmtPrinter } ;
12
+
13
+ use std:: fmt:: { self , Write } ;
12
14
13
15
impl NiceRegionError < ' me , ' gcx , ' tcx > {
14
16
/// When given a `ConcreteFailure` for a function with arguments containing a named region and
@@ -309,13 +311,48 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
309
311
sup_placeholder : Option < ty:: Region < ' tcx > > ,
310
312
has_sub : Option < usize > ,
311
313
has_sup : Option < usize > ,
312
- expected_trait_ref : ty:: TraitRef < ' _ > ,
313
- actual_trait_ref : ty:: TraitRef < ' _ > ,
314
+ expected_trait_ref : ty:: TraitRef < ' tcx > ,
315
+ actual_trait_ref : ty:: TraitRef < ' tcx > ,
314
316
vid : Option < ty:: Region < ' tcx > > ,
315
317
expected_has_vid : Option < usize > ,
316
318
actual_has_vid : Option < usize > ,
317
319
any_self_ty_has_vid : bool ,
318
320
) {
321
+ // HACK(eddyb) maybe move this in a more central location.
322
+ #[ derive( Copy , Clone ) ]
323
+ struct Highlighted < ' a , ' gcx , ' tcx , T > {
324
+ tcx : TyCtxt < ' a , ' gcx , ' tcx > ,
325
+ highlight : RegionHighlightMode ,
326
+ value : T ,
327
+ }
328
+
329
+ impl < ' a , ' gcx , ' tcx , T > Highlighted < ' a , ' gcx , ' tcx , T > {
330
+ fn map < U > ( self , f : impl FnOnce ( T ) -> U ) -> Highlighted < ' a , ' gcx , ' tcx , U > {
331
+ Highlighted {
332
+ tcx : self . tcx ,
333
+ highlight : self . highlight ,
334
+ value : f ( self . value ) ,
335
+ }
336
+ }
337
+ }
338
+
339
+ impl < ' tcx , T > fmt:: Display for Highlighted < ' _ , ' _ , ' tcx , T >
340
+ where T : for < ' a , ' b > Print < ' tcx ,
341
+ FmtPrinter < & ' a mut fmt:: Formatter < ' b > > ,
342
+ Error = fmt:: Error ,
343
+ > ,
344
+ {
345
+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
346
+ let mut printer = ty:: print:: FmtPrinter :: new ( f) ;
347
+ printer. region_highlight_mode = self . highlight ;
348
+
349
+ ty:: print:: PrintCx :: with ( self . tcx , printer, |cx| {
350
+ self . value . print ( cx) ?;
351
+ Ok ( ( ) )
352
+ } )
353
+ }
354
+ }
355
+
319
356
// The weird thing here with the `maybe_highlighting_region` calls and the
320
357
// the match inside is meant to be like this:
321
358
//
@@ -331,112 +368,93 @@ impl NiceRegionError<'me, 'gcx, 'tcx> {
331
368
// None, an then we check again inside the closure, but this
332
369
// setup sort of minimized the number of calls and so form.
333
370
334
- RegionHighlightMode :: maybe_highlighting_region ( sub_placeholder, has_sub, || {
335
- RegionHighlightMode :: maybe_highlighting_region ( sup_placeholder, has_sup, || {
336
- match ( has_sub, has_sup) {
337
- ( Some ( n1) , Some ( n2) ) => {
338
- if any_self_ty_has_vid {
339
- err. note ( & format ! (
340
- "`{}` would have to be implemented for the type `{}`, \
341
- for any two lifetimes `'{}` and `'{}`",
342
- expected_trait_ref,
343
- expected_trait_ref. self_ty( ) ,
344
- std:: cmp:: min( n1, n2) ,
345
- std:: cmp:: max( n1, n2) ,
346
- ) ) ;
347
- } else {
348
- err. note ( & format ! (
349
- "`{}` must implement `{}`, \
350
- for any two lifetimes `'{}` and `'{}`",
351
- expected_trait_ref. self_ty( ) ,
352
- expected_trait_ref,
353
- std:: cmp:: min( n1, n2) ,
354
- std:: cmp:: max( n1, n2) ,
355
- ) ) ;
356
- }
357
- }
358
- ( Some ( n) , _) | ( _, Some ( n) ) => {
359
- if any_self_ty_has_vid {
360
- err. note ( & format ! (
361
- "`{}` would have to be implemented for the type `{}`, \
362
- for any lifetime `'{}`",
363
- expected_trait_ref,
364
- expected_trait_ref. self_ty( ) ,
365
- n,
366
- ) ) ;
367
- } else {
368
- err. note ( & format ! (
369
- "`{}` must implement `{}`, for any lifetime `'{}`" ,
370
- expected_trait_ref. self_ty( ) ,
371
- expected_trait_ref,
372
- n,
373
- ) ) ;
374
- }
375
- }
376
- ( None , None ) => RegionHighlightMode :: maybe_highlighting_region (
377
- vid,
378
- expected_has_vid,
379
- || {
380
- if let Some ( n) = expected_has_vid {
381
- err. note ( & format ! (
382
- "`{}` would have to be implemented for the type `{}`, \
383
- for some specific lifetime `'{}`",
384
- expected_trait_ref,
385
- expected_trait_ref. self_ty( ) ,
386
- n,
387
- ) ) ;
388
- } else {
389
- if any_self_ty_has_vid {
390
- err. note ( & format ! (
391
- "`{}` would have to be implemented for the type `{}`" ,
392
- expected_trait_ref,
393
- expected_trait_ref. self_ty( ) ,
394
- ) ) ;
395
- } else {
396
- err. note ( & format ! (
397
- "`{}` must implement `{}`" ,
398
- expected_trait_ref. self_ty( ) ,
399
- expected_trait_ref,
400
- ) ) ;
401
- }
402
- }
403
- } ,
404
- ) ,
405
- }
406
- } )
407
- } ) ;
371
+ let highlight_trait_ref = |trait_ref| Highlighted {
372
+ tcx : self . tcx ( ) ,
373
+ highlight : RegionHighlightMode :: default ( ) ,
374
+ value : trait_ref,
375
+ } ;
408
376
409
- RegionHighlightMode :: maybe_highlighting_region (
410
- vid,
411
- actual_has_vid,
412
- || match actual_has_vid {
413
- Some ( n) => {
414
- if any_self_ty_has_vid {
415
- err. note ( & format ! (
416
- "but `{}` is actually implemented for the type `{}`, \
417
- for some specific lifetime `'{}`",
418
- actual_trait_ref,
419
- actual_trait_ref. self_ty( ) ,
420
- n
421
- ) ) ;
422
- } else {
423
- err. note ( & format ! (
424
- "but `{}` actually implements `{}`, for some specific lifetime `'{}`" ,
425
- actual_trait_ref. self_ty( ) ,
426
- actual_trait_ref,
427
- n
428
- ) ) ;
377
+ let mut expected_trait_ref = highlight_trait_ref ( expected_trait_ref) ;
378
+ expected_trait_ref. highlight . maybe_highlighting_region ( sub_placeholder, has_sub) ;
379
+ expected_trait_ref. highlight . maybe_highlighting_region ( sup_placeholder, has_sup) ;
380
+ err. note ( & {
381
+ let passive_voice = match ( has_sub, has_sup) {
382
+ ( Some ( _) , _) | ( _, Some ( _) ) => any_self_ty_has_vid,
383
+ ( None , None ) => {
384
+ expected_trait_ref. highlight . maybe_highlighting_region ( vid, expected_has_vid) ;
385
+ match expected_has_vid {
386
+ Some ( _) => true ,
387
+ None => any_self_ty_has_vid,
429
388
}
430
389
}
390
+ } ;
431
391
432
- _ => {
433
- err. note ( & format ! (
434
- "but `{}` is actually implemented for the type `{}`" ,
435
- actual_trait_ref,
436
- actual_trait_ref. self_ty( ) ,
437
- ) ) ;
392
+ let mut note = if passive_voice {
393
+ format ! (
394
+ "`{}` would have to be implemented for the type `{}`" ,
395
+ expected_trait_ref,
396
+ expected_trait_ref. map( |tr| tr. self_ty( ) ) ,
397
+ )
398
+ } else {
399
+ format ! (
400
+ "`{}` must implement `{}`" ,
401
+ expected_trait_ref. map( |tr| tr. self_ty( ) ) ,
402
+ expected_trait_ref,
403
+ )
404
+ } ;
405
+
406
+ match ( has_sub, has_sup) {
407
+ ( Some ( n1) , Some ( n2) ) => {
408
+ let _ = write ! ( note,
409
+ ", for any two lifetimes `'{}` and `'{}`" ,
410
+ std:: cmp:: min( n1, n2) ,
411
+ std:: cmp:: max( n1, n2) ,
412
+ ) ;
438
413
}
439
- } ,
440
- ) ;
414
+ ( Some ( n) , _) | ( _, Some ( n) ) => {
415
+ let _ = write ! ( note,
416
+ ", for any lifetime `'{}`" ,
417
+ n,
418
+ ) ;
419
+ }
420
+ ( None , None ) => if let Some ( n) = expected_has_vid {
421
+ let _ = write ! ( note,
422
+ ", for some specific lifetime `'{}`" ,
423
+ n,
424
+ ) ;
425
+ } ,
426
+ }
427
+
428
+ note
429
+ } ) ;
430
+
431
+ let mut actual_trait_ref = highlight_trait_ref ( actual_trait_ref) ;
432
+ actual_trait_ref. highlight . maybe_highlighting_region ( vid, actual_has_vid) ;
433
+ err. note ( & {
434
+ let passive_voice = match actual_has_vid {
435
+ Some ( _) => any_self_ty_has_vid,
436
+ None => true ,
437
+ } ;
438
+
439
+ let mut note = if passive_voice {
440
+ format ! (
441
+ "but `{}` is actually implemented for the type `{}`" ,
442
+ actual_trait_ref,
443
+ actual_trait_ref. map( |tr| tr. self_ty( ) ) ,
444
+ )
445
+ } else {
446
+ format ! (
447
+ "but `{}` actually implements `{}`" ,
448
+ actual_trait_ref. map( |tr| tr. self_ty( ) ) ,
449
+ actual_trait_ref,
450
+ )
451
+ } ;
452
+
453
+ if let Some ( n) = actual_has_vid {
454
+ let _ = write ! ( note, ", for some specific lifetime `'{}`" , n) ;
455
+ }
456
+
457
+ note
458
+ } ) ;
441
459
}
442
460
}
0 commit comments