Skip to content

Commit 6d160a2

Browse files
authored
Merge pull request #75243 from xedin/inlinable-init-accessors-6.0
[6.0][AST/Sema] Make it possible to use init accessors in inlinable initializers
2 parents d395c5d + 5e2f46d commit 6d160a2

12 files changed

+282
-29
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6861,8 +6861,8 @@ ERROR(frozen_attr_on_internal_type,
68616861

68626862
ERROR(usable_from_inline_attr_with_explicit_access,
68636863
none, "'@usableFromInline' attribute can only be applied to internal or package "
6864-
"declarations, but %0 is %select{private|fileprivate|%error|package|public|open}1",
6865-
(DeclName, AccessLevel))
6864+
"declarations, but %kind0 is %select{private|fileprivate|%error|package|public|open}1",
6865+
(const ValueDecl *, AccessLevel))
68666866

68676867
WARNING(inlinable_implies_usable_from_inline,none,
68686868
"'@usableFromInline' attribute has no effect on '@inlinable' %kind0",

lib/AST/ASTPrinter.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -352,11 +352,6 @@ PrintOptions PrintOptions::printSwiftInterfaceFile(ModuleDecl *ModuleToPrint,
352352
}
353353
}
354354

355-
if (auto *accessor = dyn_cast<AccessorDecl>(D)) {
356-
if (accessor->isInitAccessor() && !options.PrintForSIL)
357-
return false;
358-
}
359-
360355
return ShouldPrintChecker::shouldPrint(D, options);
361356
}
362357
};

lib/AST/AccessRequests.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,8 @@ AccessLevelRequest::evaluate(Evaluator &evaluator, ValueDecl *D) const {
6565
// These are only needed to synthesize the setter.
6666
return AccessLevel::Private;
6767
case AccessorKind::Init:
68-
// These are only called from designated initializers.
69-
return AccessLevel::Private;
68+
// These are only called from within the same module.
69+
return AccessLevel::Internal;
7070
}
7171
}
7272

lib/Sema/ResilienceDiagnostics.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,17 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
6363
auto *DC = where.getDeclContext();
6464
auto &Context = DC->getASTContext();
6565

66+
if (auto *init = dyn_cast<ConstructorDecl>(DC)) {
67+
if (init->isDesignatedInit()) {
68+
auto *storage = dyn_cast<AbstractStorageDecl>(D);
69+
if (storage && storage->hasInitAccessor()) {
70+
if (diagnoseInlinableDeclRefAccess(
71+
loc, storage->getAccessor(AccessorKind::Init), where))
72+
return true;
73+
}
74+
}
75+
}
76+
6677
ImportAccessLevel problematicImport = D->getImportAccessFrom(DC);
6778
if (problematicImport.has_value()) {
6879
auto SF = DC->getParentSourceFile();
@@ -111,7 +122,7 @@ bool TypeChecker::diagnoseInlinableDeclRefAccess(SourceLoc loc,
111122

112123
// Swift 4.2 did not check accessor accessibility.
113124
if (auto accessor = dyn_cast<AccessorDecl>(D)) {
114-
if (!Context.isSwiftVersionAtLeast(5))
125+
if (!accessor->isInitAccessor() && !Context.isSwiftVersionAtLeast(5))
115126
downgradeToWarning = DowngradeToWarning::Yes;
116127
}
117128

lib/Sema/TypeCheckAttr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3243,7 +3243,7 @@ void AttributeChecker::visitUsableFromInlineAttr(UsableFromInlineAttr *attr) {
32433243
VD->getFormalAccess() != AccessLevel::Package) {
32443244
diagnoseAndRemoveAttr(attr,
32453245
diag::usable_from_inline_attr_with_explicit_access,
3246-
VD->getName(), VD->getFormalAccess());
3246+
VD, VD->getFormalAccess());
32473247
return;
32483248
}
32493249

test/Compatibility/attr_usableFromInline_swift4.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
// RUN: %target-typecheck-verify-swift -enable-testing -swift-version 4 -disable-objc-attr-requires-foundation-module -enable-objc-interop
33

44
@usableFromInline private func privateVersioned() {}
5-
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but 'privateVersioned()' is private}}
5+
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but global function 'privateVersioned()' is private}}
66

