@@ -2968,6 +2968,29 @@ Expr *ArgumentSource::findStorageReferenceExprForMoveOnlyBorrow(
29682968 return lvExpr;
29692969}
29702970
2971+ Expr *
2972+ ArgumentSource::findStorageReferenceExprForBorrowExpr (SILGenFunction &SGF) && {
2973+ if (!isExpr ())
2974+ return nullptr ;
2975+
2976+ auto argExpr = asKnownExpr ();
2977+ auto *li = dyn_cast<LoadExpr>(argExpr);
2978+ if (!li)
2979+ return nullptr ;
2980+ auto *borrowExpr = dyn_cast<BorrowExpr>(li->getSubExpr ());
2981+ if (!borrowExpr)
2982+ return nullptr ;
2983+
2984+ auto *lvExpr = ::findStorageReferenceExprForBorrow (borrowExpr->getSubExpr ());
2985+
2986+ // Claim the value of this argument.
2987+ if (lvExpr) {
2988+ (void )std::move (*this ).asKnownExpr ();
2989+ }
2990+
2991+ return lvExpr;
2992+ }
2993+
29712994Expr *ArgumentSource::findStorageReferenceExprForBorrow () && {
29722995 if (!isExpr ()) return nullptr ;
29732996
@@ -3097,18 +3120,23 @@ class ArgEmitter {
30973120 return ;
30983121 }
30993122
3100- // If this is a yield, and the yield is borrowed, emit a borrowed r-value.
3101- if (IsYield && param.isGuaranteed ()) {
3102- if (tryEmitBorrowed (std::move (arg), loweredSubstArgType,
3103- loweredSubstParamType, origParamType, paramSlice))
3123+ // If we have a guaranteed +0 parameter...
3124+ if (param.isGuaranteed ()) {
3125+ // And this is a yield, emit a borrowed r-value.
3126+ if (IsYield) {
3127+ if (tryEmitBorrowed (std::move (arg), loweredSubstArgType,
3128+ loweredSubstParamType, origParamType, paramSlice))
3129+ return ;
3130+ }
3131+
3132+ if (tryEmitBorrowExpr (std::move (arg), loweredSubstArgType,
3133+ loweredSubstParamType, origParamType, paramSlice))
31043134 return ;
3105- }
31063135
3107- // If we have a guaranteed paramter, see if we have a move only type and can
3108- // emit it borrow.
3109- //
3110- // We check for move only in tryEmitBorrowedMoveOnly.
3111- if (param.isGuaranteed ()) {
3136+ // If we have a guaranteed paramter, see if we have a move only type and
3137+ // can emit it borrow.
3138+ //
3139+ // We check for move only in tryEmitBorrowedMoveOnly.
31123140 if (tryEmitBorrowedMoveOnly (std::move (arg), loweredSubstArgType,
31133141 loweredSubstParamType, origParamType,
31143142 paramSlice))
@@ -3302,6 +3330,23 @@ class ArgEmitter {
33023330 return true ;
33033331 }
33043332
3333+ bool tryEmitBorrowExpr (ArgumentSource &&arg, SILType loweredSubstArgType,
3334+ SILType loweredSubstParamType,
3335+ AbstractionPattern origParamType,
3336+ ClaimedParamsRef paramsSlice) {
3337+ assert (paramsSlice.size () == 1 );
3338+
3339+ // Try to find an expression we can emit as a borrowed l-value.
3340+ auto lvExpr = std::move (arg).findStorageReferenceExprForBorrowExpr (SGF);
3341+ if (!lvExpr)
3342+ return false ;
3343+
3344+ emitBorrowed (lvExpr, loweredSubstArgType, loweredSubstParamType,
3345+ origParamType, paramsSlice);
3346+
3347+ return true ;
3348+ }
3349+
33053350 void emitBorrowed (Expr *arg, SILType loweredSubstArgType,
33063351 SILType loweredSubstParamType,
33073352 AbstractionPattern origParamType,
0 commit comments