Skip to content

Commit 6e8324b

Browse files
committed
Sema: Relax availability checking in universally unavailable contexts.
Recent refactoring fixed a bug that previously caused `f()` to be checked as if it were unavailable only on macOS in the following example: ``` @available(macOS, unavailable) struct Outer { @available(*, unavailable) func f() { someFunctionUnavailableOnMacOS() } } ``` Unfortunately, fixing that bug made a different existing availability checking rule more problematic. References to declarations that are unavailable on the current platform have been diagnosed as unavailable even in contexts that are universally unavailable. This long standing behavior is overly strict but it rarely had consequences. However, now that the example above is modeled correctly, this overly strict behavior is causing some source compatibility issues. The easiest solution is to relax the overly strict checking. Resolves rdar://141124478.
1 parent 0d34057 commit 6e8324b

File tree

5 files changed

+86
-50
lines changed

5 files changed

+86
-50
lines changed

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -345,17 +345,17 @@ static bool computeContainedByDeploymentTarget(AvailabilityScope *scope,
345345
static bool isInsideCompatibleUnavailableDeclaration(
346346
const Decl *D, AvailabilityContext availabilityContext,
347347
const AvailableAttr *attr) {
348-
auto referencedPlatform = availabilityContext.getUnavailablePlatformKind();
349-
if (!referencedPlatform)
348+
auto contextPlatform = availabilityContext.getUnavailablePlatformKind();
349+
if (!contextPlatform)
350350
return false;
351351

352352
if (!attr->isUnconditionallyUnavailable())
353353
return false;
354354

355355
// Refuse calling universally unavailable functions from unavailable code,
356356
// but allow the use of types.
357-
PlatformKind platform = attr->Platform;
358-
if (platform == PlatformKind::none && !attr->isForEmbedded() &&
357+
PlatformKind declPlatform = attr->Platform;
358+
if (declPlatform == PlatformKind::none && !attr->isForEmbedded() &&
359359
!isa<TypeDecl>(D) && !isa<ExtensionDecl>(D))
360360
return false;
361361

@@ -364,8 +364,9 @@ static bool isInsideCompatibleUnavailableDeclaration(
364364
if (attr->isForEmbedded())
365365
return availabilityContext.isUnavailableInEmbedded();
366366

367-
return (*referencedPlatform == platform ||
368-
inheritsAvailabilityFromPlatform(platform, *referencedPlatform));
367+
return (*contextPlatform == PlatformKind::none ||
368+
*contextPlatform == declPlatform ||
369+
inheritsAvailabilityFromPlatform(declPlatform, *contextPlatform));
369370
}
370371

371372
const AvailableAttr *

test/Sema/property_wrapper_availability.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ struct WrappedValueUnavailableOnMacOS<T> {
3232
init(wrappedValue: T) { fatalError() }
3333

3434
@available(macOS, unavailable)
35-
var wrappedValue: T { // expected-note 9 {{'wrappedValue' has been explicitly marked unavailable here}}
35+
var wrappedValue: T { // expected-note 6 {{'wrappedValue' has been explicitly marked unavailable here}}
3636
get { fatalError() }
3737
set { fatalError() }
3838
}
@@ -98,7 +98,7 @@ struct UnavailableStruct {
9898
@UnavailableWrapper var unavailableExplicit: S
9999
@UnavailableWrapper var unavailableInferred = S()
100100

101-
@WrappedValueUnavailableOnMacOS var unavailableWrappedValue: S // expected-error {{'wrappedValue' is unavailable in macOS}}
101+
@WrappedValueUnavailableOnMacOS var unavailableWrappedValue: S
102102
@WrappedValueAvailable51 var wrappedValueAavailable51: S // expected-error {{'wrappedValue' is only available in macOS 51 or newer}}
103103
}
104104

@@ -159,14 +159,14 @@ func unavailableFunc(
159159
@Available51Wrapper _ available51: S,
160160
@DeprecatedWrapper _ deprecated: S,
161161
@UnavailableWrapper _ unavailable: S,
162-
@WrappedValueUnavailableOnMacOS _ unavailableWrappedValue: S, // expected-error {{'wrappedValue' is unavailable in macOS}}
162+
@WrappedValueUnavailableOnMacOS _ unavailableWrappedValue: S,
163163
@WrappedValueAvailable51 _ wrappedValueAavailable51: S // expected-error {{'wrappedValue' is only available in macOS 51 or newer}}
164164
) {
165165
@AlwaysAvailableWrapper var alwaysAvailableLocal = S()
166166
@Available51Wrapper var available51Local = S()
167167
@DeprecatedWrapper var deprecatedLocal = S()
168168
@UnavailableWrapper var unavailableLocal = S()
169-
@WrappedValueUnavailableOnMacOS var unavailableWrappedValueLocal = S() // expected-error {{'wrappedValue' is unavailable}}
169+
@WrappedValueUnavailableOnMacOS var unavailableWrappedValueLocal = S()
170170
@WrappedValueAvailable51 var wrappedValueAavailable51 = S() // expected-error {{'wrappedValue' is only available in macOS 51 or newer}}
171171
}
172172

test/attr/attr_availability_transitive_osx.swift

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ func never_available_func(
8989
never() // expected-error {{'never()' is unavailable}}
9090
osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}}
9191
// expected-note@-1 {{add 'if #available' version check}}
92-
osx() // expected-error {{'osx()' is unavailable}}
93-
osx_ios() // expected-error {{'osx_ios()' is unavailable}}
92+
osx()
93+
osx_ios()
9494
osx_extension()
9595
}
9696

@@ -160,8 +160,8 @@ var never_var: (
160160
always(),
161161
never(), // expected-error {{'never()' is unavailable}}
162162
osx_future(), // expected-error {{'osx_future()' is only available in macOS 99 or newer}}
163-
osx(), // expected-error {{'osx()' is unavailable}}
164-
osx_ios(), // expected-error {{'osx_ios()' is unavailable}}
163+
osx(),
164+
osx_ios(),
165165
osx_extension()
166166
)
167167

@@ -219,8 +219,8 @@ struct NeverAvailableContainer { // expected-note 2 {{'NeverAvailableContainer'
219219
let always_var: AlwaysAvailabile = always()
220220
let never_var: NeverAvailable = never() // expected-error {{'never()' is unavailable}}
221221
let osx_future_var: OSXFutureAvailable = osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}}
222-
let osx_var: OSXUnavailable = osx() // expected-error {{'osx()' is unavailable}}
223-
let osx_ios_var: MultiPlatformUnavailable = osx_ios() // expected-error {{'osx_ios()' is unavailable}}
222+
let osx_var: OSXUnavailable = osx()
223+
let osx_ios_var: MultiPlatformUnavailable = osx_ios()
224224
let osx_extension_var: OSXAppExtensionsUnavailable = osx_extension()
225225
}
226226

@@ -303,8 +303,8 @@ extension ExtendMe {
303303
never() // expected-error {{'never()' is unavailable}}
304304
osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}}
305305
// expected-note@-1 {{add 'if #available' version check}}
306-
osx() // expected-error {{'osx()' is unavailable}}
307-
osx_ios() // expected-error {{'osx_ios()' is unavailable}}
306+
osx()
307+
osx_ios()
308308
osx_extension()
309309
}
310310

