Skip to content

Commit 7e6e8ed

Browse files
committed
Sema: Fully check the availability of wrappedValue.
Call `checkDeclarationAvailability()`, instead of just diagnosing unavailability.
1 parent 4069518 commit 7e6e8ed

11 files changed

+95
-25
lines changed

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2903,7 +2903,7 @@ void swift::diagnoseOverrideOfUnavailableDecl(ValueDecl *override,
29032903

29042904
/// Emit a diagnostic for references to declarations that have been
29052905
/// marked as unavailable, either through "unavailable" or "obsoleted:".
2906-
bool swift::diagnoseExplicitUnavailability(const ValueDecl *D, SourceRange R,
2906+
static bool diagnoseExplicitUnavailability(const ValueDecl *D, SourceRange R,
29072907
const ExportContext &Where,
29082908
const Expr *call,
29092909
DeclAvailabilityFlags Flags) {
@@ -4091,8 +4091,6 @@ bool swift::diagnoseDeclAvailability(const ValueDecl *D, SourceRange R,
40914091
const Expr *call,
40924092
const ExportContext &Where,
40934093
DeclAvailabilityFlags Flags) {
4094-
assert(!Where.isImplicit());
4095-
40964094
// Generic parameters are always available.
40974095
if (isa<GenericTypeParamDecl>(D))
40984096
return false;

lib/Sema/TypeCheckAvailability.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -311,13 +311,6 @@ void diagnoseOverrideOfUnavailableDecl(ValueDecl *override,
311311
const ValueDecl *base,
312312
const AvailableAttr *attr);
313313

314-
/// Emit a diagnostic for references to declarations that have been
315-
/// marked as unavailable, either through "unavailable" or "obsoleted:".
316-
bool diagnoseExplicitUnavailability(const ValueDecl *D, SourceRange R,
317-
const ExportContext &Where,
318-
const Expr *call,
319-
DeclAvailabilityFlags Flags = std::nullopt);
320-
321314
/// Checks whether a declaration should be considered unavailable when referred
322315
/// to in the given declaration context and availability context and, if so,
323316
/// returns a result that describes the unmet availability requirements.

lib/Sema/TypeCheckStorage.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1202,13 +1202,10 @@ static Expr *buildStorageReference(AccessorDecl *accessor,
12021202
// Check for availability of wrappedValue.
12031203
if (accessor->getAccessorKind() == AccessorKind::Get ||
12041204
isYieldingDefaultNonmutatingAccessor(accessor->getAccessorKind())) {
1205-
if (wrappedValue->getAttrs().getUnavailable(ctx)) {
1206-
ExportContext where = ExportContext::forDeclSignature(var);
1207-
diagnoseExplicitUnavailability(
1208-
wrappedValue,
1209-
var->getAttachedPropertyWrappers()[i]->getRangeWithAt(),
1210-
where, nullptr);
1211-
}
1205+
diagnoseDeclAvailability(
1206+
wrappedValue,
1207+
var->getAttachedPropertyWrappers()[i]->getRangeWithAt(), nullptr,
1208+
ExportContext::forDeclSignature(accessor));
12121209
}
12131210

12141211
underlyingVars.push_back({ wrappedValue, isWrapperRefLValue });

test/SPI/spi-only-import-exportability.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ public func implementationDetailsUser() {
150150
public struct ClientStruct {
151151
#if !SKIP_ERRORS
152152
public var a: SPIOnlyStruct // expected-error {{cannot use struct 'SPIOnlyStruct' here; 'SPIOnlyImportedLib' was imported for SPI only}}
153+
// expected-error@+1 {{cannot use property 'wrappedValue' here; 'SPIOnlyImportedLib' was imported for SPI only}}
153154
@SPIOnlyPropertyWrapper(42) public var aWrapped: Any // expected-error {{cannot use generic struct 'SPIOnlyPropertyWrapper' as property wrapper here; 'SPIOnlyImportedLib' was imported for SPI only}}
154155
#endif
155156
@PublicPropertyWrapper(SPIOnlyStruct()) public var bWrapped: Any

test/Sema/access-level-import-inlinable.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ fileprivate import FileprivateLib
8888
// expected-note@-1 2 {{generic struct 'FileprivateImportWrapper' imported as 'fileprivate' from 'FileprivateLib' here}}
8989
// expected-note@-2 2 {{initializer 'init(wrappedValue:)' imported as 'fileprivate' from 'FileprivateLib' here}}
9090
// expected-note@-3 2 {{protocol 'FileprivateImportProto' imported as 'fileprivate' from 'FileprivateLib' here}}
91+
// expected-note@-4 2 {{property 'wrappedValue' imported as 'fileprivate' from 'FileprivateLib' here}}
9192

9293
private import PrivateLib
9394
// expected-note@-1 10 {{struct 'PrivateImportType' imported as 'private' from 'PrivateLib' here}}
@@ -128,6 +129,7 @@ public struct GenericType<T, U> {}
128129

129130
@FileprivateImportWrapper // expected-error {{initializer 'init(wrappedValue:)' is fileprivate and cannot be referenced from an '@inlinable' function}}
130131
// expected-error @-1 {{generic struct 'FileprivateImportWrapper' is fileprivate and cannot be referenced from an '@inlinable' function}}
132+
// expected-error @-2 {{property 'wrappedValue' is fileprivate and cannot be referenced from an '@inlinable' function}}
131133
var wrappedFileprivate: PublicImportType
132134

133135
let _: GenericType<PublicImportType, PublicImportType>
@@ -168,6 +170,7 @@ public struct GenericType<T, U> {}
168170

169171
@FileprivateImportWrapper // expected-error {{initializer 'init(wrappedValue:)' is fileprivate and cannot be referenced from an '@_alwaysEmitIntoClient' function}}
170172
// expected-error @-1 {{generic struct 'FileprivateImportWrapper' is fileprivate and cannot be referenced from an '@_alwaysEmitIntoClient' function}}
173+
// expected-error @-2 {{property 'wrappedValue' is fileprivate and cannot be referenced from an '@_alwaysEmitIntoClient' function}}
171174
var wrappedFileprivate: PublicImportType
172175

173176
let _: GenericType<PublicImportType, PublicImportType>

test/Sema/implementation-only-import-in-decls.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public struct TestInit {
5656

5757
public struct TestPropertyWrapper {
5858
@BadWrapper public var BadProperty: Int // expected-error {{cannot use struct 'BadWrapper' as property wrapper here; 'BADLibrary' has been imported as implementation-only}}
59+
// expected-error@-1 {{cannot use property 'wrappedValue' here; 'BADLibrary' has been imported as implementation-only}}
5960
}
6061

6162
public protocol TestInherited: BadProto {} // expected-error {{cannot use protocol 'BadProto' here; 'BADLibrary' has been imported as implementation-only}}

test/Sema/missing-import-typealias.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@ public class InheritsFromClazzAlias: ClazzAlias {}
8181
public func takesGeneric<T: ProtoAlias>(_ t: T) {}
8282

8383
public struct HasMembers {
84+
// expected-warning@+3 {{cannot use property 'wrappedValue' here; 'Original' was not imported by this file}}
8485
// expected-warning@+2 {{'WrapperAlias' aliases 'Original.Wrapper' and cannot be used as property wrapper here because 'Original' was not imported by this file; this is an error in the Swift 6 language mode}}
8586
// expected-note@+1 {{The missing import of module 'Original' will be added implicitly}}
8687
@WrapperAlias public var wrapped: Int

test/Sema/property_wrapper_availability.swift

Lines changed: 66 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,33 @@ struct Available51Wrapper<T> {
1717

1818
@available(*, unavailable)
1919
@propertyWrapper
20-
struct UnavailableWrapper<T> { // expected-note 6 {{'UnavailableWrapper' has been explicitly marked unavailable here}}
20+
struct UnavailableWrapper<T> { // expected-note 8 {{'UnavailableWrapper' has been explicitly marked unavailable here}}
2121
var wrappedValue: T
2222
}
2323

24+
@propertyWrapper
25+
struct WrappedValueUnavailableOnMacOS<T> {
26+
init(wrappedValue: T) { fatalError() }
27+
28+
@available(macOS, unavailable)
29+
var wrappedValue: T { // expected-note 6 {{'wrappedValue' has been explicitly marked unavailable here}}
30+
get { fatalError() }
31+
set { fatalError() }
32+
}
33+
}
34+
35+
@propertyWrapper
36+
struct WrappedValueAvailable51<T> {
37+
init(wrappedValue: T) { fatalError() }
38+
39+
@available(macOS 51, *)
40+
var wrappedValue: T {
41+
get { fatalError() }
42+
set { fatalError() }
43+
}
44+
}
2445

25-
struct AlwaysAvailableStruct { // expected-note 2 {{add @available attribute to enclosing struct}}
46+
struct AlwaysAvailableStruct { // expected-note 3 {{add @available attribute to enclosing struct}}
2647
@AlwaysAvailableWrapper var alwaysAvailableExplicit: S
2748
@AlwaysAvailableWrapper var alwaysAvailableInferred = S()
2849

@@ -31,6 +52,9 @@ struct AlwaysAvailableStruct { // expected-note 2 {{add @available attribute to
3152

3253
@UnavailableWrapper var unavailableExplicit: S // expected-error {{'UnavailableWrapper' is unavailable}}
3354
@UnavailableWrapper var unavailableInferred = S() // expected-error {{'UnavailableWrapper' is unavailable}}
55+
56+
@WrappedValueUnavailableOnMacOS var unavailableWrappedValue: S // expected-error {{'wrappedValue' is unavailable in macOS}}
57+
@WrappedValueAvailable51 var wrappedValueAavailable51: S // expected-error {{'wrappedValue' is only available in macOS 51 or newer}}
3458
}
3559

3660
@available(macOS 51, *)
@@ -43,6 +67,9 @@ struct Available51Struct {
4367

4468
@UnavailableWrapper var unavailableExplicit: S // expected-error {{'UnavailableWrapper' is unavailable}}
4569
@UnavailableWrapper var unavailableInferred = S() // expected-error {{'UnavailableWrapper' is unavailable}}
70+
71+
@WrappedValueUnavailableOnMacOS var unavailableWrappedValue: S // expected-error {{'wrappedValue' is unavailable in macOS}}
72+
@WrappedValueAvailable51 var wrappedValueAavailable51: S
4673
}
4774

4875
@available(*, unavailable)
@@ -55,24 +82,57 @@ struct UnavailableStruct {
5582

5683
@UnavailableWrapper var unavailableExplicit: S
5784
@UnavailableWrapper var unavailableInferred = S()
85+
86+
@WrappedValueUnavailableOnMacOS var unavailableWrappedValue: S // expected-error {{'wrappedValue' is unavailable in macOS}}
87+
@WrappedValueAvailable51 var wrappedValueAavailable51: S // expected-error {{'wrappedValue' is only available in macOS 51 or newer}}
5888
}
5989

60-
func alwaysAvailableFunc( // expected-note {{add @available attribute to enclosing global function}}
90+
@available(macOS, unavailable)
91+
struct UnavailableOnMacOSStruct {
92+
@AlwaysAvailableWrapper var alwaysAvailableExplicit: S
93+
@AlwaysAvailableWrapper var alwaysAvailableInferred = S()
94+
95+
@Available51Wrapper var available51Explicit: S // expected-error {{'Available51Wrapper' is only available in macOS 51 or newer}}
96+
@Available51Wrapper var available51Inferred = S() // expected-error {{'Available51Wrapper' is only available in macOS 51 or newer}}
97+
98+
@UnavailableWrapper var unavailableExplicit: S // expected-error {{'UnavailableWrapper' is unavailable}}
99+
@UnavailableWrapper var unavailableInferred = S() // expected-error {{'UnavailableWrapper' is unavailable}}
100+
101+
@WrappedValueUnavailableOnMacOS var unavailableWrappedValue: S
102+
@WrappedValueAvailable51 var wrappedValueAavailable51: S // expected-error {{'wrappedValue' is only available in macOS 51 or newer}}
103+
}
104+
105+
func alwaysAvailableFunc( // expected-note 2 {{add @available attribute to enclosing global function}}
61106
@AlwaysAvailableWrapper _ alwaysAvailable: S,
62107
@Available51Wrapper _ available51: S, // expected-error {{'Available51Wrapper' is only available in macOS 51 or newer}}
63-
@UnavailableWrapper _ unavailable: S // expected-error {{'UnavailableWrapper' is unavailable}}
108+
@UnavailableWrapper _ unavailable: S, // expected-error {{'UnavailableWrapper' is unavailable}}
109+
@WrappedValueUnavailableOnMacOS _ unavailableWrappedValue: S, // expected-error {{'wrappedValue' is unavailable in macOS}}
110+
@WrappedValueAvailable51 _ wrappedValueAavailable51: S // expected-error {{'wrappedValue' is only available in macOS 51 or newer}}
64111
) {}
65112

66113
@available(macOS 51, *)
67114
func available51Func(
68115
@AlwaysAvailableWrapper _ alwaysAvailable: S,
69116
@Available51Wrapper _ available51: S,
70-
@UnavailableWrapper _ unavailable: S // expected-error {{'UnavailableWrapper' is unavailable}}
117+
@UnavailableWrapper _ unavailable: S, // expected-error {{'UnavailableWrapper' is unavailable}}
118+
@WrappedValueUnavailableOnMacOS _ unavailableWrappedValue: S, // expected-error {{'wrappedValue' is unavailable in macOS}}
119+
@WrappedValueAvailable51 _ wrappedValueAavailable51: S
71120
) {}
72121

73122
@available(*, unavailable)
74123
func unavailableFunc(
75124
@AlwaysAvailableWrapper _ alwaysAvailable: S,
76125
@Available51Wrapper _ available51: S,
77-
@UnavailableWrapper _ unavailable: S
126+
@UnavailableWrapper _ unavailable: S,
127+
@WrappedValueUnavailableOnMacOS _ unavailableWrappedValue: S, // expected-error {{'wrappedValue' is unavailable in macOS}}
128+
@WrappedValueAvailable51 _ wrappedValueAavailable51: S // expected-error {{'wrappedValue' is only available in macOS 51 or newer}}
129+
) {}
130+
131+
@available(macOS, unavailable)
132+
func unavailableOnMacOSFunc(
133+
@AlwaysAvailableWrapper _ alwaysAvailable: S,
134+
@Available51Wrapper _ available51: S,
135+
@UnavailableWrapper _ unavailable: S,
136+
@WrappedValueUnavailableOnMacOS _ unavailableWrappedValue: S,
137+
@WrappedValueAvailable51 _ wrappedValueAavailable51: S // expected-error {{'wrappedValue' is only available in macOS 51 or newer}}
78138
) {}

test/Sema/property_wrapper_parameter_invalid.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ struct Wrapper<T> { // expected-note 3 {{type declared here}}
7777
self.wrappedValue = projectedValue.value
7878
}
7979

80+
// expected-note@+1 {{property 'wrappedValue' is not '@usableFromInline' or public}}
8081
var wrappedValue: T
8182
var projectedValue: Projection<T> { Projection(value: wrappedValue) }
8283
}
@@ -127,6 +128,7 @@ enum E {
127128
// expected-error@+1 {{function cannot be declared public because its parameter uses an internal API wrapper type}}
128129
public func f1(@Wrapper value: Int) {}
129130

131+
// expected-error@+4 {{property 'wrappedValue' is internal and cannot be referenced from an '@inlinable' function}}
130132
// expected-error@+3 {{generic struct 'Wrapper' is internal and cannot be referenced from an '@inlinable' function}}
131133
// expected-error@+2 {{the parameter API wrapper of a '@usableFromInline' function must be '@usableFromInline' or public}}
132134
// expected-error@+1 {{initializer 'init(wrappedValue:)' is internal and cannot be referenced from an '@inlinable' function}}
@@ -155,6 +157,7 @@ public struct PublicWrapper<T> {
155157
// expected-note@+2 2 {{generic struct 'PackageWrapper' is not '@usableFromInline' or public}}
156158
@propertyWrapper
157159
package struct PackageWrapper<T> { // expected-note 3 {{type declared here}}
160+
// expected-note@+1 2 {{property 'wrappedValue' is not '@usableFromInline' or public}}
158161
package var wrappedValue: T
159162

160163
// expected-note@+1 2 {{initializer 'init(wrappedValue:)' is not '@usableFromInline' or public}}
@@ -164,6 +167,7 @@ package struct PackageWrapper<T> { // expected-note 3 {{type declared here}}
164167
// expected-note@+2 2 {{generic struct 'InternalWrapper' is not '@usableFromInline' or public}}
165168
@propertyWrapper
166169
struct InternalWrapper<T> { // expected-note 3 {{type declared here}}
170+
// expected-note@+1 2 {{property 'wrappedValue' is not '@usableFromInline' or public}}
167171
var wrappedValue: T
168172

169173
// expected-note@+1 2 {{initializer 'init(wrappedValue:)' is not '@usableFromInline' or public}}
@@ -200,20 +204,24 @@ public func testComposition2pkg(@PackageWrapper @PublicWrapper value: Int) {}
200204
// Okay because `PackageWrapper` is implementation-detail.
201205
@usableFromInline func testComposition4pkg(@PackageWrapper @PublicWrapper value: Int) {}
202206

207+
// expected-error@+4 {{property 'wrappedValue' is internal and cannot be referenced from an '@inlinable' function}}
203208
// expected-error@+3 {{generic struct 'InternalWrapper' is internal and cannot be referenced from an '@inlinable' function}}
204209
// expected-error@+2 {{the parameter API wrapper of a '@usableFromInline' function must be '@usableFromInline' or public}}
205210
// expected-error@+1 {{initializer 'init(wrappedValue:)' is internal and cannot be referenced from an '@inlinable' function}}
206211
@inlinable func testComposition5(@PublicWrapper @InternalWrapper value: Int) {}
207212

213+
// expected-error@+3 {{property 'wrappedValue' is internal and cannot be referenced from an '@inlinable' function}}
208214
// expected-error@+2 {{generic struct 'InternalWrapper' is internal and cannot be referenced from an '@inlinable' function}}
209215
// expected-error@+1 {{initializer 'init(wrappedValue:)' is internal and cannot be referenced from an '@inlinable' function}}
210216
@inlinable func testComposition6(@InternalWrapper @PublicWrapper value: Int) {}
211217

218+
// expected-error@+4 {{property 'wrappedValue' is package and cannot be referenced from an '@inlinable' function}}
212219
// expected-error@+3 {{generic struct 'PackageWrapper' is package and cannot be referenced from an '@inlinable' function}}
213220
// expected-error@+2 {{the parameter API wrapper of a '@usableFromInline' function must be '@usableFromInline' or public}}
214221
// expected-error@+1 {{initializer 'init(wrappedValue:)' is package and cannot be referenced from an '@inlinable' function}}
215222
@inlinable func testComposition5pkg(@PublicWrapper @PackageWrapper value: Int) {}
216223

224+
// expected-error@+3 {{property 'wrappedValue' is package and cannot be referenced from an '@inlinable' function}}
217225
// expected-error@+2 {{generic struct 'PackageWrapper' is package and cannot be referenced from an '@inlinable' function}}
218226
// expected-error@+1 {{initializer 'init(wrappedValue:)' is package and cannot be referenced from an '@inlinable' function}}
219227
@inlinable func testComposition6pkg(@PackageWrapper @PublicWrapper value: Int) {}

test/Sema/spi-in-decls.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ public struct IntLike: ExpressibleByIntegerLiteral, Equatable { // expected-note
3636
@_spi(X)
3737
@propertyWrapper
3838
public struct BadWrapper { // expected-note {{type declared here}}
39-
public var wrappedValue: Int
39+
public var wrappedValue: Int // expected-note {{type declared here}}
4040
public init(wrappedValue: Int) {
4141
self.wrappedValue = wrappedValue
4242
}
@@ -87,6 +87,7 @@ public struct TestInit {
8787

8888
public struct TestPropertyWrapper {
8989
@BadWrapper public var BadProperty: Int // expected-error {{cannot use struct 'BadWrapper' as property wrapper here; it is SPI}}
90+
// expected-error@-1 {{cannot use property 'wrappedValue' here; it is SPI}}
9091
}
9192

9293
public protocol TestInherited: BadProto {} // expected-error {{cannot use protocol 'BadProto' here; it is SPI}}

test/decl/var/property_wrappers.swift

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -961,7 +961,7 @@ struct Observable<Value> {
961961
}
962962

963963
@available(*, unavailable, message: "must be in a class")
964-
var wrappedValue: Value { // expected-note{{'wrappedValue' has been explicitly marked unavailable here}}
964+
var wrappedValue: Value { // expected-note 2{{'wrappedValue' has been explicitly marked unavailable here}}
965965
get { fatalError("called wrappedValue getter") }
966966
set { fatalError("called wrappedValue setter") }
967967
}
@@ -985,6 +985,13 @@ struct MyObservedValueType {
985985
var observedProperty = 17
986986
}
987987

988+
func takesObservable(@Observable _ observable: Int) {} // expected-error{{'wrappedValue' is unavailable: must be in a class}}
989+
990+
class MyObservedClass {
991+
@Observable
992+
var observedProperty = 17
993+
}
994+
988995
// ---------------------------------------------------------------------------
989996
// Miscellaneous bugs
990997
// ---------------------------------------------------------------------------

0 commit comments

Comments
 (0)