From 550d7bb7540b3bf4af221c0fa744c59173a068d8 Mon Sep 17 00:00:00 2001 From: Allan Shortlidge Date: Wed, 13 Aug 2025 16:45:50 -0700 Subject: [PATCH] Sema: Allow overrides to be unavailable in the current Swift language mode. Fixes a regression from https://github.com/swiftlang/swift/pull/83354. Resolves rdar://158262522 --- lib/Sema/TypeCheckDeclOverride.cpp | 22 ++++++++++++------- .../availability_unavailable_overrides.swift | 17 +++++++++++++- test/ClangImporter/objc_override.swift | 14 ++++++++++++ 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/lib/Sema/TypeCheckDeclOverride.cpp b/lib/Sema/TypeCheckDeclOverride.cpp index ca02ee89f06de..fa620318394e9 100644 --- a/lib/Sema/TypeCheckDeclOverride.cpp +++ b/lib/Sema/TypeCheckDeclOverride.cpp @@ -2191,17 +2191,23 @@ static bool checkSingleOverride(ValueDecl *override, ValueDecl *base) { auto domain = unavailableAttr.getDomain(); auto parsedAttr = unavailableAttr.getParsedAttr(); - if (domain.isPlatform() || domain.isUniversal()) { + switch (domain.getKind()) { + case AvailabilityDomain::Kind::Universal: + case AvailabilityDomain::Kind::SwiftLanguage: + case AvailabilityDomain::Kind::PackageDescription: + case AvailabilityDomain::Kind::Platform: // FIXME: [availability] Diagnose as an error in a future Swift version. break; + case AvailabilityDomain::Kind::Embedded: + case AvailabilityDomain::Kind::Custom: + if (parsedAttr->getLocation().isValid()) + ctx.Diags.diagnose(override, diag::override_unavailable, override) + .fixItRemove(parsedAttr->getRangeWithAt()); + else + ctx.Diags.diagnose(override, diag::override_unavailable, override); + ctx.Diags.diagnose(base, diag::overridden_here); + break; } - - if (parsedAttr->getLocation().isValid()) - ctx.Diags.diagnose(override, diag::override_unavailable, override) - .fixItRemove(parsedAttr->getRangeWithAt()); - else - ctx.Diags.diagnose(override, diag::override_unavailable, override); - ctx.Diags.diagnose(base, diag::overridden_here); break; } case OverrideAvailability::OverrideLessAvailable: { diff --git a/test/Availability/availability_unavailable_overrides.swift b/test/Availability/availability_unavailable_overrides.swift index 363fb075a3abd..a2e0e1353d440 100644 --- a/test/Availability/availability_unavailable_overrides.swift +++ b/test/Availability/availability_unavailable_overrides.swift @@ -239,7 +239,6 @@ func testOverrideOfUnavailableDeclFromUnavailableDerivedType() { } } - func testImplicitSuperInit() { // FIXME: The diagnostics for the implicit call to super.init() could be // relaxed since both initializers are unreachable and the developer cannot @@ -256,3 +255,19 @@ func testImplicitSuperInit() { // expected-note@-2 {{call to unavailable initializer 'init()' from superclass 'Base' occurs implicitly at the end of this initializer}} } } + +func testUnavailableInSwiftOverrides() { + class Base { + func availableMethod() {} + } + + class Derived1: Base { + @available(swift, introduced: 99) + override func availableMethod() {} + } + + class Derived2: Base { + @available(swift, obsoleted: 1) + override func availableMethod() {} + } +} diff --git a/test/ClangImporter/objc_override.swift b/test/ClangImporter/objc_override.swift index 5723f347f047e..70b2b5fb1f2a3 100644 --- a/test/ClangImporter/objc_override.swift +++ b/test/ClangImporter/objc_override.swift @@ -83,6 +83,20 @@ class SomeCellSub5 : SomeCell { func otherIsEnabled() { } // should not conflict } +class SomeCellSub6 : SomeCell { + @available(*, unavailable) + @objc override init(string: String) { + super.init(string: string) + } +} + +class SomeCellSub7 : SomeCell { + @available(swift, obsoleted: 4) + @objc override init(string: String) { + super.init(string: string) + } +} + class FailSub : FailBase { override init(value: Int) { try! super.init(value: value) } // expected-error {{overriding a throwing '@objc' initializer with a non-throwing initializer is not supported}} override class func processValue() {} // expected-error {{overriding a throwing '@objc' method with a non-throwing method is not supported}}