@@ -55,6 +55,7 @@ use middle::lang_items::FnMutTraitLangItem;
55
55
use middle:: subst:: { FnSpace , TypeSpace , SelfSpace , Subst , Substs } ;
56
56
use middle:: ty;
57
57
use middle:: ty_fold:: TypeFolder ;
58
+ use middle:: typeck:: rscope:: { ExplicitRscope , ImpliedSingleRscope } ;
58
59
use middle:: typeck:: rscope:: RegionScope ;
59
60
use middle:: typeck:: { TypeAndSubsts , infer, lookup_def_tcx, rscope} ;
60
61
use middle:: typeck;
@@ -931,31 +932,45 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(
931
932
Option < ty:: ExplicitSelfCategory > ) {
932
933
debug ! ( "ty_of_method_or_bare_fn" ) ;
933
934
934
- // new region names that appear inside of the fn decl are bound to
935
- // that function type
935
+ // New region names that appear inside of the arguments of the function
936
+ // declaration are bound to that function type.
936
937
let rb = rscope:: BindingRscope :: new ( id) ;
937
938
939
+ // `implied_output_region` is the region that will be assumed for any
940
+ // region parameters in the return type. In accordance with the rules for
941
+ // lifetime elision, we can determine it in two ways. First (determined
942
+ // here), if self is by-reference, then the implied output region is the
943
+ // region of the self parameter.
938
944
let mut explicit_self_category_result = None ;
939
- let self_ty = opt_self_info. and_then ( |self_info| {
940
- // Figure out and record the explicit self category.
941
- let explicit_self_category =
942
- determine_explicit_self_category ( this, & rb, & self_info) ;
943
- explicit_self_category_result = Some ( explicit_self_category) ;
944
- match explicit_self_category {
945
- ty:: StaticExplicitSelfCategory => None ,
946
- ty:: ByValueExplicitSelfCategory => {
947
- Some ( self_info. untransformed_self_ty )
948
- }
949
- ty:: ByReferenceExplicitSelfCategory ( region, mutability) => {
950
- Some ( ty:: mk_rptr ( this. tcx ( ) , region,
951
- ty:: mt { ty : self_info. untransformed_self_ty ,
952
- mutbl : mutability} ) )
953
- }
954
- ty:: ByBoxExplicitSelfCategory => {
955
- Some ( ty:: mk_uniq ( this. tcx ( ) , self_info. untransformed_self_ty ) )
945
+ let ( self_ty, mut implied_output_region) = match opt_self_info {
946
+ None => ( None , None ) ,
947
+ Some ( self_info) => {
948
+ // Figure out and record the explicit self category.
949
+ let explicit_self_category =
950
+ determine_explicit_self_category ( this, & rb, & self_info) ;
951
+ explicit_self_category_result = Some ( explicit_self_category) ;
952
+ match explicit_self_category {
953
+ ty:: StaticExplicitSelfCategory => ( None , None ) ,
954
+ ty:: ByValueExplicitSelfCategory => {
955
+ ( Some ( self_info. untransformed_self_ty ) , None )
956
+ }
957
+ ty:: ByReferenceExplicitSelfCategory ( region, mutability) => {
958
+ ( Some ( ty:: mk_rptr ( this. tcx ( ) ,
959
+ region,
960
+ ty:: mt {
961
+ ty : self_info. untransformed_self_ty ,
962
+ mutbl : mutability
963
+ } ) ) ,
964
+ Some ( region) )
965
+ }
966
+ ty:: ByBoxExplicitSelfCategory => {
967
+ ( Some ( ty:: mk_uniq ( this. tcx ( ) ,
968
+ self_info. untransformed_self_ty ) ) ,
969
+ None )
970
+ }
956
971
}
957
972
}
958
- } ) ;
973
+ } ;
959
974
960
975
// HACK(eddyb) replace the fake self type in the AST with the actual type.
961
976
let input_tys = if self_ty. is_some ( ) {
@@ -964,12 +979,47 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(
964
979
decl. inputs . as_slice ( )
965
980
} ;
966
981
let input_tys = input_tys. iter ( ) . map ( |a| ty_of_arg ( this, & rb, a, None ) ) ;
982
+ let self_and_input_tys: Vec < _ > =
983
+ self_ty. move_iter ( ) . chain ( input_tys) . collect ( ) ;
984
+
985
+ // Second, if there was exactly one lifetime (either a substitution or a
986
+ // reference) in the arguments, then any anonymous regions in the output
987
+ // have that lifetime.
988
+ if implied_output_region. is_none ( ) {
989
+ let mut self_and_input_tys_iter = self_and_input_tys. iter ( ) ;
990
+ if self_ty. is_some ( ) {
991
+ // Skip the first argument if `self` is present.
992
+ drop ( self_and_input_tys_iter. next ( ) )
993
+ }
967
994
968
- let self_and_input_tys = self_ty. move_iter ( ) . chain ( input_tys) . collect ( ) ;
995
+ let mut accumulator = Vec :: new ( ) ;
996
+ for input_type in self_and_input_tys_iter {
997
+ ty:: accumulate_lifetimes_in_type ( & mut accumulator, * input_type)
998
+ }
999
+ if accumulator. len ( ) == 1 {
1000
+ implied_output_region = Some ( * accumulator. get ( 0 ) ) ;
1001
+ }
1002
+ }
969
1003
970
1004
let output_ty = match decl. output . node {
971
1005
ast:: TyInfer => this. ty_infer ( decl. output . span ) ,
972
- _ => ast_ty_to_ty ( this, & rb, & * decl. output )
1006
+ _ => {
1007
+ match implied_output_region {
1008
+ Some ( implied_output_region) => {
1009
+ let rb = ImpliedSingleRscope {
1010
+ region : implied_output_region,
1011
+ } ;
1012
+ ast_ty_to_ty ( this, & rb, & * decl. output )
1013
+ }
1014
+ None => {
1015
+ // All regions must be explicitly specified in the output
1016
+ // if the lifetime elision rules do not apply. This saves
1017
+ // the user from potentially-confusing errors.
1018
+ let rb = ExplicitRscope ;
1019
+ ast_ty_to_ty ( this, & rb, & * decl. output )
1020
+ }
1021
+ }
1022
+ }
973
1023
} ;
974
1024
975
1025
( ty:: BareFnTy {
0 commit comments