Skip to content

Commit ae4d40a

Browse files
committed
SILGen: Fix key paths that reference internal private(set) decls from other files.
The setter needs to be given hidden linkage so that other files can still form key paths to it.
1 parent b607e54 commit ae4d40a

File tree

8 files changed

+81
-5
lines changed

8 files changed

+81
-5
lines changed

lib/SIL/SILDeclRef.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -314,8 +314,19 @@ SILLinkage SILDeclRef::getLinkage(ForDefinition_t forDefinition) const {
314314
neverPublic = true;
315315
}
316316
}
317+
318+
auto effectiveAccess = d->getEffectiveAccess();
319+
320+
// Private setter implementations for an internal storage declaration should
321+
// be internal as well, so that a dynamically-writable
322+
// keypath can be formed from other files.
323+
if (auto accessor = dyn_cast<AccessorDecl>(d)) {
324+
if (accessor->isSetter()
325+
&& accessor->getStorage()->getEffectiveAccess() == AccessLevel::Internal)
326+
effectiveAccess = AccessLevel::Internal;
327+
}
317328

318-
switch (d->getEffectiveAccess()) {
329+
switch (effectiveAccess) {
319330
case AccessLevel::Private:
320331
case AccessLevel::FilePrivate:
321332
return maybeAddExternal(SILLinkage::Private);
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
struct A {
2+
private(set) var x: Int {
3+
get { return 0 }
4+
set {}
5+
}
6+
7+
private(set) subscript(x: Int) -> Int {
8+
get { return x }
9+
set {}
10+
}
11+
}

test/SILGen/accessibility_warnings.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ internal struct PrivateSettersForReadOnlyInternal : PublicReadOnlyOperations {
105105
// CHECK-DAG: sil hidden{{( \[.+\])*}} @$S22accessibility_warnings33PrivateSettersForReadOnlyInternalV4sizeSivg
106106
public private(set) var size = 0
107107
// CHECK-DAG: sil hidden @$S22accessibility_warnings33PrivateSettersForReadOnlyInternalVyS2icig
108-
// CHECK-DAG: sil private @$S22accessibility_warnings33PrivateSettersForReadOnlyInternalVyS2icis
108+
// CHECK-DAG: sil hidden @$S22accessibility_warnings33PrivateSettersForReadOnlyInternalVyS2icis
109109
internal private(set) subscript (_: Int) -> Int { // no-warning
110110
get { return 42 }
111111
set {}

test/SILGen/accessors.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ struct Foo {
213213
private(set) subscript(withPrivateSet x: Void) -> Void {
214214
// CHECK-DAG: sil hidden @$S9accessors3FooV14withPrivateSetyyt_tcig : $@convention(method) (Foo) -> () {
215215
get {}
216-
// CHECK-DAG: sil private @$S9accessors3FooV14withPrivateSetyyt_tcis : $@convention(method) (@inout Foo) -> () {
216+
// CHECK-DAG: sil hidden @$S9accessors3FooV14withPrivateSetyyt_tcis : $@convention(method) (@inout Foo) -> () {
217217
set {}
218218
}
219219
subscript(withNestedClass x: Void) -> Void {
@@ -229,7 +229,7 @@ struct Foo {
229229
private(set) var variableWithPrivateSet: Void {
230230
// CHECK-DAG: sil hidden @$S9accessors3FooV22variableWithPrivateSetytvg : $@convention(method) (Foo) -> () {
231231
get {}
232-
// CHECK-DAG: sil private @$S9accessors3FooV22variableWithPrivateSetytvs : $@convention(method) (@inout Foo) -> () {
232+
// CHECK-DAG: sil hidden @$S9accessors3FooV22variableWithPrivateSetytvs : $@convention(method) (@inout Foo) -> () {
233233
set {}
234234
}
235235
var propertyWithNestedClass: Void {

test/SILGen/keypaths_multi_file.swift

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// RUN: %target-swift-emit-silgen -module-name keypaths -primary-file %s %S/Inputs/keypaths_multi_file_b.swift | %FileCheck %s
2+
// RUN: %target-swift-emit-silgen -module-name keypaths %s -primary-file %S/Inputs/keypaths_multi_file_b.swift | %FileCheck --check-prefix=DEFINITION %s
3+
4+
func foo(x: Int) -> KeyPath<A, Int> {
5+
switch x {
6+
case 0:
7+
return \A.x
8+
default:
9+
return \A.[0]
10+
}
11+
return \A.x
12+
}
13+
14+
// A.x setter
15+
// CHECK-LABEL: sil hidden_external @$S8keypaths1AV1xSivs
16+
// DEFINITION-LABEL: sil hidden @$S8keypaths1AV1xSivs
17+
18+
// A.subscript setter
19+
// CHECK-LABEL: sil hidden_external @$S8keypaths1AVyS2icis
20+
// DEFINITION-LABEL: sil hidden @$S8keypaths1AVyS2icis
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
struct A {
2+
private(set) var x: Int {
3+
get { return 0 }
4+
set {}
5+
}
6+
7+
private(set) subscript(x: Int) -> Int {
8+
get { return 0 }
9+
set {}
10+
}
11+
}
12+
13+
func A_x_keypath() -> WritableKeyPath<A, Int> {
14+
return \A.x
15+
}
16+
17+
func A_subscript_0_keypath() -> WritableKeyPath<A, Int> {
18+
return \A.[0]
19+
}

test/stdlib/KeyPath.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
// RUN: %empty-directory(%t)
2-
// RUN: %target-build-swift %s -Xfrontend -enable-sil-ownership -Xfrontend -g -o %t/a.out
2+
// RUN: %target-build-swift %s -o %t/a.out
33
// RUN: %target-run %t/a.out
44
// REQUIRES: executable_test
55

test/stdlib/KeyPathMultiFile.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: cp %s %t/main.swift
3+
// RUN: %target-build-swift -o %t/a.out %t/main.swift %S/Inputs/KeyPathMultiFile_b.swift
4+
// RUN: %target-run %t/a.out
5+
6+
import StdlibUnittest
7+
8+
var keyPathMultiFile = TestSuite("key paths across multiple files")
9+
10+
keyPathMultiFile.test("identity across multiple files") {
11+
expectEqual(A_x_keypath(), \A.x)
12+
expectEqual(A_subscript_0_keypath(), \A.[0])
13+
}
14+
15+
runAllTests()

0 commit comments

Comments
 (0)