Skip to content

Commit 63c2979

Browse files
authored
Merge pull request #78471 from xymus/fix-accessor-is-spi
Sema: Accessors's SPI are tied to the attributes on the storage
2 parents 7c9f47e + aa75341 commit 63c2979

File tree

4 files changed

+209
-50
lines changed

4 files changed

+209
-50
lines changed

lib/AST/Module.cpp

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

3180+
// Accessors get the SPI groups from the PBD.
3181+
if (auto AD = dyn_cast<AccessorDecl>(decl))
3182+
if (auto VD = dyn_cast<VarDecl>(AD->getStorage()))
3183+
if (auto *PBD = VD->getParentPatternBinding()) {
3184+
auto moreGroups = PBD->getSPIGroups();
3185+
spiGroups.insert(moreGroups.begin(), moreGroups.end());
3186+
}
3187+
31803188
// If there is no local SPI information, look at the context.
31813189
if (spiGroups.empty()) {
31823190

lib/Sema/TypeCheckAttr.cpp

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1475,8 +1475,17 @@ void AttributeChecker::visitSPIAccessControlAttr(SPIAccessControlAttr *attr) {
14751475
// VD must be public or open to use an @_spi attribute.
14761476
auto declAccess = VD->getFormalAccess();
14771477
auto DC = VD->getDeclContext()->getAsDecl();
1478-
if (declAccess < AccessLevel::Public &&
1479-
!VD->getAttrs().hasAttribute<UsableFromInlineAttr>() &&
1478+
1479+
AbstractStorageDecl *storage = nullptr;
1480+
if (auto *AD = dyn_cast<AccessorDecl>(VD))
1481+
storage = AD->getStorage();
1482+
1483+
auto canUseAttr = [](ValueDecl *VD) {
1484+
return VD->getFormalAccess() >= AccessLevel::Public ||
1485+
VD->getAttrs().hasAttribute<UsableFromInlineAttr>();
1486+
};
1487+
if (!canUseAttr(VD) &&
1488+
!(storage && canUseAttr(storage)) &&
14801489
!(DC && DC->isSPI())) {
14811490
diagnoseAndRemoveAttr(attr,
14821491
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: 99 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,106 +8,157 @@ 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+
// expected-note@-1 2 {{property declared here}}
18+
}
19+
20+
@_spi(Foo)
21+
public class SPIType {
1222
// expected-note@-1 16{{class declared here}}
1323

1424
public init() {}
1525
}
1626

17-
public struct ResilientStructSPIMembers {
27+
public struct PublicType {
1828
public init() {}
1929

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

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

3175
@frozen public struct FrozenStructSPIMembers {
3276
public init() {}
3377

34-
@_spi(Foo) public func method(_: Bar) {}
35-
@_spi(Foo) public var computedProperty: Bar { Bar() }
78+
@_spi(Foo) public func method(_: SPIType) {}
79+
@_spi(Foo) public var computedProperty: SPIType { SPIType() }
3680

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

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

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

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

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

54-
@_spi(Foo) @Wrapper public var wrappedProperty2 = Bar()
98+
@_spi(Foo) @Wrapper public var wrappedProperty2 = SPIType()
5599
// expected-error@-1 {{stored property 'wrappedProperty2' cannot be declared '@_spi' in a '@frozen' struct}}
100+
101+
@_spi(Foo) @SPIWrapper public var wrappedProperty3 = SPIType()
102+
// expected-error@-1 {{stored property 'wrappedProperty3' cannot be declared '@_spi' in a '@frozen' struct}}
56103
}
57104

58105
@frozen public struct FrozenStructPublicMembers {
59106
public init() {}
60107

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

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

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}}
113+
public var storedProperty2 = SPIType()
114+
// expected-error@-1 {{cannot use class 'SPIType' here; it is SPI}}
115+
// expected-error@-2 {{class 'SPIType' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
69116
// expected-error@-3 {{initializer 'init()' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
70117

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

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

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

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

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}}
127+
@Wrapper public var wrappedProperty2 = SPIType()
128+
// expected-error@-1 {{cannot use class 'SPIType' here; it is SPI}}
129+
// expected-error@-2 {{class 'SPIType' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
83130
// expected-error@-3 {{initializer 'init()' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
131+
132+
@SPIWrapper public var wrappedProperty3: PublicType
133+
// expected-error@-1 {{cannot use generic struct 'SPIWrapper' as property wrapper here; it is SPI}}
134+
// expected-error@-2 {{cannot use property 'wrappedValue' here; it is SPI}}
84135
}
85136

86137
@frozen public struct FrozenStructPrivateMembers {
87138
private init() {}
88139

89-
private func method(_: Bar) {}
140+
private func method(_: SPIType) {}
90141

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

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}}
145+
private var storedProperty2 = SPIType()
146+
// expected-error@-1 {{cannot use class 'SPIType' here; it is SPI}}
147+
// expected-error@-2 {{class 'SPIType' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
97148
// expected-error@-3 {{initializer 'init()' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
98149

99-
private var computedProperty: Bar { Bar() }
150+
private var computedProperty: SPIType { SPIType() }
100151

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

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

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

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}}
159+
@Wrapper private var wrappedProperty2 = SPIType()
160+
// expected-error@-1 {{cannot use class 'SPIType' here; it is SPI}}
161+
// expected-error@-2 {{class 'SPIType' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
111162
// expected-error@-3 {{initializer 'init()' cannot be used in a property initializer in a '@frozen' type because it is SPI}}
112163
}
113164

0 commit comments

Comments
 (0)