Skip to content

Commit 27515c9

Browse files
authored
Merge pull request #10245 from slavapestov/local-generic-function-captures
SILGen: Fix problems with local generic functions
2 parents 55e8172 + 28c35ff commit 27515c9

File tree

4 files changed

+88
-12
lines changed

4 files changed

+88
-12
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -868,13 +868,17 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
868868

869869
auto afd = dyn_cast<AbstractFunctionDecl>(e->getDecl());
870870

871+
CaptureInfo captureInfo;
872+
871873
// Otherwise, we have a statically-dispatched call.
872-
SubstitutionList subs;
873-
if (e->getDeclRef().isSpecialized() &&
874-
(!afd ||
875-
!afd->getDeclContext()->isLocalContext() ||
876-
afd->getCaptureInfo().hasGenericParamCaptures()))
877-
subs = e->getDeclRef().getSubstitutions();
874+
SubstitutionList subs = e->getDeclRef().getSubstitutions();
875+
876+
if (afd) {
877+
captureInfo = SGF.SGM.Types.getLoweredLocalCaptures(afd);
878+
if (afd->getDeclContext()->isLocalContext() &&
879+
!captureInfo.hasGenericParamCaptures())
880+
subs = SubstitutionList();
881+
}
878882

879883
// Enum case constructor references are open-coded.
880884
if (isa<EnumElementDecl>(e->getDecl()))
@@ -884,7 +888,7 @@ class SILGenApply : public Lowering::ExprVisitor<SILGenApply> {
884888

885889
// If the decl ref requires captures, emit the capture params.
886890
if (afd) {
887-
if (SGF.SGM.M.Types.hasLoweredLocalCaptures(afd)) {
891+
if (!captureInfo.getCaptures().empty()) {
888892
SmallVector<ManagedValue, 4> captures;
889893
SGF.emitCaptures(e, afd, CaptureEmission::ImmediateApplication,
890894
captures);
@@ -4900,6 +4904,15 @@ static Callee getBaseAccessorFunctionRef(SILGenFunction &SGF,
49004904
SubstitutionList subs) {
49014905
auto *decl = cast<AbstractFunctionDecl>(constant.getDecl());
49024906

4907+
// The accessor might be a local function that does not capture any
4908+
// generic parameters, in which case we don't want to pass in any
4909+
// substitutions.
4910+
auto captureInfo = SGF.SGM.Types.getLoweredLocalCaptures(decl);
4911+
if (decl->getDeclContext()->isLocalContext() &&
4912+
!captureInfo.hasGenericParamCaptures()) {
4913+
subs = SubstitutionList();
4914+
}
4915+
49034916
// If this is a method in a protocol, generate it as a protocol call.
49044917
if (isa<ProtocolDecl>(decl->getDeclContext())) {
49054918
assert(!isDirectUse && "direct use of protocol accessor?");

lib/Sema/TypeCheckCaptures.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,14 @@ class FindCapturedVars : public ASTWalker {
229229
std::pair<bool, Expr *> walkToDeclRefExpr(DeclRefExpr *DRE) {
230230
auto *D = DRE->getDecl();
231231

232-
// Capture the generic parameters of the decl.
233-
if (!AFR.isObjC() || !D->isObjC() || isa<ConstructorDecl>(D)) {
234-
for (auto sub : DRE->getDeclRef().getSubstitutions()) {
235-
checkType(sub.getReplacement(), DRE->getLoc());
232+
// Capture the generic parameters of the decl, unless it's a
233+
// local declaration in which case we will pick up generic
234+
// parameter references transitively.
235+
if (!D->getDeclContext()->isLocalContext()) {
236+
if (!AFR.isObjC() || !D->isObjC() || isa<ConstructorDecl>(D)) {
237+
for (auto sub : DRE->getDeclRef().getSubstitutions()) {
238+
checkType(sub.getReplacement(), DRE->getLoc());
239+
}
236240
}
237241
}
238242

test/SILGen/generic_closures.swift

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,27 @@ var zero: Int
88
func generic_nondependent_context<T>(_ x: T, y: Int) -> Int {
99
func foo() -> Int { return y }
1010

11+
func bar() -> Int { return y }
12+
1113
// CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A21_nondependent_context{{.*}} : $@convention(thin) (Int) -> Int
1214
// CHECK: [[FOO_CLOSURE:%.*]] = partial_apply [[FOO]](%1)
1315
// CHECK: destroy_value [[FOO_CLOSURE]]
1416
let _ = foo
1517

18+
// CHECK: [[BAR:%.*]] = function_ref @_T016generic_closures0A21_nondependent_context{{.*}} : $@convention(thin) (Int) -> Int
19+
// CHECK: [[BAR_CLOSURE:%.*]] = partial_apply [[BAR]](%1)
20+
// CHECK: destroy_value [[BAR_CLOSURE]]
21+
let _ = bar
22+
1623
// CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A21_nondependent_context{{.*}} : $@convention(thin) (Int) -> Int
1724
// CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]
18-
return foo()
25+
_ = foo()
26+
27+
// CHECK: [[BAR:%.*]] = function_ref @_T016generic_closures0A21_nondependent_context{{.*}} : $@convention(thin) (Int) -> Int
28+
// CHECK: [[BAR_CLOSURE:%.*]] = apply [[BAR]]
29+
30+
// CHECK: [[BAR_CLOSURE]]
31+
return bar()
1932
}
2033

2134
// CHECK-LABEL: sil hidden @_T016generic_closures0A8_capture{{[_0-9a-zA-Z]*}}F
@@ -29,6 +42,8 @@ func generic_capture<T>(_ x: T) -> Any.Type {
2942

3043
// CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A8_capture{{.*}} : $@convention(thin) <τ_0_0> () -> @thick Any.Type
3144
// CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]<T>()
45+
46+
// CHECK: return [[FOO_CLOSURE]]
3247
return foo()
3348
}
3449

@@ -43,6 +58,8 @@ func generic_capture_cast<T>(_ x: T, y: Any) -> Bool {
4358

4459
// CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A13_capture_cast{{.*}} : $@convention(thin) <τ_0_0> (@in Any) -> Bool
4560
// CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]<T>([[ARG:%.*]])
61+
62+
// CHECK: return [[FOO_CLOSURE]]
4663
return foo(y)
4764
}
4865

@@ -61,6 +78,8 @@ func generic_nocapture_existential<T>(_ x: T, y: Concept) -> Bool {
6178

6279
// CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A22_nocapture_existential{{.*}} : $@convention(thin) (@in Concept) -> Bool
6380
// CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]([[ARG:%.*]])
81+
82+
// CHECK: return [[FOO_CLOSURE]]
6483
return foo(y)
6584
}
6685

@@ -75,6 +94,8 @@ func generic_dependent_context<T>(_ x: T, y: Int) -> T {
7594

7695
// CHECK: [[FOO:%.*]] = function_ref @_T016generic_closures0A18_dependent_context{{.*}} : $@convention(thin) <τ_0_0> (@owned <τ_0_0> { var τ_0_0 } <τ_0_0>) -> @out τ_0_0
7796
// CHECK: [[FOO_CLOSURE:%.*]] = apply [[FOO]]<T>
97+
98+
// CHECK: return
7899
return foo()
79100
}
80101

test/SILGen/properties.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,25 @@ func logical_local_get(_ x: Int) -> Int {
325325
// CHECK-: sil private [[PROP_GET_CLOSURE]]
326326
// CHECK: bb0(%{{[0-9]+}} : $Int):
327327

328+
func logical_generic_local_get<T>(_ x: Int, _: T) {
329+
var prop1: Int {
330+
get {
331+
return x
332+
}
333+
}
334+
335+
_ = prop1
336+
337+
var prop2: Int {
338+
get {
339+
_ = T.self
340+
return x
341+
}
342+
}
343+
344+
_ = prop2
345+
}
346+
328347
// CHECK-LABEL: sil hidden @_T010properties26logical_local_captured_get{{[_0-9a-zA-Z]*}}F
329348
func logical_local_captured_get(_ x: Int) -> Int {
330349
var prop : Int {
@@ -654,7 +673,26 @@ func local_observing_property(_ arg: Int) {
654673
// CHECK: [[PB:%.*]] = project_box [[BOX]]
655674
// CHECK: store [[ARG]] to [trivial] [[PB]]
656675

676+
func local_generic_observing_property<T>(_ arg: Int, _: T) {
677+
var localproperty1: Int = arg {
678+
didSet {
679+
takeInt(localproperty1)
680+
}
681+
}
682+
683+
takeInt(localproperty1)
684+
localproperty1 = arg
657685

686+
var localproperty2: Int = arg {
687+
didSet {
688+
_ = T.self
689+
takeInt(localproperty2)
690+
}
691+
}
692+
693+
takeInt(localproperty2)
694+
localproperty2 = arg
695+
}
658696

659697

660698
// <rdar://problem/16006333> observing properties don't work in @objc classes

0 commit comments

Comments
 (0)