@@ -386,20 +386,81 @@ fn convert_angle_bracketed_parameters<'tcx, AC, RS>(this: &AC,
386
386
( regions, types)
387
387
}
388
388
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
+
389
443
fn convert_parenthesized_parameters < ' tcx , AC > ( this : & AC ,
390
444
data : & ast:: ParenthesizedParameterData )
391
445
-> Vec < Ty < ' tcx > >
392
446
where AC : AstConv < ' tcx >
393
447
{
394
448
let binding_rscope = BindingRscope :: new ( ) ;
395
-
396
449
let inputs = data. inputs . iter ( )
397
450
. 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
+
399
457
let input_ty = ty:: mk_tup ( this. tcx ( ) , inputs) ;
400
458
401
459
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) ,
403
464
None => ty:: mk_nil ( this. tcx ( ) ) ,
404
465
} ;
405
466
@@ -1059,55 +1120,33 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>(
1059
1120
let self_and_input_tys: Vec < Ty > =
1060
1121
self_ty. into_iter ( ) . chain ( input_tys) . collect ( ) ;
1061
1122
1062
- let mut lifetimes_for_params: Vec < ( String , Vec < ty:: Region > ) > = Vec :: new ( ) ;
1063
1123
1064
1124
// Second, if there was exactly one lifetime (either a substitution or a
1065
1125
// reference) in the arguments, then any anonymous regions in the output
1066
1126
// 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 ( ) {
1070
1129
// 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
+ } ;
1088
1134
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
+ } ;
1093
1141
1094
1142
let output_ty = match decl. output {
1095
1143
ast:: Return ( ref output) if output. node == ast:: TyInfer =>
1096
1144
ty:: FnConverging ( this. ty_infer ( output. span ) ) ,
1097
1145
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) ) ,
1111
1150
ast:: NoReturn ( _) => ty:: FnDiverging
1112
1151
} ;
1113
1152
0 commit comments