@@ -321,8 +321,8 @@ extension ExtendMe {
321321
never() // expected-error {{'never()' is unavailable}}
322322
osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}}
323323
// expected-note@-1 {{add 'if #available' version check}}
324-
osx() // expected-error {{'osx()' is unavailable}}
325-
osx_ios() // expected-error {{'osx_ios()' is unavailable}}
324+
osx()
325+
osx_ios()
326326
osx_extension()
327327
}
328328

@@ -339,8 +339,8 @@ extension ExtendMe {
339339
never() // expected-error {{'never()' is unavailable}}
340340
osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}}
341341
// expected-note@-1 {{add 'if #available' version check}}
342-
osx() // expected-error {{'osx()' is unavailable}}
343-
osx_ios() // expected-error {{'osx_ios()' is unavailable}}
342+
osx()
343+
osx_ios()
344344
osx_extension()
345345
}
346346

@@ -357,8 +357,8 @@ extension ExtendMe {
357357
never() // expected-error {{'never()' is unavailable}}
358358
osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}}
359359
// expected-note@-1 {{add 'if #available' version check}}
360-
osx() // expected-error {{'osx()' is unavailable}}
361-
osx_ios() // expected-error {{'osx_ios()' is unavailable}}
360+
osx()
361+
osx_ios()
362362
osx_extension()
363363
}
364364
}
@@ -400,8 +400,8 @@ extension ExtendMe {
400400
never() // expected-error {{'never()' is unavailable}}
401401
osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}}
402402
// expected-note@-1 {{add 'if #available' version check}}
403-
osx() // expected-error {{'osx()' is unavailable}}
404-
osx_ios() // expected-error {{'osx_ios()' is unavailable}}
403+
osx()
404+
osx_ios()
405405
osx_extension()
406406
}
407407

