AST: Allow obsoletion in Swift version to disambiguate overloads consistently.

It must be possible to disambiguate overloads using the module-wide Swift
language version, even in contexts that are themselves obsolete in the current
Swift language version.

Resolves rdar://158620835.
This commit is contained in:
Allan Shortlidge
2025-08-18 15:37:14 -07:00
parent de82e315a5
commit 5ae0ad6a8f
3 changed files with 69 additions and 54 deletions

View File

@@ -155,20 +155,20 @@ static bool canIgnoreConstraintInUnavailableContexts(
const AvailabilityConstraintFlags flags) { const AvailabilityConstraintFlags flags) {
auto domain = constraint.getDomain(); auto domain = constraint.getDomain();
switch (constraint.getReason()) { // Always reject uses of universally unavailable declarations, regardless
case AvailabilityConstraint::Reason::UnavailableUnconditionally: // of context, since there are no possible compilation configurations in
if (flags.contains(AvailabilityConstraintFlag:: // which they are available. However, make an exception for types and
AllowUniversallyUnavailableInCompatibleContexts)) // conformances, which can sometimes be awkward to avoid references to.
return true; if (!flags.contains(AvailabilityConstraintFlag::
AllowUniversallyUnavailableInCompatibleContexts)) {
// Always reject uses of universally unavailable declarations, regardless
// of context, since there are no possible compilation configurations in
// which they are available. However, make an exception for types and
// conformances, which can sometimes be awkward to avoid references to.
if (!isa<TypeDecl>(decl) && !isa<ExtensionDecl>(decl)) { if (!isa<TypeDecl>(decl) && !isa<ExtensionDecl>(decl)) {
if (domain.isUniversal() || domain.isSwiftLanguage()) if (domain.isUniversal() || domain.isSwiftLanguage())
return false; return false;
} }
}
switch (constraint.getReason()) {
case AvailabilityConstraint::Reason::UnavailableUnconditionally:
return true; return true;
case AvailabilityConstraint::Reason::Unintroduced: case AvailabilityConstraint::Reason::Unintroduced:

View File

@@ -52,19 +52,34 @@ public class BeforeAndAfter {
// Make sure we can generate calls to these overloads, too // Make sure we can generate calls to these overloads, too
_ = BeforeAndAfter(foo: ()) public func testLocal() throws {
_ = try BeforeAndAfter() _ = BeforeAndAfter(foo: ())
_ = try BeforeAndAfter.foo() _ = try BeforeAndAfter()
_ = BeforeAndAfter.computed _ = try BeforeAndAfter.foo()
BeforeAndAfter.computed = 10 _ = BeforeAndAfter.computed
_ = try BeforeAndAfter().computed BeforeAndAfter.computed = 10
try BeforeAndAfter().computed = 10 _ = try BeforeAndAfter().computed
try BeforeAndAfter().computed = 10
}
@available(swift, obsoleted: 4.0)
public func testLocalObsoleted() throws {
_ = BeforeAndAfter(foo: ())
_ = try BeforeAndAfter()
_ = try BeforeAndAfter.foo()
_ = BeforeAndAfter.computed
BeforeAndAfter.computed = 10
_ = try BeforeAndAfter().computed
try BeforeAndAfter().computed = 10
}
// Same thing but in a different module // Same thing but in a different module
_ = BeforeAndAfterOther(foo: ()) public func testOtherModule() throws {
_ = try BeforeAndAfterOther() _ = BeforeAndAfterOther(foo: ())
_ = try BeforeAndAfterOther.foo() _ = try BeforeAndAfterOther()
_ = BeforeAndAfterOther.computed _ = try BeforeAndAfterOther.foo()
BeforeAndAfterOther.computed = 10 _ = BeforeAndAfterOther.computed
_ = try BeforeAndAfterOther().computed BeforeAndAfterOther.computed = 10
try BeforeAndAfterOther().computed = 10 _ = try BeforeAndAfterOther().computed
try BeforeAndAfterOther().computed = 10
}

View File

@@ -59,8 +59,8 @@ func never_available_func(
) { ) {
always() always()
never() // expected-error {{'never()' is unavailable}} never() // expected-error {{'never()' is unavailable}}
unavailableInSwift4() unavailableInSwift4() // expected-error {{'unavailableInSwift4()' is unavailable}}
availableInFutureSwift() availableInFutureSwift() // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
} }
@available(swift, obsoleted: 4) @available(swift, obsoleted: 4)
@@ -72,8 +72,8 @@ func unavailable_in_swift4_func(
) { ) {
always() always()
never() // expected-error {{'never()' is unavailable}} never() // expected-error {{'never()' is unavailable}}
unavailableInSwift4() unavailableInSwift4() // expected-error {{'unavailableInSwift4()' is unavailable}}
availableInFutureSwift() availableInFutureSwift() // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
} }
@available(swift, introduced: 99) @available(swift, introduced: 99)
@@ -85,8 +85,8 @@ func introduced_in_future_swift_func(
) { ) {
always() always()
never() // expected-error {{'never()' is unavailable}} never() // expected-error {{'never()' is unavailable}}
unavailableInSwift4() unavailableInSwift4() // expected-error {{'unavailableInSwift4()' is unavailable}}
availableInFutureSwift() availableInFutureSwift() // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
} }
// MARK: Global vars // MARK: Global vars
@@ -112,8 +112,8 @@ var never_var: (
) = ( ) = (
always(), always(),
never(), // expected-error {{'never()' is unavailable}} never(), // expected-error {{'never()' is unavailable}}
unavailableInSwift4(), unavailableInSwift4(), // expected-error {{'unavailableInSwift4()' is unavailable}}
availableInFutureSwift(), availableInFutureSwift(), // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
) )
@available(swift, obsoleted: 4) @available(swift, obsoleted: 4)
@@ -125,8 +125,8 @@ var unavailable_in_swift4_var: (
) = ( ) = (
always(), always(),
never(), // expected-error {{'never()' is unavailable}} never(), // expected-error {{'never()' is unavailable}}
unavailableInSwift4(), unavailableInSwift4(), // expected-error {{'unavailableInSwift4()' is unavailable}}
availableInFutureSwift(), availableInFutureSwift(), // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
) )
@available(swift, introduced: 99) @available(swift, introduced: 99)
@@ -138,8 +138,8 @@ var available_in_future_swift_var: (
) = ( ) = (
always(), always(),
never(), // expected-error {{'never()' is unavailable}} never(), // expected-error {{'never()' is unavailable}}
unavailableInSwift4(), unavailableInSwift4(), // expected-error {{'unavailableInSwift4()' is unavailable}}
availableInFutureSwift(), availableInFutureSwift(), // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
) )
@@ -159,8 +159,8 @@ struct AlwaysAvailableContainer {
struct NeverAvailableContainer { // expected-note 3 {{'NeverAvailableContainer' has been explicitly marked unavailable here}} struct NeverAvailableContainer { // expected-note 3 {{'NeverAvailableContainer' has been explicitly marked unavailable here}}
let always_var: AlwaysAvailable = always() let always_var: AlwaysAvailable = always()
let never_var: NeverAvailable = never() // expected-error {{'never()' is unavailable}} let never_var: NeverAvailable = never() // expected-error {{'never()' is unavailable}}
let unavailable_in_swift4_var: UnavailableInSwift4 = unavailableInSwift4() let unavailable_in_swift4_var: UnavailableInSwift4 = unavailableInSwift4() // expected-error {{'unavailableInSwift4()' is unavailable}}
let available_in_future_swift_var: AvailableInFutureSwift = availableInFutureSwift() let available_in_future_swift_var: AvailableInFutureSwift = availableInFutureSwift() // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
} }
@available(swift, obsoleted: 4) @available(swift, obsoleted: 4)
@@ -168,8 +168,8 @@ struct UnavailableInSwift4Container { // expected-note {{'UnavailableInSwift4Con
let always_var: AlwaysAvailable = always() let always_var: AlwaysAvailable = always()
let never_var: NeverAvailable = never() // expected-error {{'never()' is unavailable}} let never_var: NeverAvailable = never() // expected-error {{'never()' is unavailable}}
// expected-error@-1 {{'NeverAvailable' is unavailable}} // expected-error@-1 {{'NeverAvailable' is unavailable}}
let unavailable_in_swift4_var: UnavailableInSwift4 = unavailableInSwift4() let unavailable_in_swift4_var: UnavailableInSwift4 = unavailableInSwift4() // expected-error {{'unavailableInSwift4()' is unavailable}}
let available_in_future_swift_var: AvailableInFutureSwift = availableInFutureSwift() let available_in_future_swift_var: AvailableInFutureSwift = availableInFutureSwift() // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
} }
@available(swift, introduced: 99) @available(swift, introduced: 99)
@@ -177,8 +177,8 @@ struct AvailableInFutureSwiftContainer { // expected-note {{'AvailableInFutureSw
let always_var: AlwaysAvailable = always() let always_var: AlwaysAvailable = always()
let never_var: NeverAvailable = never() // expected-error {{'never()' is unavailable}} let never_var: NeverAvailable = never() // expected-error {{'never()' is unavailable}}
// expected-error@-1 {{'NeverAvailable' is unavailable}} // expected-error@-1 {{'NeverAvailable' is unavailable}}
let unavailable_in_swift4_var: UnavailableInSwift4 = unavailableInSwift4() let unavailable_in_swift4_var: UnavailableInSwift4 = unavailableInSwift4() // expected-error {{'unavailableInSwift4()' is unavailable}}
let available_in_future_swift_var: AvailableInFutureSwift = availableInFutureSwift() let available_in_future_swift_var: AvailableInFutureSwift = availableInFutureSwift() // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
} }
// MARK: Extensions // MARK: Extensions
@@ -229,8 +229,8 @@ extension ExtendMe {
) { ) {
always() always()
never() // expected-error {{'never()' is unavailable}} never() // expected-error {{'never()' is unavailable}}
unavailableInSwift4() unavailableInSwift4() // expected-error {{'unavailableInSwift4()' is unavailable}}
availableInFutureSwift() availableInFutureSwift() // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
} }
@available(*, unavailable) @available(*, unavailable)
@@ -242,8 +242,8 @@ extension ExtendMe {
) { ) {
always() always()
never() // expected-error {{'never()' is unavailable}} never() // expected-error {{'never()' is unavailable}}
unavailableInSwift4() unavailableInSwift4() // expected-error {{'unavailableInSwift4()' is unavailable}}
availableInFutureSwift() availableInFutureSwift() // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
} }
@available(swift, obsoleted: 4) @available(swift, obsoleted: 4)
@@ -255,8 +255,8 @@ extension ExtendMe {
) { ) {
always() always()
never() // expected-error {{'never()' is unavailable}} never() // expected-error {{'never()' is unavailable}}
unavailableInSwift4() unavailableInSwift4() // expected-error {{'unavailableInSwift4()' is unavailable}}
availableInFutureSwift() availableInFutureSwift() // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
} }
@available(swift, introduced: 99) @available(swift, introduced: 99)
@@ -268,8 +268,8 @@ extension ExtendMe {
) { ) {
always() always()
never() // expected-error {{'never()' is unavailable}} never() // expected-error {{'never()' is unavailable}}
unavailableInSwift4() unavailableInSwift4() // expected-error {{'unavailableInSwift4()' is unavailable}}
availableInFutureSwift() availableInFutureSwift() // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
} }
} }
@@ -286,8 +286,8 @@ extension ExtendMe {
) { ) {
always() always()
never() // expected-error {{'never()' is unavailable}} never() // expected-error {{'never()' is unavailable}}
unavailableInSwift4() unavailableInSwift4() // expected-error {{'unavailableInSwift4()' is unavailable}}
availableInFutureSwift() availableInFutureSwift() // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
} }
} }
@@ -304,8 +304,8 @@ extension ExtendMe {
) { ) {
always() always()
never() // expected-error {{'never()' is unavailable}} never() // expected-error {{'never()' is unavailable}}
unavailableInSwift4() unavailableInSwift4() // expected-error {{'unavailableInSwift4()' is unavailable}}
availableInFutureSwift() availableInFutureSwift() // expected-error {{'availableInFutureSwift()' is unavailable in Swift}}
} }
} }