Skip to content

Commit 759a9ee

Browse files
authored
Merge pull request #12671 from hamishknight/subscript-non-escaping-args
[Sema] Allow non-escaping functions to be passed as subscript arguments
2 parents 323e759 + d734631 commit 759a9ee

File tree

2 files changed

+38
-8
lines changed

2 files changed

+38
-8
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,12 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
233233
if (auto *IOE = dyn_cast<InOutExpr>(SE->getBase()))
234234
if (IOE->isImplicit())
235235
AcceptableInOutExprs.insert(IOE);
236+
237+
visitIndices(SE, [&](unsigned argIndex, Expr *arg) {
238+
arg = lookThroughArgument(arg);
239+
if (auto *DRE = dyn_cast<DeclRefExpr>(arg))
240+
checkNoEscapeParameterUse(DRE, SE, OperandKind::Argument);
241+
});
236242
}
237243

238244
// Check decl refs in withoutActuallyEscaping blocks.
@@ -352,10 +358,12 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
352358
return { true, E };
353359
}
354360

355-
static void visitArguments(ApplyExpr *apply,
356-
llvm::function_ref<void(unsigned, Expr*)> fn) {
357-
auto *arg = apply->getArg();
358-
361+
/// Visit the argument/s represented by either a ParenExpr or TupleExpr,
362+
/// unshuffling if needed. If any other kind of expression, will pass it
363+
/// straight back.
364+
static void argExprVisitArguments(Expr* arg,
365+
llvm::function_ref
366+
<void(unsigned, Expr*)> fn) {
359367
// The argument could be shuffled if it includes default arguments,
360368
// label differences, or other exciting things like that.
361369
if (auto *TSE = dyn_cast<TupleShuffleExpr>(arg))
@@ -373,6 +381,18 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
373381
}
374382
}
375383

384+
static void visitIndices(SubscriptExpr *subscript,
385+
llvm::function_ref<void(unsigned, Expr*)> fn) {
386+
auto *indexArgs = subscript->getIndex();
387+
argExprVisitArguments(indexArgs, fn);
388+
}
389+
390+
static void visitArguments(ApplyExpr *apply,
391+
llvm::function_ref<void(unsigned, Expr*)> fn) {
392+
auto *arg = apply->getArg();
393+
argExprVisitArguments(arg, fn);
394+
}
395+
376396
static Expr *lookThroughArgument(Expr *arg) {
377397
while (1) {
378398
if (auto conv = dyn_cast<ImplicitConversionExpr>(arg))
@@ -655,6 +675,9 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
655675
if (isa<ParamDecl>(DRE->getDecl()) && useKind == OperandKind::Callee)
656676
checkNoEscapeParameterCall(apply);
657677
return;
678+
} else if (isa<SubscriptExpr>(parent)
679+
&& useKind == OperandKind::Argument) {
680+
return;
658681
} else if (isa<MakeTemporarilyEscapableExpr>(parent)) {
659682
return;
660683
}

test/decl/subscript/noescape_accessors.swift

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,15 @@ struct Subscripts {
5454
global = value
5555
}
5656
}
57+
58+
subscript(nonescapingIndexWithAddressor fn: () -> Void) -> Int {
59+
get {
60+
return 0
61+
}
62+
mutableAddressWithNativeOwner {
63+
fatalError()
64+
}
65+
}
5766

5867
// expected-note@+1 2 {{implicitly non-escaping}}
5968
subscript(nonescapingIndex fn: () -> ()) -> Int {
@@ -95,14 +104,12 @@ func testSubscripts_value2(nonescaping: () -> (),
95104
s[value2: 0] = nonescaping // expected-error {{assigning non-escaping parameter}}
96105
}
97106

98-
// FIXME: Allow these uses in subscript expressions!
99-
// expected-note@+1 2 {{implicitly non-escaping}}
100107
func testSubscripts_nonescapingIndex(nonescaping: () -> (),
101108
escaping: @escaping () -> ()) {
102109
var s = Subscripts()
103-
_ = s[nonescapingIndex: nonescaping] // expected-error{{may only be called}}
110+
_ = s[nonescapingIndex: nonescaping]
104111
_ = s[nonescapingIndex: escaping]
105-
s[nonescapingIndex: nonescaping] = 0 // expected-error{{may only be called}}
112+
s[nonescapingIndex: nonescaping] = 0
106113
s[nonescapingIndex: escaping] = 0
107114
}
108115

0 commit comments

Comments
 (0)