@@ -479,8 +479,8 @@ extension ExtendMe { // expected-note * {{add @available attribute to enclosing
479479
never() // expected-error {{'never()' is unavailable}}
480480
osx_future() // expected-error {{'osx_future()' is only available in macOS 99 or newer}}
481481
// expected-note@-1 {{add 'if #available' version check}}
482-
osx() // expected-error {{'osx()' is unavailable}}
483-
osx_ios() // expected-error {{'osx_ios()' is unavailable}}
482+
osx()
483+
osx_ios()
484484
osx_extension()
485485
}
486486

test/attr/attr_availability_transitive_osx_appext.swift

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ func never_available_func(
4949
_: OSXAppExtensionsUnavailable
5050
) {
5151
never() // expected-error {{'never()' is unavailable}}
52-
osx() // expected-error {{'osx()' is unavailable}}
53-
osx_extension() // expected-error {{'osx_extension()' is unavailable in application extensions for macOS}}
52+
osx()
53+
osx_extension()
5454
}
5555

5656
@available(OSX, unavailable)
@@ -94,8 +94,8 @@ var never_var: (
9494
OSXAppExtensionsUnavailable
9595
) = (
9696
never(), // expected-error {{'never()' is unavailable}}
97-
osx(), // expected-error {{'osx()' is unavailable}}
98-
osx_extension() // expected-error {{'osx_extension()' is unavailable in application extensions for macOS}}
97+
osx(),
98+
osx_extension()
9999
)
100100

101101
@available(OSX, unavailable)
@@ -134,8 +134,8 @@ struct AlwaysAvailabileContainer {
134134
@available(*, unavailable)
135135
struct NeverAvailableContainer { // expected-note {{'NeverAvailableContainer' has been explicitly marked unavailable here}}
136136
let never_var: NeverAvailable = never() // expected-error {{'never()' is unavailable}}
137-
let osx_var: OSXUnavailable = osx() // expected-error {{'osx()' is unavailable}}
138-
let osx_extension_var: OSXAppExtensionsUnavailable = osx_extension() // expected-error {{'osx_extension()' is unavailable in application extensions for macOS}}
137+
let osx_var: OSXUnavailable = osx()
138+
let osx_extension_var: OSXAppExtensionsUnavailable = osx_extension()
139139
}
140140

141141
@available(OSX, unavailable)
@@ -201,8 +201,8 @@ extension ExtendMe {
201201
_: OSXAppExtensionsUnavailable
202202
) {
203203
never() // expected-error {{'never()' is unavailable}}
204-
osx() // expected-error {{'osx()' is unavailable}}
205-
osx_extension() // expected-error {{'osx_extension()' is unavailable in application extensions for macOS}}
204+
osx()
205+
osx_extension()
206206
}
207207

208208
@available(*, unavailable)
@@ -212,8 +212,8 @@ extension ExtendMe {
212212
_: OSXAppExtensionsUnavailable
213213
) {
214214
never() // expected-error {{'never()' is unavailable}}
215-
osx() // expected-error {{'osx()' is unavailable}}
216-
osx_extension() // expected-error {{'osx_extension()' is unavailable in application extensions for macOS}}
215+
osx()
216+
osx_extension()
217217
}
218218

219219
@available(OSX, unavailable)
@@ -223,8 +223,8 @@ extension ExtendMe {
223223
_: OSXAppExtensionsUnavailable
224224
) {
225225
never() // expected-error {{'never()' is unavailable}}
226-
osx() // expected-error {{'osx()' is unavailable}}
227-
osx_extension() // expected-error {{'osx_extension()' is unavailable in application extensions for macOS}}
226+
osx()
227+
osx_extension()
228228
}
229229

230230
@available(OSXApplicationExtension, unavailable)
@@ -234,8 +234,8 @@ extension ExtendMe {
234234
_: OSXAppExtensionsUnavailable
235235
) {
236236
never() // expected-error {{'never()' is unavailable}}
237-
osx() // expected-error {{'osx()' is unavailable}}
238-
osx_extension() // expected-error {{'osx_extension()' is unavailable in application extensions for macOS}}
237+
osx()
238+
osx_extension()
239239
}
240240
}
241241

