@@ -34,13 +34,8 @@ crate enum RegionNameSource {
34
34
Static ,
35
35
/// The free region corresponding to the environment of a closure.
36
36
SynthesizedFreeEnvRegion ( Span , String ) ,
37
- /// The region name corresponds to a region where the type annotation is completely missing
38
- /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference.
39
- CannotMatchHirTy ( Span , String ) ,
40
- /// The region name corresponds a reference that was found by traversing the type in the HIR.
41
- MatchedHirTy ( Span ) ,
42
- /// A region name from the generics list of a struct/enum/union.
43
- MatchedAdtAndSegment ( Span ) ,
37
+ /// The region corresponding to an argument.
38
+ AnonRegionFromArgument ( RegionNameHighlight ) ,
44
39
/// The region corresponding to a closure upvar.
45
40
AnonRegionFromUpvar ( Span , String ) ,
46
41
/// The region corresponding to the return type of a closure.
@@ -51,23 +46,52 @@ crate enum RegionNameSource {
51
46
AnonRegionFromAsyncFn ( Span ) ,
52
47
}
53
48
49
+ /// Describes what to highlight to explain to the user that we're giving an anonymous region a
50
+ /// synthesized name, and how to highlight it.
51
+ #[ derive( Debug , Clone ) ]
52
+ crate enum RegionNameHighlight {
53
+ /// The anonymous region corresponds to a reference that was found by traversing the type in the HIR.
54
+ MatchedHirTy ( Span ) ,
55
+ /// The anonymous region corresponds to a `'_` in the generics list of a struct/enum/union.
56
+ MatchedAdtAndSegment ( Span ) ,
57
+ /// The anonymous region corresponds to a region where the type annotation is completely missing
58
+ /// from the code, e.g. in a closure arguments `|x| { ... }`, where `x` is a reference.
59
+ CannotMatchHirTy ( Span , String ) ,
60
+ }
61
+
54
62
impl RegionName {
55
63
crate fn was_named ( & self ) -> bool {
56
64
match self . source {
57
65
RegionNameSource :: NamedEarlyBoundRegion ( ..)
58
66
| RegionNameSource :: NamedFreeRegion ( ..)
59
67
| RegionNameSource :: Static => true ,
60
68
RegionNameSource :: SynthesizedFreeEnvRegion ( ..)
61
- | RegionNameSource :: CannotMatchHirTy ( ..)
62
- | RegionNameSource :: MatchedHirTy ( ..)
63
- | RegionNameSource :: MatchedAdtAndSegment ( ..)
69
+ | RegionNameSource :: AnonRegionFromArgument ( ..)
64
70
| RegionNameSource :: AnonRegionFromUpvar ( ..)
65
71
| RegionNameSource :: AnonRegionFromOutput ( ..)
66
72
| RegionNameSource :: AnonRegionFromYieldTy ( ..)
67
73
| RegionNameSource :: AnonRegionFromAsyncFn ( ..) => false ,
68
74
}
69
75
}
70
76
77
+ crate fn span ( & self ) -> Option < Span > {
78
+ match self . source {
79
+ RegionNameSource :: Static => None ,
80
+ RegionNameSource :: NamedEarlyBoundRegion ( span)
81
+ | RegionNameSource :: NamedFreeRegion ( span)
82
+ | RegionNameSource :: SynthesizedFreeEnvRegion ( span, _)
83
+ | RegionNameSource :: AnonRegionFromUpvar ( span, _)
84
+ | RegionNameSource :: AnonRegionFromOutput ( span, _, _)
85
+ | RegionNameSource :: AnonRegionFromYieldTy ( span, _)
86
+ | RegionNameSource :: AnonRegionFromAsyncFn ( span) => Some ( span) ,
87
+ RegionNameSource :: AnonRegionFromArgument ( ref highlight) => match * highlight {
88
+ RegionNameHighlight :: MatchedHirTy ( span)
89
+ | RegionNameHighlight :: MatchedAdtAndSegment ( span)
90
+ | RegionNameHighlight :: CannotMatchHirTy ( span, _) => Some ( span) ,
91
+ } ,
92
+ }
93
+ }
94
+
71
95
crate fn highlight_region_name ( & self , diag : & mut DiagnosticBuilder < ' _ > ) {
72
96
match & self . source {
73
97
RegionNameSource :: NamedFreeRegion ( span)
@@ -81,17 +105,22 @@ impl RegionName {
81
105
) ;
82
106
diag. note ( & note) ;
83
107
}
84
- RegionNameSource :: CannotMatchHirTy ( span, type_name) => {
108
+ RegionNameSource :: AnonRegionFromArgument ( RegionNameHighlight :: CannotMatchHirTy (
109
+ span,
110
+ type_name,
111
+ ) ) => {
85
112
diag. span_label ( * span, format ! ( "has type `{}`" , type_name) ) ;
86
113
}
87
- RegionNameSource :: MatchedHirTy ( span)
114
+ RegionNameSource :: AnonRegionFromArgument ( RegionNameHighlight :: MatchedHirTy ( span) )
88
115
| RegionNameSource :: AnonRegionFromAsyncFn ( span) => {
89
116
diag. span_label (
90
117
* span,
91
118
format ! ( "let's call the lifetime of this reference `{}`" , self ) ,
92
119
) ;
93
120
}
94
- RegionNameSource :: MatchedAdtAndSegment ( span) => {
121
+ RegionNameSource :: AnonRegionFromArgument (
122
+ RegionNameHighlight :: MatchedAdtAndSegment ( span) ,
123
+ ) => {
95
124
diag. span_label ( * span, format ! ( "let's call this `{}`" , self ) ) ;
96
125
}
97
126
RegionNameSource :: AnonRegionFromUpvar ( span, upvar_name) => {
@@ -307,21 +336,31 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
307
336
308
337
let arg_ty = self . regioncx . universal_regions ( ) . unnormalized_input_tys
309
338
[ implicit_inputs + argument_index] ;
310
- if let Some ( region_name ) =
311
- self . give_name_if_we_can_match_hir_ty_from_argument ( fr , arg_ty , argument_index )
312
- {
313
- return Some ( region_name ) ;
314
- }
339
+ let ( _ , span ) = self . regioncx . get_argument_name_and_span_for_region (
340
+ & self . body ,
341
+ & self . local_names ,
342
+ argument_index ,
343
+ ) ;
315
344
316
- self . give_name_if_we_cannot_match_hir_ty ( fr, arg_ty)
345
+ self . get_argument_hir_ty_for_highlighting ( argument_index)
346
+ . and_then ( |arg_hir_ty| self . highlight_if_we_can_match_hir_ty ( fr, arg_ty, arg_hir_ty) )
347
+ . or_else ( || {
348
+ // `highlight_if_we_cannot_match_hir_ty` needs to know the number we will give to
349
+ // the anonymous region. If it succeeds, the `synthesize_region_name` call below
350
+ // will increment the counter, "reserving" the number we just used.
351
+ let counter = * self . next_region_name . try_borrow ( ) . unwrap ( ) ;
352
+ self . highlight_if_we_cannot_match_hir_ty ( fr, arg_ty, span, counter)
353
+ } )
354
+ . map ( |highlight| RegionName {
355
+ name : self . synthesize_region_name ( ) ,
356
+ source : RegionNameSource :: AnonRegionFromArgument ( highlight) ,
357
+ } )
317
358
}
318
359
319
- fn give_name_if_we_can_match_hir_ty_from_argument (
360
+ fn get_argument_hir_ty_for_highlighting (
320
361
& self ,
321
- needle_fr : RegionVid ,
322
- argument_ty : Ty < ' tcx > ,
323
362
argument_index : usize ,
324
- ) -> Option < RegionName > {
363
+ ) -> Option < & hir :: Ty < ' tcx > > {
325
364
let mir_hir_id = self . infcx . tcx . hir ( ) . as_local_hir_id ( self . mir_def_id ) ;
326
365
let fn_decl = self . infcx . tcx . hir ( ) . fn_decl_by_hir_id ( mir_hir_id) ?;
327
366
let argument_hir_ty: & hir:: Ty < ' _ > = fn_decl. inputs . get ( argument_index) ?;
@@ -333,7 +372,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
333
372
// (`give_name_if_anonymous_region_appears_in_arguments`).
334
373
hir:: TyKind :: Infer => None ,
335
374
336
- _ => self . give_name_if_we_can_match_hir_ty ( needle_fr , argument_ty , argument_hir_ty) ,
375
+ _ => Some ( argument_hir_ty) ,
337
376
}
338
377
}
339
378
@@ -348,42 +387,28 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
348
387
/// | | has type `&'1 u32`
349
388
/// | has type `&'2 u32`
350
389
/// ```
351
- fn give_name_if_we_cannot_match_hir_ty (
390
+ fn highlight_if_we_cannot_match_hir_ty (
352
391
& self ,
353
392
needle_fr : RegionVid ,
354
- argument_ty : Ty < ' tcx > ,
355
- ) -> Option < RegionName > {
356
- let counter = * self . next_region_name . try_borrow ( ) . unwrap ( ) ;
393
+ ty : Ty < ' tcx > ,
394
+ span : Span ,
395
+ counter : usize ,
396
+ ) -> Option < RegionNameHighlight > {
357
397
let mut highlight = RegionHighlightMode :: default ( ) ;
358
398
highlight. highlighting_region_vid ( needle_fr, counter) ;
359
- let type_name = self . infcx . extract_type_name ( & argument_ty , Some ( highlight) ) . 0 ;
399
+ let type_name = self . infcx . extract_type_name ( & ty , Some ( highlight) ) . 0 ;
360
400
361
401
debug ! (
362
- "give_name_if_we_cannot_match_hir_ty : type_name={:?} needle_fr={:?}" ,
402
+ "highlight_if_we_cannot_match_hir_ty : type_name={:?} needle_fr={:?}" ,
363
403
type_name, needle_fr
364
404
) ;
365
- let assigned_region_name = if type_name. find ( & format ! ( "'{}" , counter) ) . is_some ( ) {
405
+ if type_name. find ( & format ! ( "'{}" , counter) ) . is_some ( ) {
366
406
// Only add a label if we can confirm that a region was labelled.
367
- let argument_index =
368
- self . regioncx . get_argument_index_for_region ( self . infcx . tcx , needle_fr) ?;
369
- let ( _, span) = self . regioncx . get_argument_name_and_span_for_region (
370
- & self . body ,
371
- & self . local_names ,
372
- argument_index,
373
- ) ;
374
-
375
- Some ( RegionName {
376
- // This counter value will already have been used, so this function will increment
377
- // it so the next value will be used next and return the region name that would
378
- // have been used.
379
- name : self . synthesize_region_name ( ) ,
380
- source : RegionNameSource :: CannotMatchHirTy ( span, type_name) ,
381
- } )
407
+
408
+ Some ( RegionNameHighlight :: CannotMatchHirTy ( span, type_name) )
382
409
} else {
383
410
None
384
- } ;
385
-
386
- assigned_region_name
411
+ }
387
412
}
388
413
389
414
/// Attempts to highlight the specific part of a type annotation
@@ -395,9 +420,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
395
420
/// | - let's call the lifetime of this reference `'1`
396
421
/// ```
397
422
///
398
- /// the way this works is that we match up `argument_ty `, which is
423
+ /// the way this works is that we match up `ty `, which is
399
424
/// a `Ty<'tcx>` (the internal form of the type) with
400
- /// `argument_hir_ty `, a `hir::Ty` (the syntax of the type
425
+ /// `hir_ty `, a `hir::Ty` (the syntax of the type
401
426
/// annotation). We are descending through the types stepwise,
402
427
/// looking in to find the region `needle_fr` in the internal
403
428
/// type. Once we find that, we can use the span of the `hir::Ty`
@@ -407,18 +432,17 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
407
432
/// keep track of the **closest** type we've found. If we fail to
408
433
/// find the exact `&` or `'_` to highlight, then we may fall back
409
434
/// to highlighting that closest type instead.
410
- fn give_name_if_we_can_match_hir_ty (
435
+ fn highlight_if_we_can_match_hir_ty (
411
436
& self ,
412
437
needle_fr : RegionVid ,
413
- argument_ty : Ty < ' tcx > ,
414
- argument_hir_ty : & hir:: Ty < ' _ > ,
415
- ) -> Option < RegionName > {
416
- let search_stack: & mut Vec < ( Ty < ' tcx > , & hir:: Ty < ' _ > ) > =
417
- & mut vec ! [ ( argument_ty, argument_hir_ty) ] ;
438
+ ty : Ty < ' tcx > ,
439
+ hir_ty : & hir:: Ty < ' _ > ,
440
+ ) -> Option < RegionNameHighlight > {
441
+ let search_stack: & mut Vec < ( Ty < ' tcx > , & hir:: Ty < ' _ > ) > = & mut vec ! [ ( ty, hir_ty) ] ;
418
442
419
443
while let Some ( ( ty, hir_ty) ) = search_stack. pop ( ) {
420
444
match ( & ty. kind , & hir_ty. kind ) {
421
- // Check if the `argument_ty ` is `&'X ..` where `'X`
445
+ // Check if the `ty ` is `&'X ..` where `'X`
422
446
// is the region we are looking for -- if so, and we have a `&T`
423
447
// on the RHS, then we want to highlight the `&` like so:
424
448
//
@@ -429,16 +453,11 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
429
453
hir:: TyKind :: Rptr ( _lifetime, referent_hir_ty) ,
430
454
) => {
431
455
if region. to_region_vid ( ) == needle_fr {
432
- let region_name = self . synthesize_region_name ( ) ;
433
-
434
456
// Just grab the first character, the `&`.
435
457
let source_map = self . infcx . tcx . sess . source_map ( ) ;
436
458
let ampersand_span = source_map. start_point ( hir_ty. span ) ;
437
459
438
- return Some ( RegionName {
439
- name : region_name,
440
- source : RegionNameSource :: MatchedHirTy ( ampersand_span) ,
441
- } ) ;
460
+ return Some ( RegionNameHighlight :: MatchedHirTy ( ampersand_span) ) ;
442
461
}
443
462
444
463
// Otherwise, let's descend into the referent types.
@@ -458,13 +477,13 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
458
477
Res :: Def ( DefKind :: TyAlias , _) => ( ) ,
459
478
_ => {
460
479
if let Some ( last_segment) = path. segments . last ( ) {
461
- if let Some ( name ) = self . match_adt_and_segment (
480
+ if let Some ( highlight ) = self . match_adt_and_segment (
462
481
substs,
463
482
needle_fr,
464
483
last_segment,
465
484
search_stack,
466
485
) {
467
- return Some ( name ) ;
486
+ return Some ( highlight ) ;
468
487
}
469
488
}
470
489
}
@@ -507,7 +526,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
507
526
needle_fr : RegionVid ,
508
527
last_segment : & ' hir hir:: PathSegment < ' hir > ,
509
528
search_stack : & mut Vec < ( Ty < ' tcx > , & ' hir hir:: Ty < ' hir > ) > ,
510
- ) -> Option < RegionName > {
529
+ ) -> Option < RegionNameHighlight > {
511
530
// Did the user give explicit arguments? (e.g., `Foo<..>`)
512
531
let args = last_segment. args . as_ref ( ) ?;
513
532
let lifetime =
@@ -517,12 +536,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
517
536
| hir:: LifetimeName :: Error
518
537
| hir:: LifetimeName :: Static
519
538
| hir:: LifetimeName :: Underscore => {
520
- let region_name = self . synthesize_region_name ( ) ;
521
- let ampersand_span = lifetime. span ;
522
- Some ( RegionName {
523
- name : region_name,
524
- source : RegionNameSource :: MatchedAdtAndSegment ( ampersand_span) ,
525
- } )
539
+ let lifetime_span = lifetime. span ;
540
+ Some ( RegionNameHighlight :: MatchedAdtAndSegment ( lifetime_span) )
526
541
}
527
542
528
543
hir:: LifetimeName :: ImplicitObjectLifetimeDefault | hir:: LifetimeName :: Implicit => {
0 commit comments