@@ -34,13 +34,8 @@ crate enum RegionNameSource {
3434 Static ,
3535 /// The free region corresponding to the environment of a closure.
3636 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 ) ,
4439 /// The region corresponding to a closure upvar.
4540 AnonRegionFromUpvar ( Span , String ) ,
4641 /// The region corresponding to the return type of a closure.
@@ -51,23 +46,52 @@ crate enum RegionNameSource {
5146 AnonRegionFromAsyncFn ( Span ) ,
5247}
5348
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+
5462impl RegionName {
5563 crate fn was_named ( & self ) -> bool {
5664 match self . source {
5765 RegionNameSource :: NamedEarlyBoundRegion ( ..)
5866 | RegionNameSource :: NamedFreeRegion ( ..)
5967 | RegionNameSource :: Static => true ,
6068 RegionNameSource :: SynthesizedFreeEnvRegion ( ..)
61- | RegionNameSource :: CannotMatchHirTy ( ..)
62- | RegionNameSource :: MatchedHirTy ( ..)
63- | RegionNameSource :: MatchedAdtAndSegment ( ..)
69+ | RegionNameSource :: AnonRegionFromArgument ( ..)
6470 | RegionNameSource :: AnonRegionFromUpvar ( ..)
6571 | RegionNameSource :: AnonRegionFromOutput ( ..)
6672 | RegionNameSource :: AnonRegionFromYieldTy ( ..)
6773 | RegionNameSource :: AnonRegionFromAsyncFn ( ..) => false ,
6874 }
6975 }
7076
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+
7195 crate fn highlight_region_name ( & self , diag : & mut DiagnosticBuilder < ' _ > ) {
7296 match & self . source {
7397 RegionNameSource :: NamedFreeRegion ( span)
@@ -81,17 +105,22 @@ impl RegionName {
81105 ) ;
82106 diag. note ( & note) ;
83107 }
84- RegionNameSource :: CannotMatchHirTy ( span, type_name) => {
108+ RegionNameSource :: AnonRegionFromArgument ( RegionNameHighlight :: CannotMatchHirTy (
109+ span,
110+ type_name,
111+ ) ) => {
85112 diag. span_label ( * span, format ! ( "has type `{}`" , type_name) ) ;
86113 }
87- RegionNameSource :: MatchedHirTy ( span)
114+ RegionNameSource :: AnonRegionFromArgument ( RegionNameHighlight :: MatchedHirTy ( span) )
88115 | RegionNameSource :: AnonRegionFromAsyncFn ( span) => {
89116 diag. span_label (
90117 * span,
91118 format ! ( "let's call the lifetime of this reference `{}`" , self ) ,
92119 ) ;
93120 }
94- RegionNameSource :: MatchedAdtAndSegment ( span) => {
121+ RegionNameSource :: AnonRegionFromArgument (
122+ RegionNameHighlight :: MatchedAdtAndSegment ( span) ,
123+ ) => {
95124 diag. span_label ( * span, format ! ( "let's call this `{}`" , self ) ) ;
96125 }
97126 RegionNameSource :: AnonRegionFromUpvar ( span, upvar_name) => {
@@ -307,21 +336,31 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
307336
308337 let arg_ty = self . regioncx . universal_regions ( ) . unnormalized_input_tys
309338 [ 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+ ) ;
315344
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+ } )
317358 }
318359
319- fn give_name_if_we_can_match_hir_ty_from_argument (
360+ fn get_argument_hir_ty_for_highlighting (
320361 & self ,
321- needle_fr : RegionVid ,
322- argument_ty : Ty < ' tcx > ,
323362 argument_index : usize ,
324- ) -> Option < RegionName > {
363+ ) -> Option < & hir :: Ty < ' tcx > > {
325364 let mir_hir_id = self . infcx . tcx . hir ( ) . as_local_hir_id ( self . mir_def_id ) ;
326365 let fn_decl = self . infcx . tcx . hir ( ) . fn_decl_by_hir_id ( mir_hir_id) ?;
327366 let argument_hir_ty: & hir:: Ty < ' _ > = fn_decl. inputs . get ( argument_index) ?;
@@ -333,7 +372,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
333372 // (`give_name_if_anonymous_region_appears_in_arguments`).
334373 hir:: TyKind :: Infer => None ,
335374
336- _ => self . give_name_if_we_can_match_hir_ty ( needle_fr , argument_ty , argument_hir_ty) ,
375+ _ => Some ( argument_hir_ty) ,
337376 }
338377 }
339378
@@ -348,42 +387,28 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
348387 /// | | has type `&'1 u32`
349388 /// | has type `&'2 u32`
350389 /// ```
351- fn give_name_if_we_cannot_match_hir_ty (
390+ fn highlight_if_we_cannot_match_hir_ty (
352391 & self ,
353392 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 > {
357397 let mut highlight = RegionHighlightMode :: default ( ) ;
358398 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 ;
360400
361401 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={:?}" ,
363403 type_name, needle_fr
364404 ) ;
365- let assigned_region_name = if type_name. find ( & format ! ( "'{}" , counter) ) . is_some ( ) {
405+ if type_name. find ( & format ! ( "'{}" , counter) ) . is_some ( ) {
366406 // 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) )
382409 } else {
383410 None
384- } ;
385-
386- assigned_region_name
411+ }
387412 }
388413
389414 /// Attempts to highlight the specific part of a type annotation
@@ -395,9 +420,9 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
395420 /// | - let's call the lifetime of this reference `'1`
396421 /// ```
397422 ///
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
399424 /// 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
401426 /// annotation). We are descending through the types stepwise,
402427 /// looking in to find the region `needle_fr` in the internal
403428 /// type. Once we find that, we can use the span of the `hir::Ty`
@@ -407,18 +432,17 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
407432 /// keep track of the **closest** type we've found. If we fail to
408433 /// find the exact `&` or `'_` to highlight, then we may fall back
409434 /// 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 (
411436 & self ,
412437 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) ] ;
418442
419443 while let Some ( ( ty, hir_ty) ) = search_stack. pop ( ) {
420444 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`
422446 // is the region we are looking for -- if so, and we have a `&T`
423447 // on the RHS, then we want to highlight the `&` like so:
424448 //
@@ -429,16 +453,11 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
429453 hir:: TyKind :: Rptr ( _lifetime, referent_hir_ty) ,
430454 ) => {
431455 if region. to_region_vid ( ) == needle_fr {
432- let region_name = self . synthesize_region_name ( ) ;
433-
434456 // Just grab the first character, the `&`.
435457 let source_map = self . infcx . tcx . sess . source_map ( ) ;
436458 let ampersand_span = source_map. start_point ( hir_ty. span ) ;
437459
438- return Some ( RegionName {
439- name : region_name,
440- source : RegionNameSource :: MatchedHirTy ( ampersand_span) ,
441- } ) ;
460+ return Some ( RegionNameHighlight :: MatchedHirTy ( ampersand_span) ) ;
442461 }
443462
444463 // Otherwise, let's descend into the referent types.
@@ -458,13 +477,13 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
458477 Res :: Def ( DefKind :: TyAlias , _) => ( ) ,
459478 _ => {
460479 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 (
462481 substs,
463482 needle_fr,
464483 last_segment,
465484 search_stack,
466485 ) {
467- return Some ( name ) ;
486+ return Some ( highlight ) ;
468487 }
469488 }
470489 }
@@ -507,7 +526,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
507526 needle_fr : RegionVid ,
508527 last_segment : & ' hir hir:: PathSegment < ' hir > ,
509528 search_stack : & mut Vec < ( Ty < ' tcx > , & ' hir hir:: Ty < ' hir > ) > ,
510- ) -> Option < RegionName > {
529+ ) -> Option < RegionNameHighlight > {
511530 // Did the user give explicit arguments? (e.g., `Foo<..>`)
512531 let args = last_segment. args . as_ref ( ) ?;
513532 let lifetime =
@@ -517,12 +536,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
517536 | hir:: LifetimeName :: Error
518537 | hir:: LifetimeName :: Static
519538 | 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) )
526541 }
527542
528543 hir:: LifetimeName :: ImplicitObjectLifetimeDefault | hir:: LifetimeName :: Implicit => {
0 commit comments