@@ -561,15 +561,16 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
561
561
/// Returns the appropriate lifetime to use for any output lifetimes
562
562
/// (if one exists) and a vector of the (pattern, number of lifetimes)
563
563
/// corresponding to each input type/pattern.
564
- fn find_implied_output_region ( & self ,
565
- input_tys : & [ Ty < ' tcx > ] ,
566
- input_pats : Vec < String > ) -> ElidedLifetime
564
+ fn find_implied_output_region < F > ( & self ,
565
+ input_tys : & [ Ty < ' tcx > ] ,
566
+ input_pats : F ) -> ElidedLifetime
567
+ where F : FnOnce ( ) -> Vec < String >
567
568
{
568
569
let tcx = self . tcx ( ) ;
569
570
let mut lifetimes_for_params = Vec :: new ( ) ;
570
571
let mut possible_implied_output_region = None ;
571
572
572
- for ( input_type, input_pat ) in input_tys. iter ( ) . zip ( input_pats ) {
573
+ for input_type in input_tys. iter ( ) {
573
574
let mut regions = FnvHashSet ( ) ;
574
575
let have_bound_regions = tcx. collect_regions ( input_type, & mut regions) ;
575
576
@@ -583,8 +584,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
583
584
possible_implied_output_region = regions. iter ( ) . cloned ( ) . next ( ) ;
584
585
}
585
586
587
+ // Use a placeholder for `name` because computing it can be
588
+ // expensive and we don't want to do it until we know it's
589
+ // necessary.
586
590
lifetimes_for_params. push ( ElisionFailureInfo {
587
- name : input_pat ,
591
+ name : String :: new ( ) ,
588
592
lifetime_count : regions. len ( ) ,
589
593
have_bound_regions : have_bound_regions
590
594
} ) ;
@@ -593,6 +597,11 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
593
597
if lifetimes_for_params. iter ( ) . map ( |e| e. lifetime_count ) . sum :: < usize > ( ) == 1 {
594
598
Ok ( * possible_implied_output_region. unwrap ( ) )
595
599
} else {
600
+ // Fill in the expensive `name` fields now that we know they're
601
+ // needed.
602
+ for ( info, input_pat) in lifetimes_for_params. iter_mut ( ) . zip ( input_pats ( ) ) {
603
+ info. name = input_pat;
604
+ }
596
605
Err ( Some ( lifetimes_for_params) )
597
606
}
598
607
}
@@ -629,7 +638,8 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
629
638
let inputs: Vec < _ > = data. inputs . iter ( ) . map ( |a_t| {
630
639
self . ast_ty_arg_to_ty ( & binding_rscope, None , region_substs, a_t)
631
640
} ) . collect ( ) ;
632
- let input_params = vec ! [ String :: new( ) ; inputs. len( ) ] ;
641
+ let inputs_len = inputs. len ( ) ;
642
+ let input_params = || vec ! [ String :: new( ) ; inputs_len] ;
633
643
let implied_output_region = self . find_implied_output_region ( & inputs, input_params) ;
634
644
635
645
let ( output, output_span) = match data. output {
@@ -1861,15 +1871,22 @@ impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
1861
1871
} ;
1862
1872
let arg_tys: Vec < Ty > =
1863
1873
arg_params. iter ( ) . map ( |a| self . ty_of_arg ( & rb, a, None ) ) . collect ( ) ;
1864
- let arg_pats: Vec < String > =
1865
- arg_params. iter ( ) . map ( |a| pprust:: pat_to_string ( & a. pat ) ) . collect ( ) ;
1866
1874
1867
1875
// Second, if there was exactly one lifetime (either a substitution or a
1868
1876
// reference) in the arguments, then any anonymous regions in the output
1869
1877
// have that lifetime.
1870
1878
let implied_output_region = match explicit_self_category {
1871
1879
ty:: ExplicitSelfCategory :: ByReference ( region, _) => Ok ( * region) ,
1872
- _ => self . find_implied_output_region ( & arg_tys, arg_pats)
1880
+ _ => {
1881
+ // `pat_to_string` is expensive and
1882
+ // `find_implied_output_region` only needs its result when
1883
+ // there's an error. So we wrap it in a closure to avoid
1884
+ // calling it until necessary.
1885
+ let arg_pats = || {
1886
+ arg_params. iter ( ) . map ( |a| pprust:: pat_to_string ( & a. pat ) ) . collect ( )
1887
+ } ;
1888
+ self . find_implied_output_region ( & arg_tys, arg_pats)
1889
+ }
1873
1890
} ;
1874
1891
1875
1892
let output_ty = match decl. output {
0 commit comments