@@ -55,6 +55,7 @@ use middle::lang_items::FnMutTraitLangItem;
5555use middle:: subst:: { FnSpace , TypeSpace , SelfSpace , Subst , Substs } ;
5656use middle:: ty;
5757use middle:: ty_fold:: TypeFolder ;
58+ use middle:: typeck:: rscope:: { ExplicitRscope , ImpliedSingleRscope } ;
5859use middle:: typeck:: rscope:: RegionScope ;
5960use middle:: typeck:: { TypeAndSubsts , infer, lookup_def_tcx, rscope} ;
6061use middle:: typeck;
@@ -931,31 +932,45 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(
931932 Option < ty:: ExplicitSelfCategory > ) {
932933 debug ! ( "ty_of_method_or_bare_fn" ) ;
933934
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.
936937 let rb = rscope:: BindingRscope :: new ( id) ;
937938
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.
938944 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+ }
956971 }
957972 }
958- } ) ;
973+ } ;
959974
960975 // HACK(eddyb) replace the fake self type in the AST with the actual type.
961976 let input_tys = if self_ty. is_some ( ) {
@@ -964,12 +979,47 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(
964979 decl. inputs . as_slice ( )
965980 } ;
966981 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+ }
967994
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+ }
9691003
9701004 let output_ty = match decl. output . node {
9711005 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+ }
9731023 } ;
9741024
9751025 ( ty:: BareFnTy {
0 commit comments