@@ -1338,7 +1338,8 @@ static SGFAccessKind getBaseAccessKind(SILGenModule &SGM,
13381338 AbstractStorageDecl *member,
13391339 SGFAccessKind accessKind,
13401340 AccessStrategy strategy,
1341- CanType baseFormalType);
1341+ CanType baseFormalType,
1342+ bool forBorrowExpr);
13421343
13431344namespace {
13441345 // / A helper class for implementing components that involve accessing
@@ -1977,7 +1978,8 @@ namespace {
19771978 if (!base) return LValue ();
19781979 auto baseAccessKind =
19791980 getBaseAccessKind (SGF.SGM , Storage, accessKind, strategy,
1980- BaseFormalType);
1981+ BaseFormalType,
1982+ /* for borrow*/ false );
19811983 return LValue::forValue (baseAccessKind, base, BaseFormalType);
19821984 }();
19831985
@@ -3055,7 +3057,8 @@ class LLVM_LIBRARY_VISIBILITY SILGenBorrowedBaseVisitor
30553057 auto baseFormalType = getBaseFormalType (e->getBase ());
30563058 LValue lv = visit (
30573059 e->getBase (),
3058- getBaseAccessKind (SGF.SGM , var, accessKind, strategy, baseFormalType),
3060+ getBaseAccessKind (SGF.SGM , var, accessKind, strategy, baseFormalType,
3061+ /* for borrow*/ true ),
30593062 getBaseOptions (options, strategy));
30603063 llvm::Optional<ActorIsolation> actorIso;
30613064 if (e->isImplicitlyAsync ())
@@ -3724,14 +3727,50 @@ LValue SILGenLValue::visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *e,
37243727 return visitRec (e->getRHS (), accessKind, options);
37253728}
37263729
3730+ // / Should the self argument of the given method always be emitted as
3731+ // / an r-value (meaning that it can be borrowed only if that is not
3732+ // / semantically detectable), or it acceptable to emit it as a borrowed
3733+ // / storage reference?
3734+ static bool shouldEmitSelfAsRValue (AccessorDecl *fn, CanType selfType,
3735+ bool forBorrowExpr) {
3736+ if (fn->isStatic ())
3737+ return true ;
3738+
3739+ switch (fn->getSelfAccessKind ()) {
3740+ case SelfAccessKind::Mutating:
3741+ return false ;
3742+ case SelfAccessKind::Borrowing:
3743+ case SelfAccessKind::NonMutating:
3744+ // If the accessor is a coroutine, we may want to access the projected
3745+ // value through a borrow of the base. But if it's a regular get/set then
3746+ // there isn't any real benefit to doing so.
3747+ if (!fn->isCoroutine ()) {
3748+ return true ;
3749+ }
3750+ // Normally we'll copy the base to minimize accesses. But if the base
3751+ // is noncopyable, or we're accessing it in a `borrow` expression, then
3752+ // we want to keep the access nested on the original base.
3753+ if (forBorrowExpr || selfType->isNoncopyable ()) {
3754+ return false ;
3755+ }
3756+ return true ;
3757+
3758+ case SelfAccessKind::LegacyConsuming:
3759+ case SelfAccessKind::Consuming:
3760+ return true ;
3761+ }
3762+ llvm_unreachable (" bad self-access kind" );
3763+ }
3764+
37273765static SGFAccessKind getBaseAccessKindForAccessor (SILGenModule &SGM,
37283766 AccessorDecl *accessor,
3729- CanType baseFormalType) {
3767+ CanType baseFormalType,
3768+ bool forBorrowExpr) {
37303769 if (accessor->isMutating ())
37313770 return SGFAccessKind::ReadWrite;
37323771
37333772 auto declRef = SGM.getAccessorDeclRef (accessor, ResilienceExpansion::Minimal);
3734- if (SGM. shouldEmitSelfAsRValue (accessor, baseFormalType)) {
3773+ if (shouldEmitSelfAsRValue (accessor, baseFormalType, forBorrowExpr )) {
37353774 return SGM.isNonMutatingSelfIndirect (declRef)
37363775 ? SGFAccessKind::OwnedAddressRead
37373776 : SGFAccessKind::OwnedObjectRead;
@@ -3755,7 +3794,8 @@ static SGFAccessKind getBaseAccessKind(SILGenModule &SGM,
37553794 AbstractStorageDecl *member,
37563795 SGFAccessKind accessKind,
37573796 AccessStrategy strategy,
3758- CanType baseFormalType) {
3797+ CanType baseFormalType,
3798+ bool forBorrowExpr) {
37593799 switch (strategy.getKind ()) {
37603800 case AccessStrategy::Storage:
37613801 return getBaseAccessKindForStorage (accessKind);
@@ -3764,7 +3804,8 @@ static SGFAccessKind getBaseAccessKind(SILGenModule &SGM,
37643804 assert (accessKind == SGFAccessKind::ReadWrite);
37653805 auto writeBaseKind = getBaseAccessKind (SGM, member, SGFAccessKind::Write,
37663806 strategy.getWriteStrategy (),
3767- baseFormalType);
3807+ baseFormalType,
3808+ /* for borrow*/ false );
37683809
37693810 // Fast path for the common case that the write will need to mutate
37703811 // the base.
@@ -3774,7 +3815,8 @@ static SGFAccessKind getBaseAccessKind(SILGenModule &SGM,
37743815 auto readBaseKind = getBaseAccessKind (SGM, member,
37753816 SGFAccessKind::OwnedAddressRead,
37763817 strategy.getReadStrategy (),
3777- baseFormalType);
3818+ baseFormalType,
3819+ /* for borrow*/ false );
37783820
37793821 // If they're the same kind, just use that.
37803822 if (readBaseKind == writeBaseKind)
@@ -3793,7 +3835,8 @@ static SGFAccessKind getBaseAccessKind(SILGenModule &SGM,
37933835 case AccessStrategy::DispatchToAccessor:
37943836 case AccessStrategy::DispatchToDistributedThunk: {
37953837 auto accessor = member->getOpaqueAccessor (strategy.getAccessor ());
3796- return getBaseAccessKindForAccessor (SGM, accessor, baseFormalType);
3838+ return getBaseAccessKindForAccessor (SGM, accessor, baseFormalType,
3839+ forBorrowExpr);
37973840 }
37983841 }
37993842 llvm_unreachable (" bad access strategy" );
@@ -3870,7 +3913,8 @@ LValue SILGenLValue::visitMemberRefExpr(MemberRefExpr *e,
38703913
38713914 LValue lv = visitRec (e->getBase (),
38723915 getBaseAccessKind (SGF.SGM , var, accessKind, strategy,
3873- getBaseFormalType (e->getBase ())),
3916+ getBaseFormalType (e->getBase ()),
3917+ /* for borrow */ false ),
38743918 getBaseOptions (options, strategy));
38753919 assert (lv.isValid ());
38763920
@@ -4075,7 +4119,8 @@ LValue SILGenLValue::visitSubscriptExpr(SubscriptExpr *e,
40754119
40764120 LValue lv = visitRec (e->getBase (),
40774121 getBaseAccessKind (SGF.SGM , decl, accessKind, strategy,
4078- getBaseFormalType (e->getBase ())),
4122+ getBaseFormalType (e->getBase ()),
4123+ /* for borrow*/ false ),
40794124 getBaseOptions (options, strategy));
40804125 assert (lv.isValid ());
40814126
@@ -4432,7 +4477,8 @@ LValue SILGenFunction::emitPropertyLValue(SILLocation loc, ManagedValue base,
44324477 F.getResilienceExpansion ());
44334478
44344479 auto baseAccessKind =
4435- getBaseAccessKind (SGM, ivar, accessKind, strategy, baseFormalType);
4480+ getBaseAccessKind (SGM, ivar, accessKind, strategy, baseFormalType,
4481+ /* for borrow*/ false );
44364482
44374483 LValueTypeData baseTypeData =
44384484 getValueTypeData (baseAccessKind, baseFormalType, base.getValue ());
@@ -5155,7 +5201,8 @@ RValue SILGenFunction::emitRValueForStorageLoad(
51555201 if (!base) return LValue ();
51565202
51575203 auto baseAccess = getBaseAccessKind (SGM, storage, accessKind,
5158- strategy, baseFormalType);
5204+ strategy, baseFormalType,
5205+ /* for borrow*/ false );
51595206 return LValue::forValue (baseAccess, base, baseFormalType);
51605207 }();
51615208
0 commit comments