77
@usableFromInline fileprivate func fileprivateVersioned() {}
8-
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but 'fileprivateVersioned()' is fileprivate}}
8+
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but global function 'fileprivateVersioned()' is fileprivate}}
99

1010
@usableFromInline internal func internalVersioned() {}
1111
// OK
@@ -14,11 +14,11 @@
1414
// OK
1515

1616
@usableFromInline public func publicVersioned() {}
17-
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but 'publicVersioned()' is public}}
17+
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but global function 'publicVersioned()' is public}}
1818

1919
internal class InternalClass {
2020
@usableFromInline public func publicVersioned() {}
21-
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but 'publicVersioned()' is public}}
21+
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but instance method 'publicVersioned()' is public}}
2222
}
2323

2424
fileprivate class filePrivateClass {

test/Compatibility/attr_usableFromInline_swift42.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
// RUN: %target-typecheck-verify-swift -enable-testing -swift-version 4.2 -disable-objc-attr-requires-foundation-module -enable-objc-interop
33

44
@usableFromInline private func privateVersioned() {}
5-
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but 'privateVersioned()' is private}}
5+
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but global function 'privateVersioned()' is private}}
66

77
@usableFromInline fileprivate func fileprivateVersioned() {}
8-
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but 'fileprivateVersioned()' is fileprivate}}
8+
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but global function 'fileprivateVersioned()' is fileprivate}}
99

1010
@usableFromInline internal func internalVersioned() {}
1111
// OK
@@ -14,12 +14,12 @@
1414
// OK
1515

1616
@usableFromInline public func publicVersioned() {}
17-
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but 'publicVersioned()' is public}}
17+
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but global function 'publicVersioned()' is public}}
1818

1919
internal class InternalClass {
2020
// expected-note@-1 2{{type declared here}}
2121
@usableFromInline public func publicVersioned() {}
22-
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but 'publicVersioned()' is public}}
22+
// expected-error@-1 {{'@usableFromInline' attribute can only be applied to internal or package declarations, but instance method 'publicVersioned()' is public}}
2323
}
2424

