Skip to content

Commit cc1bf0d

Browse files
authored
Merge pull request #73410 from jckarter/noncopyable-subscript-borrow-fix
SILGen: Correct handling of subscripts with addressors.
2 parents 279f3d1 + d08f1c3 commit cc1bf0d

File tree

2 files changed

+34
-29
lines changed

2 files changed

+34
-29
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 14 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3230,36 +3230,18 @@ Expr *SILGenFunction::findStorageReferenceExprForMoveOnly(Expr *argExpr,
32303230
sawLoad = true;
32313231
}
32323232

3233-
// If we have a subscript, strip it off and make sure that our base is
3234-
// something that we can process. If we do and we succeed below, we return the
3235-
// subscript instead.
3236-
SubscriptExpr *subscriptExpr = nullptr;
3237-
if ((subscriptExpr = dyn_cast<SubscriptExpr>(argExpr))) {
3238-
auto *decl = cast<SubscriptDecl>(subscriptExpr->getDecl().getDecl());
3239-
if (decl->getReadImpl() != ReadImplKind::Read) {
3240-
subscriptExpr = nullptr;
3241-
} else {
3242-
argExpr = subscriptExpr->getBase();
3243-
}
3244-
3245-
// If there's a load on the base of the subscript expr, look past it.
3246-
if (auto *li = dyn_cast<LoadExpr>(argExpr)) {
3247-
argExpr = li->getSubExpr();
3248-
}
3249-
}
3250-
32513233
// If we're consuming instead, then the load _must_ have been there.
32523234
if (kind == StorageReferenceOperationKind::Consume && !sawLoad)
32533235
return nullptr;
32543236

3255-
// If we did not see a load or a subscript expr and our argExpr is a
3237+
// If we did not see a load and our argExpr is a
32563238
// declref_expr, return nullptr. We have an object not something that will be
32573239
// in memory. This can happen with classes or with values captured by a
32583240
// closure.
32593241
//
32603242
// NOTE: If we see a member_ref_expr from a decl_ref_expr, we still process it
32613243
// since the declref_expr could be from a class.
3262-
if (!sawLoad && !subscriptExpr) {
3244+
if (!sawLoad) {
32633245
if (auto *declRef = dyn_cast<DeclRefExpr>(argExpr)) {
32643246
assert(!declRef->getType()->is<LValueType>() &&
32653247
"Shouldn't ever have an lvalue type here!");
@@ -3288,18 +3270,27 @@ Expr *SILGenFunction::findStorageReferenceExprForMoveOnly(Expr *argExpr,
32883270
// We want to perform a borrow/consume if the first piece of storage being
32893271
// referenced is a move-only type.
32903272

3291-
VarDecl *storage = nullptr;
3273+
AbstractStorageDecl *storage = nullptr;
32923274
Type type;
32933275
if (auto dre = dyn_cast<DeclRefExpr>(result.getStorageRef())) {
3294-
storage = dyn_cast<VarDecl>(dre->getDecl());
3276+
storage = dyn_cast<AbstractStorageDecl>(dre->getDecl());
32953277
type = dre->getType();
32963278
} else if (auto mre = dyn_cast<MemberRefExpr>(result.getStorageRef())) {
3297-
storage = dyn_cast<VarDecl>(mre->getDecl().getDecl());
3279+
storage = dyn_cast<AbstractStorageDecl>(mre->getDecl().getDecl());
32983280
type = mre->getType();
3281+
} else if (auto se = dyn_cast<SubscriptExpr>(result.getStorageRef())) {
3282+
storage = dyn_cast<AbstractStorageDecl>(se->getDecl().getDecl());
3283+
type = se->getType();
32993284
}
33003285

33013286
if (!storage)
33023287
return nullptr;
3288+
if (!storage->hasStorage()
3289+
&& storage->getReadImpl() != ReadImplKind::Read
3290+
&& storage->getReadImpl() != ReadImplKind::Address) {
3291+
return nullptr;
3292+
}
3293+
33033294
assert(type);
33043295

33053296
SILType ty =
@@ -3312,12 +3303,6 @@ Expr *SILGenFunction::findStorageReferenceExprForMoveOnly(Expr *argExpr,
33123303
if (!isMoveOnly)
33133304
return nullptr;
33143305

3315-
// If we saw a subscript expr and the base of the subscript expr passed our
3316-
// tests above, we can emit the call to the subscript directly as a borrowed
3317-
// lvalue. Return the subscript expr here so that we emit it appropriately.
3318-
if (subscriptExpr)
3319-
return subscriptExpr;
3320-
33213306
return result.getTransitiveRoot();
33223307
}
33233308

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-swift-emit-silgen %s | %FileCheck %s
2+
3+
struct Foo: ~Copyable {
4+
let value: Int
5+
6+
@_silgen_name("load")
7+
borrowing func load() -> Int
8+
}
9+
10+
// CHECK-LABEL: sil {{.*}} @${{.*}}4load
11+
func load(b: UnsafeMutableBufferPointer<Foo>) -> Int {
12+
// Ensure the borrowing invocation of `load` happens within the access to
13+
// the pointed-at memory.
14+
// CHECK: [[PTR:%.*]] = pointer_to_address
15+
// CHECK: [[BEGIN:%.*]] = begin_access [read] [unsafe] [[PTR]]
16+
// CHECK: [[FN:%.*]] = function_ref @load
17+
// CHECK: apply [[FN]]
18+
// CHECK: end_access [[BEGIN]]
19+
return b[1].load()
20+
}

0 commit comments

Comments
 (0)