Skip to content

Commit 344d5be

Browse files
committed
Sema: Signatures of decls in local contexts always inherit availability.
Declarations nested in inlinable function bodies, such as `var` declarations, should not introduce new `TypeRefinementContext` nodes that are restricted to the deployment target. This bug was preventing availability checking from noticing availability errors when the occurred in a `var` declaration inside of a fragile function body: ``` @available(macOS 12.0, *) public struct X { public init() {} } @_alwaysEmitIntoClient public func x() { // This should be diagnosed, X is not always available let _ = X() } ``` Resolves rdar://125564069
1 parent c00f00f commit 344d5be

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,11 @@ class TypeRefinementContextBuilder : private ASTWalker {
682682
if (isCurrentTRCContainedByDeploymentTarget())
683683
return false;
684684

685+
// A declaration inside of a local context always inherits the availability
686+
// of the parent.
687+
if (D->getDeclContext()->isLocalContext())
688+
return false;
689+
685690
// As a convenience, SPI decls and explicitly unavailable decls are
686691
// constrained to the deployment target. There's not much benefit to
687692
// checking these declarations at a lower availability version floor since

test/attr/attr_inlinable_available.swift

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,7 @@ public func spiDeployedUseNoAvailable( // expected-note 3 {{add @available attri
368368
// using the minimum inlining target.
369369
//
370370

371-
@inlinable public func inlinedUseNoAvailable( // expected-note 8 {{add @available attribute}}
371+
@inlinable public func inlinedUseNoAvailable( // expected-note 13 {{add @available attribute}}
372372
_: NoAvailable,
373373
_: BeforeInliningTarget,
374374
_: AtInliningTarget,
@@ -396,6 +396,28 @@ public func spiDeployedUseNoAvailable( // expected-note 3 {{add @available attri
396396
if #available(macOS 11, *) {
397397
_ = AfterDeploymentTarget()
398398
}
399+
400+
// Repeat everything with pattern binding decls instead of discard expressions.
401+
defer {
402+
let _ = AtDeploymentTarget() // expected-error {{'AtDeploymentTarget' is only available in macOS 10.15 or newer; clients of 'Test' may have a lower deployment target}} expected-note {{add 'if #available'}}
403+
let _ = AfterDeploymentTarget() // expected-error {{'AfterDeploymentTarget' is only available in macOS 11 or newer}} expected-note {{add 'if #available'}}
404+
}
405+
let _ = NoAvailable()
406+
let _ = BeforeInliningTarget()
407+
let _ = AtInliningTarget()
408+
let _ = BetweenTargets() // expected-error {{'BetweenTargets' is only available in macOS 10.14.5 or newer; clients of 'Test' may have a lower deployment target}} expected-note {{add 'if #available'}}
409+
let _ = AtDeploymentTarget() // expected-error {{'AtDeploymentTarget' is only available in macOS 10.15 or newer; clients of 'Test' may have a lower deployment target}} expected-note {{add 'if #available'}}
410+
let _ = AfterDeploymentTarget() // expected-error {{'AfterDeploymentTarget' is only available in macOS 11 or newer}} expected-note {{add 'if #available'}}
411+
412+
if #available(macOS 10.14.5, *) {
413+
let _ = BetweenTargets()
414+
}
415+
if #available(macOS 10.15, *) {
416+
let _ = AtDeploymentTarget()
417+
}
418+
if #available(macOS 11, *) {
419+
let _ = AfterDeploymentTarget()
420+
}
399421
}
400422

401423
@available(macOS 10.9, *)

0 commit comments

Comments
 (0)