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