@@ -263,8 +263,8 @@ extension ExtendMe {
263263
_: OSXAppExtensionsUnavailable
264264
) {
265265
never() // expected-error {{'never()' is unavailable}}
266-
osx() // expected-error {{'osx()' is unavailable}}
267-
osx_extension() // expected-error {{'osx_extension()' is unavailable in application extensions for macOS}}
266+
osx()
267+
osx_extension()
268268
}
269269

270270
@available(OSX, unavailable)
@@ -314,8 +314,8 @@ extension ExtendMe {
314314
_: OSXAppExtensionsUnavailable
315315
) {
316316
never() // expected-error {{'never()' is unavailable}}
317-
osx() // expected-error {{'osx()' is unavailable}}
318-
osx_extension() // expected-error {{'osx_extension()' is unavailable in application extensions for macOS}}
317+
osx()
318+
osx_extension()
319319
}
320320

321321
@available(OSX, unavailable)

test/type/opaque_availability.swift

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,47 @@ func alwaysOpaque() -> some P { return X() } // expected-only-available-error{{'
1010
@available(SwiftStdlib 5.1, *)
1111
func sometimesOpaque() -> some P { return X() }
1212

13-
struct NotP {}
13+
struct NeverConformsToP {}
1414

1515
@available(*, unavailable)
16-
extension NotP: P {} // expected-note {{conformance of 'NotP' to 'P' has been explicitly marked unavailable here}}
16+
extension NeverConformsToP: P {} // expected-note 2 {{conformance of 'NeverConformsToP' to 'P' has been explicitly marked unavailable here}}
1717

1818
@available(SwiftStdlib 5.1, *)
19-
func requireP() -> some P {
20-
NotP() // expected-error {{conformance of 'NotP' to 'P' is unavailable}}
19+
struct Outer {
20+
func returnsNeverConformsToP() -> some P {
21+
NeverConformsToP() // expected-error {{conformance of 'NeverConformsToP' to 'P' is unavailable}}
22+
}
23+
24+
@available(macOS, unavailable)
25+
func returnsNeverConformsToP_macOSUnavailable() -> some P {
26+
NeverConformsToP() // expected-error {{conformance of 'NeverConformsToP' to 'P' is unavailable}}
27+
}
28+
29+
@available(*, unavailable)
30+
func returnsNeverConformsToP_alwaysUnavailable() -> some P {
31+
NeverConformsToP()
32+
}
33+
}
34+
35+
struct ConformsToPExeceptOnMacOS {}
36+
37+
@available(macOS, unavailable)
38+
extension ConformsToPExeceptOnMacOS: P {} // expected-note {{conformance of 'ConformsToPExeceptOnMacOS' to 'P' has been explicitly marked unavailable here}}
39+
40+
@available(SwiftStdlib 5.1, *)
41+
extension Outer {
42+
func returnsConformsToPExeceptOnMacOS() -> some P {
43+
ConformsToPExeceptOnMacOS() // expected-error {{conformance of 'ConformsToPExeceptOnMacOS' to 'P' is unavailable in macOS}}
44+
}
45+
46+
@available(macOS, unavailable)
47+
func returnsConformsToPExeceptOnMacOS_macOSUnavailable() -> some P {
48+
ConformsToPExeceptOnMacOS()
49+
}
50+
51+
@available(*, unavailable)
52+
func returnsConformsToPExeceptOnMacOS_alwaysUnavailable() -> some P {
53+
ConformsToPExeceptOnMacOS()
54+
}
55+
2156
}

0 commit comments

Comments
 (0)