Skip to content

Commit 020fb2f

Browse files
authored
Merge pull request #78884 from xymus/fix-accessor-is-spi-6.1
[6.1] Sema: Accessors's SPI are tied to the attributes on the storage
2 parents 48c0689 + ebbd7e9 commit 020fb2f

File tree

4 files changed

+206
-50
lines changed

4 files changed

+206
-50
lines changed

lib/AST/Module.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3154,6 +3154,14 @@ SPIGroupsRequest::evaluate(Evaluator &evaluator, const Decl *decl) const {
31543154
spiGroups.insert(originalSPIs.begin(), originalSPIs.end());
31553155
}
31563156

3157+
// Accessors get the SPI groups from the PBD.
3158+
if (auto AD = dyn_cast<AccessorDecl>(decl))
3159+
if (auto VD = dyn_cast<VarDecl>(AD->getStorage()))
3160+
if (auto *PBD = VD->getParentPatternBinding()) {
3161+
auto moreGroups = PBD->getSPIGroups();
3162+
spiGroups.insert(moreGroups.begin(), moreGroups.end());
3163+
}
3164+
31573165
// If there is no local SPI information, look at the context.
31583166
if (spiGroups.empty()) {
31593167

lib/Sema/TypeCheckAttr.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,8 +1277,17 @@ void AttributeChecker::visitSPIAccessControlAttr(SPIAccessControlAttr *attr) {
12771277
// VD must be public or open to use an @_spi attribute.
12781278
auto declAccess = VD->getFormalAccess();
12791279
auto DC = VD->getDeclContext()->getAsDecl();
1280-
if (declAccess < AccessLevel::Public &&
1281-
!VD->getAttrs().hasAttribute<UsableFromInlineAttr>() &&
1280+
1281+
AbstractStorageDecl *storage = nullptr;
1282+
if (auto *AD = dyn_cast<AccessorDecl>(VD))
1283+
storage = AD->getStorage();
1284+
1285+
auto canUseAttr = [](ValueDecl *VD) {
1286+
return VD->getFormalAccess() >= AccessLevel::Public ||
1287+
VD->getAttrs().hasAttribute<UsableFromInlineAttr>();
1288+
};
1289+
if (!canUseAttr(VD) &&
1290+
!(storage && canUseAttr(storage)) &&
12821291
!(DC && DC->isSPI())) {
12831292
diagnoseAndRemoveAttr(attr,
12841293
diag::spi_attribute_on_non_public,

test/SPI/spi_internal_accessor.swift

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-swift-frontend -emit-module %s -module-name main \
3+
// RUN: -swift-version 6 -enable-library-evolution \
4+
// RUN: -emit-module-interface-path %t/main.swiftinterface \
5+
// RUN: -emit-private-module-interface-path %t/main.private.swiftinterface
6+
7+
// RUN: %FileCheck %s -check-prefix CHECK-PUBLIC --input-file %t/main.swiftinterface
8+
// CHECK-PUBLIC-NOT: @_spi
9+
10+
// RUN: %FileCheck %s -check-prefix CHECK-PRIVATE --input-file %t/main.private.swiftinterface
11+
12+
// RUN: %target-swift-typecheck-module-from-interface(%t/main.swiftinterface) -module-name main
13+
// RUN: %target-swift-typecheck-module-from-interface(%t/main.private.swiftinterface) -module-name main
14+
15+
public struct S {
16+
@usableFromInline @_spi(X)
17+
internal var v: Int {
18+
get { return 42 }
19+
}
20+
}
21+
22+
extension UnsafeMutablePointer {
23+
@_spi(X) @available(swift, obsoleted: 1)
24+
// CHECK-PRIVATE: @_spi(X) @available(swift, obsoleted: 1)
25+
@usableFromInline
26+
// CHECK-PRIVATE: @usableFromInline
27+
internal var pointee: Pointee {
28+
// CHECK-PRIVATE: internal var pointee: Pointee {
29+
@_transparent unsafeAddress {
30+
// CHECK-PRIVATE: @_spi(X) @_transparent unsafeAddress {
31+
return UnsafePointer(self)
32+
// CHECK-PRIVATE: return UnsafePointer(self)
33+
}
34+
// CHECK-PRIVATE: }
35+
@_transparent nonmutating unsafeMutableAddress {
36+
// CHECK-PRIVATE: @_transparent nonmutating unsafeMutableAddress {
37+
return self
38+
// CHECK-PRIVATE: return self
39+
}
40+
// CHECK-PRIVATE: }
41+
}
42+
// CHECK-PRIVATE: }
43+
}
44+
45+
extension UnsafeMutablePointer {
46+
@_spi(X)
47+
// CHECK-PRIVATE: @_spi(X)
48+
public var pointee2: Pointee {
49+
// CHECK-PRIVATE: public var pointee2: Pointee {
50+
unsafeAddress {
51+
// CHECK-PRIVATE: unsafeAddress
52+
return UnsafePointer(self)
53+
}
54+
@_transparent nonmutating unsafeMutableAddress {
55+
// CHECK-PRIVATE: @_transparent nonmutating unsafeMutableAddress {
56+
return self
57+
// CHECK-PRIVATE: return self
58+
}
59+
// CHECK-PRIVATE: }
60+
}
61+
// CHECK-PRIVATE: }
62+
}
63+
64+
65+
@_spi(Foo) @propertyWrapper public struct SPIWrapper<T> {
66+
// CHECK-PRIVATE: @_spi(Foo) @propertyWrapper public struct SPIWrapper<T> {
67+
public init(wrappedValue: T) {}
68+
// CHECK-PRIVATE: @_spi(Foo) public init(wrappedValue: T)
69+
public var wrappedValue: T { fatalError() }
70+
// CHECK-PRIVATE: @_spi(Foo) public var wrappedValue: T {
71+
// CHECK-PRIVATE: @_spi(Foo) get
72+
// CHECK-PRIVATE: }
73+
// CHECK-PRIVATE: }
74+
}
75+
76+
public struct InternalSet {
77+
// CHECK-PRIVATE: public struct InternalSet {
78+
@_spi(X) public internal(set) var long: Int {
79+
get { 0 }
80+
set { }
81+
}
82+
// CHECK-PRIVATE: @_spi(X) public var long: Swift.Int {
83+
// CHECK-PRIVATE: @_spi(X) get
84+
// CHECK-PRIVATE: }
85+
86+
@_spi(X) public internal(set) var short: Int
87+
// CHECK-PRIVATE: @_spi(X) public var short: Swift.Int {
88+
// CHECK-PRIVATE: get
89+
// CHECK-PRIVATE: }
90+
}
91+
// CHECK-PRIVATE: }

test/SPI/spi_members.swift

Lines changed: 96 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,106 +8,154 @@ public struct Wrapper<T> {
88
}
99

1010
@_spi(Foo)
11-
public class Bar {
11+
@propertyWrapper
12+
public struct SPIWrapper<T> {
13+
// expected-note@-1 2 {{generic struct declared here}}
14+
public init(wrappedValue: T) {}
15+
16+
public var wrappedValue: T { fatalError() }
17+
}
18+
19+
@_spi(Foo)
20+
public class SPIType {
1221
// expected-note@-1 16{{class declared here}}
1322

1423
public init() {}
1524
}
1625

17-
public struct ResilientStructSPIMembers {
26+
public struct PublicType {
1827
public init() {}
1928

20-
@_spi(Foo) public func method(_: Bar) {}
21-
@_spi(Foo) public var computedProperty: Bar { Bar() }
29+
@_spi(Foo) public func spiFunc() {}
30+
}
2231

23-
@_spi(Foo) public var storedProperty1: Bar
24-
@_spi(Foo) public var storedProperty2 = Bar()
25-
@_spi(Foo) public lazy var lazyProperty1 = Bar()
26-
@_spi(Foo) public lazy var lazyProperty2: Bar = Bar()
27-
@_spi(Foo) @Wrapper public var wrappedProperty1: Bar
28-
@_spi(Foo) @Wrapper public var wrappedProperty2 = Bar()
32+
public struct ResilientStructSPIMembers {
33+
public init() {}
34+
35+
@_spi(Foo) public func method(_: SPIType) {}
36+
@_spi(Foo) public var computedProperty: SPIType { SPIType() }
37+
38+
@_spi(Foo) public var storedProperty1: SPIType
39+
@_spi(Foo) public var storedProperty2 = SPIType()
40+
@_spi(Foo) public lazy var lazyProperty1 = SPIType()
41+
@_spi(Foo) public lazy var lazyProperty2: SPIType = SPIType()
42+
@_spi(Foo) @Wrapper public var wrappedProperty1: SPIType
43+
@_spi(Foo) @Wrapper public var wrappedProperty2 = SPIType()
44+
@_spi(Foo) @SPIWrapper public var wrappedProperty3 = SPIType()
45+
46+
@SPIWrapper public var wrappedProperty4: PublicType
47+
// expected-error@-1 {{cannot use generic struct 'SPIWrapper' as property wrapper here; it is SPI}}
48+
49+
@_spi(Foo) public var inlinableGet: Int {
50+
@inlinable
51+
get {
52+
let _ = SPIType()
53+
let t = PublicType()
54+
t.spiFunc()
55+
return 42
56+
}
57+
}
58+
59+
public var inlinablePublicGet: Int {
60+
@inlinable
61+
get {
62+
let _ = SPIType()
63+
// expected-error@-1 {{class 'SPIType' cannot be used in an '@inlinable' function because it is SPI}}
64+
// expected-error@-2 {{initializer 'init()' cannot be used in an '@inlinable' function because it is SPI}}
65+
let t = PublicType()
66+
t.spiFunc()
67+
// expected-error@-1 {{instance method 'spiFunc()' cannot be used in an '@inlinable' function because it is SPI}}
68+
return 42
69+
}
70+
}
2971
}
3072

3173
@frozen public struct FrozenStructSPIMembers {
3274
public init() {}
3375

34-
@_spi(Foo) public func method(_: Bar) {}
35-
@_spi(Foo) public var computedProperty: Bar { Bar() }
76+
@_spi(Foo) public func method(_: SPIType) {}
77+
@_spi(Foo) public var computedProperty: SPIType { SPIType() }
3678

37-
@_spi(Foo) public var storedProperty1: Bar
38-
// expected-error@-1 {{cannot use class 'Bar' here; it is SPI}}
79+
@_spi(Foo) public var storedProperty1: SPIType
80+
// expected-error@-1 {{cannot use class 'SPIType' here; it is SPI}}
3981
// expected-error@-2 {{stored property 'storedProperty1' cannot be declared '@_spi' in a '@frozen' struct}}
4082

41-
@_spi(Foo) public var storedProperty2 = Bar()
83+
@_spi(Foo) public var storedProperty2 = SPIType()
4284
// expected-error@-1 {{stored property 'storedProperty2' cannot be declared '@_spi' in a '@frozen' struct}}
4385

44-
@_spi(Foo) public lazy var lazyProperty1 = Bar()
86+
@_spi(Foo) public lazy var lazyProperty1 = SPIType()
4587
// expected-error@-1 {{stored property 'lazyProperty1' cannot be declared '@_spi' in a '@frozen' struct}}
4688

47-
@_spi(Foo) public lazy var lazyProperty2: Bar = Bar()
48-
// expected-error@-1 {{cannot use class 'Bar' here; it is SPI}}
89+
@_spi(Foo) public lazy var lazyProperty2: SPIType = SPIType()
90+
// expected-error@-1 {{cannot use class 'SPIType' here; it is SPI}}
4991
// expected-error@-2 {{stored property 'lazyProperty2' cannot be declared '@_spi' in a '@frozen' struct}}
5092

51-
@_spi(Foo) @Wrapper public var wrappedProperty1: Bar
93+
@_spi(Foo) @Wrapper public var wrappedProperty1: SPIType
5294
// expected-error@-1 {{stored property 'wrappedProperty1' cannot be declared '@_spi' in a '@frozen' struct}}
5395

54-
@_spi(Foo) @Wrapper public var wrappedProperty2 = Bar()
96+
@_spi(Foo) @Wrapper public var wrappedProperty2 = SPIType()
5597
// expected-error@-1 {{stored property 'wrappedProperty2' cannot be declared '@_spi' in a '@frozen' struct}}
98+
99+
@_spi(Foo) @SPIWrapper public var wrappedProperty3 = SPIType()
100+
// expected-error@-1 {{stored property 'wrappedProperty3' cannot be declared '@_spi' in a '@frozen' struct}}
56101
}
57102

58103
@frozen public struct FrozenStructPublicMembers {
59104
public init() {}
60105

61-
public func method(_: Bar) {} // expected-error {{cannot use class 'Bar' here; it is SPI}}
106+
public func method(_: SPIType) {} // expected-error {{cannot use class 'SPIType' here; it is SPI}}
62107

63-
public var storedProperty1: Bar
64-
// expected-error@-1 {{cannot use class 'Bar' here; it is SPI}}
108+
public var storedProperty1: SPIType
109+
// expected-error@-1 {{cannot use class 'SPIType' here; it is SPI}}
65110

66-
public var storedProperty2 = Bar()
67-
// expected-error@-1 {{cannot use class 'Bar' here; it is SPI}}
68-
// expected-error@-2 {{class 'Bar' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
111+
public var storedProperty2 = SPIType()
112+
// expected-error@-1 {{cannot use class 'SPIType' here; it is SPI}}
113+
// expected-error@-2 {{class 'SPIType' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
69114
// expected-error@-3 {{initializer 'init()' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
70115

71-
public var computedProperty: Bar { Bar() } // expected-error {{cannot use class 'Bar' here; it is SPI}}
116+
public var computedProperty: SPIType { SPIType() } // expected-error {{cannot use class 'SPIType' here; it is SPI}}
72117

73-
public lazy var lazyProperty1 = Bar() // expected-error {{cannot use class 'Bar' here; it is SPI}}
118+
public lazy var lazyProperty1 = SPIType() // expected-error {{cannot use class 'SPIType' here; it is SPI}}
74119

75-
public lazy var lazyProperty2: Bar = Bar() // expected-error {{cannot use class 'Bar' here; it is SPI}}
120+
public lazy var lazyProperty2: SPIType = SPIType() // expected-error {{cannot use class 'SPIType' here; it is SPI}}
76121

77-
@Wrapper public var wrappedProperty1: Bar
78-
// expected-error@-1 {{cannot use class 'Bar' here; it is SPI}}
122+
@Wrapper public var wrappedProperty1: SPIType
123+
// expected-error@-1 {{cannot use class 'SPIType' here; it is SPI}}
79124

80-
@Wrapper public var wrappedProperty2 = Bar()
81-
// expected-error@-1 {{cannot use class 'Bar' here; it is SPI}}
82-
// expected-error@-2 {{class 'Bar' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
125+
@Wrapper public var wrappedProperty2 = SPIType()
126+
// expected-error@-1 {{cannot use class 'SPIType' here; it is SPI}}
127+
// expected-error@-2 {{class 'SPIType' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
83128
// expected-error@-3 {{initializer 'init()' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
129+
130+
@SPIWrapper public var wrappedProperty3: PublicType
131+
// expected-error@-1 {{cannot use generic struct 'SPIWrapper' as property wrapper here; it is SPI}}
84132
}
85133

86134
@frozen public struct FrozenStructPrivateMembers {
87135
private init() {}
88136

89-
private func method(_: Bar) {}
137+
private func method(_: SPIType) {}
90138

91-
private var storedProperty1: Bar
92-
// expected-error@-1 {{cannot use class 'Bar' here; it is SPI}}
139+
private var storedProperty1: SPIType
140+
// expected-error@-1 {{cannot use class 'SPIType' here; it is SPI}}
93141

94-
private var storedProperty2 = Bar()
95-
// expected-error@-1 {{cannot use class 'Bar' here; it is SPI}}
96-
// expected-error@-2 {{class 'Bar' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
142+
private var storedProperty2 = SPIType()
143+
// expected-error@-1 {{cannot use class 'SPIType' here; it is SPI}}
144+
// expected-error@-2 {{class 'SPIType' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
97145
// expected-error@-3 {{initializer 'init()' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
98146

99-
private var computedProperty: Bar { Bar() }
147+
private var computedProperty: SPIType { SPIType() }
100148

101-
private lazy var lazyProperty1 = Bar() // expected-error {{cannot use class 'Bar' here; it is SPI}}
149+
private lazy var lazyProperty1 = SPIType() // expected-error {{cannot use class 'SPIType' here; it is SPI}}
102150

103-
private lazy var lazyProperty2: Bar = Bar() // expected-error {{cannot use class 'Bar' here; it is SPI}}
151+
private lazy var lazyProperty2: SPIType = SPIType() // expected-error {{cannot use class 'SPIType' here; it is SPI}}
104152

105-
@Wrapper private var wrappedProperty1: Bar
106-
// expected-error@-1 {{cannot use class 'Bar' here; it is SPI}}
153+
@Wrapper private var wrappedProperty1: SPIType
154+
// expected-error@-1 {{cannot use class 'SPIType' here; it is SPI}}
107155

108-
@Wrapper private var wrappedProperty2 = Bar()
109-
// expected-error@-1 {{cannot use class 'Bar' here; it is SPI}}
110-
// expected-error@-2 {{class 'Bar' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
156+
@Wrapper private var wrappedProperty2 = SPIType()
157+
// expected-error@-1 {{cannot use class 'SPIType' here; it is SPI}}
158+
// expected-error@-2 {{class 'SPIType' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
111159
// expected-error@-3 {{initializer 'init()' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
112160
}
113161

0 commit comments

Comments
 (0)