2525
fileprivate class filePrivateClass {
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// RUN: %empty-directory(%t/src)
2+
// RUN: split-file %s %t/src
3+
4+
// RUN: %target-build-swift %t/src/Library.swift -swift-version 5 -emit-module -emit-library \
5+
// RUN: -enable-library-evolution \
6+
// RUN: -module-name Library \
7+
// RUN: -o %t/%target-library-name(Library) \
8+
// RUN: -emit-module-interface-path %t/Library.swiftinterface
9+
10+
// RUN: %target-codesign %t/%target-library-name(Library)
11+
12+
// RUN: %target-build-swift -I %t -L %t -l Library %t/src/main.swift %target-rpath(%t) -o %t/main.out
13+
// RUN: %target-codesign %t/main.out
14+
// RUN: %target-run %t/main.out %t/%target-library-name(Library) 2>&1 | %FileCheck %t/src/main.swift
15+
16+
// RUN: rm %t/Library.swiftmodule
17+
18+
// RUN: %target-build-swift -I %t -L %t -l Library %t/src/main.swift %target-rpath(%t) -o %t/main.out
19+
// RUN: %target-codesign %t/main.out
20+
// RUN: %target-run %t/main.out %t/%target-library-name(Library) 2>&1 | %FileCheck %t/src/main.swift
21+
22+
// REQUIRES: executable_test
23+
24+
//--- Library.swift
25+
@frozen
26+
public struct Inlinable {
27+
var _x: Int
28+
29+
public var x: Int {
30+
@usableFromInline
31+
@storageRestrictions(initializes: _x)
32+
init {
33+
self._x = newValue
34+
}
35+
36+
get {
37+
_x
38+
}
39+
}
40+
41+
@inlinable
42+
public init(x: Int) {
43+
self.x = x
44+
}
45+
}
46+
47+
@frozen
48+
public struct Transparent {
49+
@usableFromInline
50+
var _x: Int
51+
52+
public var x: Int {
53+
@_alwaysEmitIntoClient
54+
@storageRestrictions(initializes: _x)
55+
init {
56+
self._x = newValue
57+
}
58+
59+
get {
60+
_x
61+
}
62+
}
63+
64+
@_alwaysEmitIntoClient
65+
public init(x: Int) {
66+
self.x = x
67+
}
68+
}
69+
70+
//--- main.swift
71+
import Library
72+
73+
let inlinable = Inlinable(x: 42)
74+
print("Inlinable.x = \(inlinable.x)")
75+
// CHECK: Inlinable.x = 42
76+
77+
let transparent = Transparent(x: -1)
78+
print("Transparent.x = \(transparent.x)")
79+
// CHECK: Transparent.x = -1
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// RUN: %empty-directory(%t/src)
2+
// RUN: split-file %s %t/src
3+
4+
/// Build the library A
5+
// RUN: %target-swift-frontend -emit-module %t/src/A.swift \
6+
// RUN: -module-name A -swift-version 5 -enable-library-evolution \
7+
// RUN: -emit-module-path %t/A.swiftmodule \
8+
// RUN: -emit-module-interface-path %t/A.swiftinterface
9+
10+
// RUN: %FileCheck %t/src/A.swift < %t/A.swiftinterface
11+
12+
// Build the client using module
13+
// RUN: %target-swift-emit-sil -verify -module-name Client -I %t %t/src/Client.swift | %FileCheck %t/src/Client.swift
14+
15+
// RUN: rm %t/A.swiftmodule
16+
17+
// Re-build the client using interface
18+
// RUN: %target-swift-emit-sil -verify -module-name Client -I %t %t/src/Client.swift | %FileCheck %t/src/Client.swift
19+
20+
// REQUIRES: asserts
21+
22+
//--- A.swift
23+
@frozen
24+
public struct Inlinable {
25+
var _x: Int
26+
27+
// CHECK: public var x: Swift.Int {
28+
// CHECK-NEXT: @usableFromInline
29+
// CHECK-NEXT: @storageRestrictions(initializes: _x) init
30+
// CHECK-NEXT: get
31+
// CHECK-NEXT }
32+
33+
public var x: Int {
34+
@usableFromInline
35+
@storageRestrictions(initializes: _x)
36+
init {
37+
self._x = newValue
38+
}
39+
40+
get {
41+
_x
42+
}
43+
}
44+
45+
@inlinable
46+
public init(x: Int) {
47+
self.x = x
48+
}
49+
}
50+
51+
public struct Internal {
52+
// CHECK: public var y: Swift.Int {
53+
// CHECK-NEXT: get
54+
// CHECK-NEXT: }
55+
56+
public var y: Int {
57+
init {
58+
}
59+
60+
get { 0 }
61+
}
62+
63+
init(y: Int) {
64+
self.y = y
65+
}
66+
}
67+
68+
@frozen
69+
public struct Transparent {
70+
@usableFromInline
71+
var _x: Int
72+
73+
// CHECK: public var x: Swift.Int {
74+
// CHECK-NEXT: @_alwaysEmitIntoClient @storageRestrictions(initializes: _x) init {
75+
// CHECK-NEXT: self._x = newValue
76+
// CHECK-NEXT: }
77+
// CHECK-NEXT: get
78+
// CHECK-NEXT }
79+
80+
public var x: Int {
81+
@_alwaysEmitIntoClient
82+
@storageRestrictions(initializes: _x)
83+
init {
84+
self._x = newValue
85+
}
86+
87+
get {
88+
_x
89+
}
90+
}
91+
92+
@_alwaysEmitIntoClient
93+
public init(x: Int) {
94+
self.x = x
95+
}
96+
}
97+
98+
//--- Client.swift
99+
import A
100+
101+
// CHECK-LABEL: sil hidden @$s6Client15testTransparentyyF : $@convention(thin) () -> ()
102+
// CHECK: [[X:%.*]] = struct $Int (%1 : $Builtin.Int64)
103+
// CHECK-NEXT: // function_ref Transparent.init(x:)
104+
// CHECK-NEXT: [[TRANSPARENT_REF:%.*]] = function_ref @$s1A11TransparentV1xACSi_tcfC : $@convention(method) (Int, @thin Transparent.Type) -> Transparent
105+
// CHECK-NEXT: apply [[TRANSPARENT_REF]]([[X]], %0) : $@convention(method) (Int, @thin Transparent.Type) -> Transparent
106+
func testTransparent() {
107+
_ = Transparent(x: 42)
108+
}
109+
110+
// CHECK-LABEL: sil shared @$s1A11TransparentV1xACSi_tcfC : $@convention(method) (Int, @thin Transparent.Type) -> Transparent
111+
112+
// CHECK-LABEL: sil hidden @$s6Client13testInlinableyyF : $@convention(thin) () -> ()
113+
// CHECK: [[X:%.*]] = struct $Int (%1 : $Builtin.Int64)
114+
// CHECK-NEXT: // function_ref Inlinable.init(x:)
115+
// CHECK-NEXT: [[INLINABLE_REF:%.*]] = function_ref @$s1A9InlinableV1xACSi_tcfC : $@convention(method) (Int, @thin Inlinable.Type) -> Inlinable
116+
// CHECK-NEXT: apply [[INLINABLE_REF]]([[X]], %0) : $@convention(method) (Int, @thin Inlinable.Type) -> Inlinable
117+
func testInlinable() {
118+
_ = Inlinable(x: 42)
119+
}
120+
121+
// CHECK-LABEL: sil @$s1A9InlinableV1xACSi_tcfC : $@convention(method) (Int, @thin Inlinable.Type) -> Inlinable
122+
123+
// CHECK-LABEL: sil shared @$s1A11TransparentV1xSivi : $@convention(thin) (Int, @thin Transparent.Type) -> @out Int

test/SILOptimizer/init_accessors.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ struct TestInit {
1010
var full: (Int, Int)
1111

1212
var point: (Int, Int) {
13-
// CHECK-LABEL: sil private [ossa] @$s14init_accessors8TestInitV5pointSi_Sitvi : $@convention(thin) (Int, Int, @inout Int, @thin TestInit.Type) -> (@out Int, @out (Int, Int))
13+
// CHECK-LABEL: sil hidden [ossa] @$s14init_accessors8TestInitV5pointSi_Sitvi : $@convention(thin) (Int, Int, @inout Int, @thin TestInit.Type) -> (@out Int, @out (Int, Int))
1414
// CHECK: bb0([[Y_REF:%.*]] : $*Int, [[FULL_REF:%.*]] : $*(Int, Int), [[X_VAL:%.*]] : $Int, [[Y_VAL:%.*]] : $Int, [[X_REF:%.*]] : $*Int, [[METATYPE:%.*]] : $@thin TestInit.Type):
1515
//
1616
// CHECK: [[INITIAL_VALUE:%.*]] = tuple ([[X_VAL]] : $Int, [[Y_VAL]] : $Int)
@@ -230,7 +230,7 @@ class TestClass {
230230
var y: (Int, [String])
231231

232232
var data: (Int, (Int, [String])) {
233-
// CHECK-LABEL: sil private [ossa] @$s14init_accessors9TestClassC4dataSi_Si_SaySSGttvi : $@convention(thin) (Int, Int, @owned Array<String>, @thick TestClass.Type) -> (@out Int, @out (Int, Array<String>))
233+
// CHECK-LABEL: sil hidden [ossa] @$s14init_accessors9TestClassC4dataSi_Si_SaySSGttvi : $@convention(thin) (Int, Int, @owned Array<String>, @thick TestClass.Type) -> (@out Int, @out (Int, Array<String>))
234234
// CHECK: bb0([[X_REF:%.*]] : $*Int, [[Y_REF:%.*]] : $*(Int, Array<String>), [[X_VAL:%.*]] : $Int, [[Y_VAL_0:%.*]] : $Int, [[Y_VAL_1:%.*]] : @owned $Array<String>, [[METATYPE:%.*]] : $@thick TestClass.Type):
235235
//
236236
// CHECK: ([[X_VAL:%.*]], [[Y_VAL:%.*]]) = destructure_tuple {{.*}} : $(Int, (Int, Array<String>))
@@ -277,7 +277,7 @@ struct TestGeneric<T, U> {
277277
var b: T
278278
var c: U
279279

280-
// CHECK-LABEL: sil private [ossa] @$s14init_accessors11TestGenericV4datax_xtvi : $@convention(thin) <T, U> (@in T, @in T, @inout U, @thin TestGeneric<T, U>.Type) -> (@out T, @out T)
280+
// CHECK-LABEL: sil hidden [ossa] @$s14init_accessors11TestGenericV4datax_xtvi : $@convention(thin) <T, U> (@in T, @in T, @inout U, @thin TestGeneric<T, U>.Type) -> (@out T, @out T)
281281
//
282282
// CHECK: bb0([[A_REF:%.*]] : $*T, [[B_REF:%.*]] : $*T, [[A_VALUE:%.*]] : $*T, [[B_VALUE:%.*]] : $*T, [[C_REF:%.*]] : $*U, [[METATYPE:%.*]] : $@thin TestGeneric<T, U>.Type):
283283
//
@@ -326,7 +326,7 @@ struct TestGenericTuple<T, U> {
326326
var a: T
327327
var b: (T, U)
328328

329-
// CHECK-LABEL: sil private [ossa] @$s14init_accessors16TestGenericTupleV4datax_x_q_ttvi : $@convention(thin) <T, U> (@in T, @in T, @in U, @thin TestGenericTuple<T, U>.Type) -> (@out T, @out (T, U)) {
329+
// CHECK-LABEL: sil hidden [ossa] @$s14init_accessors16TestGenericTupleV4datax_x_q_ttvi : $@convention(thin) <T, U> (@in T, @in T, @in U, @thin TestGenericTuple<T, U>.Type) -> (@out T, @out (T, U)) {
330330
//
331331
// CHECK: bb0([[A_REF:%.*]] : $*T, [[B_REF:%.*]] : $*(T, U), [[A_VALUE:%.*]] : $*T, [[B_VALUE:%.*]] : $*T, [[C_VALUE:%.*]] : $*U, [[METATYPE:%.*]] : $@thin TestGenericTuple<T, U>.Type):
332332
//

test/attr/attr_alwaysEmitIntoClient.swift

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,31 @@ public func publicFunction() {}
1515
internalFunction() // expected-error {{global function 'internalFunction()' is internal and cannot be referenced from an '@_alwaysEmitIntoClient' function}}
1616
versionedFunction()
1717
publicFunction()
18-
}
18+
}
19+
20+
public struct TestInitAccessors {
21+
var _x: Int
22+
23+
public var x: Int {
24+
@storageRestrictions(initializes: _x)
25+
init { // expected-note 2 {{init acecssor for property 'x' is not '@usableFromInline' or public}}
26+
self._x = newValue
27+
}
28+
29+
get {
30+
self._x
31+
}
32+
33+
set {}
34+
}
35+
36+
@_alwaysEmitIntoClient
37+
public init(x: Int) {
38+
self.x = 0 // expected-error {{init acecssor for property 'x' is internal and cannot be referenced from an '@_alwaysEmitIntoClient' function}}
39+
}
40+
41+
@inlinable
42+
public init() {
43+
self.x = 0 // expected-error {{init acecssor for property 'x' is internal and cannot be referenced from an '@inlinable' function}}
44+
}
45+
}

0 commit comments

Comments
 (0)