@@ -386,20 +386,81 @@ fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC,
386386 ( regions, types)
387387}
388388
389+ /// Returns the appropriate lifetime to use for any output lifetimes
390+ /// (if one exists) and a vector of the (pattern, number of lifetimes)
391+ /// corresponding to each input type/pattern.
392+ fn find_implied_output_region ( input_tys : & [ Ty ] , input_pats : Vec < String > )
393+ -> ( Option < ty:: Region > , Vec < ( String , uint ) > )
394+ {
395+ let mut lifetimes_for_params: Vec < ( String , uint ) > = Vec :: new ( ) ;
396+ let mut possible_implied_output_region = None ;
397+
398+ for ( input_type, input_pat) in input_tys. iter ( ) . zip ( input_pats. into_iter ( ) ) {
399+ let mut accumulator = Vec :: new ( ) ;
400+ ty:: accumulate_lifetimes_in_type ( & mut accumulator, * input_type) ;
401+
402+ if accumulator. len ( ) == 1 {
403+ // there's a chance that the unique lifetime of this
404+ // iteration will be the appropriate lifetime for output
405+ // parameters, so lets store it.
406+ possible_implied_output_region = Some ( accumulator[ 0 ] )
407+ }
408+
409+ lifetimes_for_params. push ( ( input_pat, accumulator. len ( ) ) ) ;
410+ }
411+
412+ let implied_output_region = if lifetimes_for_params. iter ( ) . map ( |& ( _, n) | n) . sum ( ) == 1 {
413+ assert ! ( possible_implied_output_region. is_some( ) ) ;
414+ possible_implied_output_region
415+ } else {
416+ None
417+ } ;
418+ ( implied_output_region, lifetimes_for_params)
419+ }
420+
421+ fn convert_ty_with_lifetime_elision < ' tcx , AC > ( this : & AC ,
422+ implied_output_region : Option < ty:: Region > ,
423+ param_lifetimes : Vec < ( String , uint ) > ,
424+ ty : & ast:: Ty )
425+ -> Ty < ' tcx >
426+ where AC : AstConv < ' tcx >
427+ {
428+ match implied_output_region {
429+ Some ( implied_output_region) => {
430+ let rb = SpecificRscope :: new ( implied_output_region) ;
431+ ast_ty_to_ty ( this, & rb, ty)
432+ }
433+ None => {
434+ // All regions must be explicitly specified in the output
435+ // if the lifetime elision rules do not apply. This saves
436+ // the user from potentially-confusing errors.
437+ let rb = UnelidableRscope :: new ( param_lifetimes) ;
438+ ast_ty_to_ty ( this, & rb, ty)
439+ }
440+ }
441+ }
442+
389443fn convert_parenthesized_parameters < ' tcx , AC > ( this : & AC ,
390444 data : & ast:: ParenthesizedParameterData )
391445 -> Vec < Ty < ' tcx > >
392446 where AC : AstConv < ' tcx >
393447{
394448 let binding_rscope = BindingRscope :: new ( ) ;
395-
396449 let inputs = data. inputs . iter ( )
397450 . map ( |a_t| ast_ty_to_ty ( this, & binding_rscope, & * * a_t) )
398- . collect ( ) ;
451+ . collect :: < Vec < Ty < ' tcx > > > ( ) ;
452+
453+ let input_params = Vec :: from_elem ( inputs. len ( ) , String :: new ( ) ) ;
454+ let ( implied_output_region,
455+ params_lifetimes) = find_implied_output_region ( & * inputs, input_params) ;
456+
399457 let input_ty = ty:: mk_tup ( this. tcx ( ) , inputs) ;
400458
401459 let output = match data. output {
402- Some ( ref output_ty) => ast_ty_to_ty ( this, & binding_rscope, & * * output_ty) ,
460+ Some ( ref output_ty) => convert_ty_with_lifetime_elision ( this,
461+ implied_output_region,
462+ params_lifetimes,
463+ & * * output_ty) ,
403464 None => ty:: mk_nil ( this. tcx ( ) ) ,
404465 } ;
405466
@@ -1059,55 +1120,33 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
10591120 let self_and_input_tys: Vec < Ty > =
10601121 self_ty. into_iter ( ) . chain ( input_tys) . collect ( ) ;
10611122
1062- let mut lifetimes_for_params: Vec < ( String , Vec < ty:: Region > ) > = Vec :: new ( ) ;
10631123
10641124 // Second, if there was exactly one lifetime (either a substitution or a
10651125 // reference) in the arguments, then any anonymous regions in the output
10661126 // have that lifetime.
1067- if implied_output_region. is_none ( ) {
1068- let mut self_and_input_tys_iter = self_and_input_tys. iter ( ) ;
1069- if self_ty. is_some ( ) {
1127+ let lifetimes_for_params = if implied_output_region. is_none ( ) {
1128+ let input_tys = if self_ty. is_some ( ) {
10701129 // Skip the first argument if `self` is present.
1071- drop ( self_and_input_tys_iter. next ( ) )
1072- }
1073-
1074- for ( input_type, input_pat) in self_and_input_tys_iter. zip ( input_pats. into_iter ( ) ) {
1075- let mut accumulator = Vec :: new ( ) ;
1076- ty:: accumulate_lifetimes_in_type ( & mut accumulator, * input_type) ;
1077- lifetimes_for_params. push ( ( input_pat, accumulator) ) ;
1078- }
1079-
1080- if lifetimes_for_params. iter ( ) . map ( |& ( _, ref x) | x. len ( ) ) . sum ( ) == 1 {
1081- implied_output_region =
1082- Some ( lifetimes_for_params. iter ( )
1083- . filter_map ( |& ( _, ref x) |
1084- if x. len ( ) == 1 { Some ( x[ 0 ] ) } else { None } )
1085- . next ( ) . unwrap ( ) ) ;
1086- }
1087- }
1130+ self_and_input_tys. slice_from ( 1 )
1131+ } else {
1132+ self_and_input_tys. slice_from ( 0 )
1133+ } ;
10881134
1089- let param_lifetimes: Vec < ( String , uint ) > = lifetimes_for_params. into_iter ( )
1090- . map ( |( n, v) | ( n, v. len ( ) ) )
1091- . filter ( |& ( _, l) | l != 0 )
1092- . collect ( ) ;
1135+ let ( ior, lfp) = find_implied_output_region ( input_tys, input_pats) ;
1136+ implied_output_region = ior;
1137+ lfp
1138+ } else {
1139+ vec ! [ ]
1140+ } ;
10931141
10941142 let output_ty = match decl. output {
10951143 ast:: Return ( ref output) if output. node == ast:: TyInfer =>
10961144 ty:: FnConverging ( this. ty_infer ( output. span ) ) ,
10971145 ast:: Return ( ref output) =>
1098- ty:: FnConverging ( match implied_output_region {
1099- Some ( implied_output_region) => {
1100- let rb = SpecificRscope :: new ( implied_output_region) ;
1101- ast_ty_to_ty ( this, & rb, & * * output)
1102- }
1103- None => {
1104- // All regions must be explicitly specified in the output
1105- // if the lifetime elision rules do not apply. This saves
1106- // the user from potentially-confusing errors.
1107- let rb = UnelidableRscope :: new ( param_lifetimes) ;
1108- ast_ty_to_ty ( this, & rb, & * * output)
1109- }
1110- } ) ,
1146+ ty:: FnConverging ( convert_ty_with_lifetime_elision ( this,
1147+ implied_output_region,
1148+ lifetimes_for_params,
1149+ & * * output) ) ,
11111150 ast:: NoReturn ( _) => ty:: FnDiverging
11121151 } ;
11131152
0 commit comments