Skip to content

Commit f3d3613

Browse files
authored
Merge pull request #85042 from jckarter/subscript-borrowable-base
SILGen: Subscripts can also be borrowed bases.
2 parents 74a0935 + d7ea0b8 commit f3d3613

File tree

2 files changed

+73
-16
lines changed

2 files changed

+73
-16
lines changed

lib/SILGen/SILGenLValue.cpp

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
#include "SILGen.h"
2727
#include "SILGenFunction.h"
2828
#include "Scope.h"
29+
#include "swift/AST/Decl.h"
2930
#include "swift/AST/DiagnosticsCommon.h"
3031
#include "swift/AST/DiagnosticsSIL.h"
3132
#include "swift/AST/GenericEnvironment.h"
@@ -3072,15 +3073,16 @@ class LLVM_LIBRARY_VISIBILITY SILGenBorrowedBaseVisitor
30723073

30733074
static bool isNonCopyableBaseBorrow(SILGenFunction &SGF, Expr *e,
30743075
LValueOptions options) {
3075-
if (auto *m = dyn_cast<MemberRefExpr>(e)) {
3076+
if (LookupExpr *le;
3077+
(le = dyn_cast<MemberRefExpr>(e)) || (le = dyn_cast<SubscriptExpr>(e))) {
30763078
// If our m is a pure noncopyable type or our base is, we need to perform
30773079
// a noncopyable base borrow.
30783080
//
30793081
// DISCUSSION: We can have a noncopyable member_ref_expr with a copyable
30803082
// base if the noncopyable member_ref_expr is from a computed method. In
30813083
// such a case, we want to ensure that we wrap things the right way.
3082-
if (m->getType()->isNoncopyable() ||
3083-
m->getBase()->getType()->isNoncopyable()) {
3084+
if (le->getType()->isNoncopyable() ||
3085+
le->getBase()->getType()->isNoncopyable()) {
30843086
return true;
30853087
}
30863088

@@ -3140,18 +3142,17 @@ class LLVM_LIBRARY_VISIBILITY SILGenBorrowedBaseVisitor
31403142
return SGL.visitRec(e, accessKind, options, Orig);
31413143
}
31423144

3143-
LValue visitMemberRefExpr(MemberRefExpr *e, SGFAccessKind accessKind,
3144-
LValueOptions options) {
3145-
// If we have a member_ref_expr, we create a component that will when we
3146-
// evaluate the lvalue,
3147-
VarDecl *var = cast<VarDecl>(e->getMember().getDecl());
3148-
3145+
LValue getLookupExprBaseLValue(LookupExpr *e, AccessSemantics accessSemantics,
3146+
SGFAccessKind accessKind,
3147+
LValueOptions options,
3148+
AccessStrategy &strategy) {
3149+
auto storage = cast<AbstractStorageDecl>(e->getMember().getDecl());
3150+
31493151
assert(!e->getType()->is<LValueType>());
31503152

31513153
auto pair = std::make_pair<>(e->getSourceRange(), SGF.FunctionDC);
31523154

3153-
auto accessSemantics = e->getAccessSemantics();
3154-
AccessStrategy strategy = var->getAccessStrategy(
3155+
strategy = storage->getAccessStrategy(
31553156
accessSemantics, getFormalAccessKind(accessKind),
31563157
SGF.SGM.M.getSwiftModule(), SGF.F.getResilienceExpansion(), pair,
31573158
/*useOldABI=*/false);
@@ -3168,21 +3169,54 @@ class LLVM_LIBRARY_VISIBILITY SILGenBorrowedBaseVisitor
31683169
orig = AbstractionPattern::getOpaque();
31693170
}
31703171

3171-
LValue lv = visit(
3172+
return visit(
31723173
e->getBase(),
3173-
getBaseAccessKind(SGF.SGM, var, accessKind, strategy, baseFormalType,
3174+
getBaseAccessKind(SGF.SGM, storage, accessKind, strategy, baseFormalType,
31743175
/*for borrow*/ true),
31753176
getBaseOptions(options, strategy, addressable));
3177+
}
3178+
3179+
LValue visitSubscriptExpr(SubscriptExpr *e, SGFAccessKind accessKind,
3180+
LValueOptions options) {
3181+
AccessStrategy strategy = AccessStrategy::getStorage();
3182+
LValue lv = getLookupExprBaseLValue(e, e->getAccessSemantics(),
3183+
accessKind, options,
3184+
strategy);
3185+
auto subs = e->getMember().getSubstitutions();
3186+
3187+
auto subscript = cast<SubscriptDecl>(e->getMember().getDecl());
3188+
3189+
auto storageCanType = SGF.prepareStorageType(subscript, subs);
3190+
auto indices = SGF.prepareIndices(e, storageCanType, strategy, e->getArgs());
3191+
3192+
lv.addMemberSubscriptComponent(SGF, e, subscript, subs,
3193+
options, e->isSuper(), accessKind, strategy,
3194+
getSubstFormalRValueType(e),
3195+
std::move(indices),
3196+
e->getArgs());
3197+
return lv;
3198+
}
3199+
3200+
LValue visitMemberRefExpr(MemberRefExpr *e, SGFAccessKind accessKind,
3201+
LValueOptions options) {
3202+
AccessStrategy strategy = AccessStrategy::getStorage();
3203+
LValue lv = getLookupExprBaseLValue(e, e->getAccessSemantics(),
3204+
accessKind, options,
3205+
strategy);
3206+
3207+
auto var = cast<VarDecl>(e->getMember().getDecl());
3208+
31763209
std::optional<ActorIsolation> actorIso;
31773210
if (e->isImplicitlyAsync())
31783211
actorIso = getActorIsolation(var);
3179-
lv.addMemberVarComponent(SGF, e, var, e->getMember().getSubstitutions(),
3212+
3213+
lv.addMemberVarComponent(SGF, e, var,
3214+
e->getMember().getSubstitutions(),
31803215
options, e->isSuper(), accessKind, strategy,
3181-
formalRValueType,
3216+
getSubstFormalRValueType(e),
31823217
false /*is on self parameter*/, actorIso);
31833218

31843219
SGF.SGM.noteMemberRefExpr(e);
3185-
31863220
return lv;
31873221
}
31883222

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// RUN: %target-swift-frontend -emit-sil -verify %s
2+
3+
func test(foo: borrowing Foo, s: String) -> Bool {
4+
return foo.children[0].name == s
5+
}
6+
7+
func test2(foo: borrowing Foo) -> String {
8+
return foo.children[0].name
9+
}
10+
11+
struct Foo: ~Copyable {
12+
var children: Bar<Foo>
13+
var name: String
14+
}
15+
16+
struct Bar<T: ~Copyable>: ~Copyable {
17+
subscript(x: Int) -> T {
18+
_read {
19+
fatalError()
20+
}
21+
}
22+
}
23+

0 commit comments

Comments
 (0)