Skip to content

Allow @available(swift, ...) nested within @available(macOS, ...) #15213

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions include/swift/AST/DiagnosticsSema.def
Original file line number Diff line number Diff line change
Expand Up @@ -3647,6 +3647,10 @@ WARNING(availability_query_useless_enclosing_scope, none,
NOTE(availability_query_useless_enclosing_scope_here, none,
"enclosing scope here", ())

WARNING(availability_extension_platform_agnostic, none,
"'@available' without an OS is ignored on extensions; "
"apply the attribute to each member instead", ())

ERROR(availability_global_script_no_potential,
none, "global variable cannot be marked potentially "
"unavailable with '@available' in script mode", ())
Expand Down
13 changes: 11 additions & 2 deletions lib/Sema/TypeCheckAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ class AttributeEarlyChecker : public AttributeVisitor<AttributeEarlyChecker> {
bool visitDeclAttribute(DeclAttribute *A) = delete;

#define IGNORED_ATTR(X) void visit##X##Attr(X##Attr *) {}
IGNORED_ATTR(Available)
IGNORED_ATTR(CDecl)
IGNORED_ATTR(ClangImporterSynthesizedType)
IGNORED_ATTR(Convenience)
Expand Down Expand Up @@ -115,6 +114,14 @@ class AttributeEarlyChecker : public AttributeVisitor<AttributeEarlyChecker> {
IGNORED_ATTR(WeakLinked)
#undef IGNORED_ATTR

void visitAvailableAttr(AvailableAttr *attr) {
if (!isa<ExtensionDecl>(D))
return;
if (attr->hasPlatform())
return;
diagnoseAndRemoveAttr(attr, diag::availability_extension_platform_agnostic);
}

// @noreturn has been replaced with a 'Never' return type.
void visitNoReturnAttr(NoReturnAttr *attr) {
if (auto FD = dyn_cast<FuncDecl>(D)) {
Expand Down Expand Up @@ -1073,8 +1080,10 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
if (TC.getLangOpts().DisableAvailabilityChecking)
return;

if (!attr->isActivePlatform(TC.Context) || !attr->Introduced.hasValue())
if (!attr->hasPlatform() || !attr->isActivePlatform(TC.Context) ||
!attr->Introduced.hasValue()) {
return;
}

SourceLoc attrLoc = attr->getLocation();

Expand Down
9 changes: 0 additions & 9 deletions stdlib/public/SDK/Metal/Metal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

@_exported import Metal // Clang module

@available(swift 4)
@available(macOS 10.11, iOS 8.0, tvOS 8.0, *)
extension MTLBlitCommandEncoder {

Expand All @@ -21,7 +20,6 @@ extension MTLBlitCommandEncoder {
}
}

@available(swift 4)
@available(macOS 10.11, iOS 8.0, tvOS 8.0, *)
extension MTLBuffer {

Expand All @@ -38,7 +36,6 @@ extension MTLBuffer {
}
}

@available(swift 4)
@available(macOS 10.11, iOS 8.0, tvOS 8.0, *)
extension MTLComputeCommandEncoder {

Expand Down Expand Up @@ -69,7 +66,6 @@ extension MTLComputeCommandEncoder {
}
}

@available(swift 4)
@available(macOS 10.11, iOS 8.0, tvOS 8.0, *)
extension MTLDevice {

Expand All @@ -92,7 +88,6 @@ public func MTLCopyAllDevicesWithObserver(handler: @escaping MTLDeviceNotificati
}
#endif

@available(swift 4)
@available(macOS 10.12, iOS 10.0, tvOS 10.0, *)
extension MTLFunctionConstantValues {

Expand All @@ -102,7 +97,6 @@ extension MTLFunctionConstantValues {

}

@available(swift 4)
@available(macOS 10.13, iOS 11.0, tvOS 11.0, *)
extension MTLArgumentEncoder {

Expand All @@ -119,7 +113,6 @@ extension MTLArgumentEncoder {
}
}

@available(swift 4)
@available(macOS 10.11, iOS 8.0, tvOS 8.0, *)
extension MTLRenderCommandEncoder {

Expand Down Expand Up @@ -201,7 +194,6 @@ extension MTLRenderCommandEncoder {
#endif
}

@available(swift 4)
@available(macOS 10.11, iOS 8.0, tvOS 8.0, *)
extension MTLRenderPassDescriptor {

Expand All @@ -220,7 +212,6 @@ extension MTLRenderPassDescriptor {

}

@available(swift 4)
@available(macOS 10.11, iOS 8.0, tvOS 8.0, *)
extension MTLTexture {

Expand Down
1 change: 0 additions & 1 deletion stdlib/public/SDK/MetalKit/MetalKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

@_exported import MetalKit // Clang module

@available(swift 4)
@available(macOS 10.11, iOS 9.0, tvOS 9.0, *)
extension MTKMesh {
public class func newMeshes(asset: MDLAsset, device: MTLDevice) throws -> (modelIOMeshes: [MDLMesh], metalKitMeshes: [MTKMesh]) {
Expand Down
2 changes: 0 additions & 2 deletions stdlib/public/SDK/UIKit/UIKit.swift
Original file line number Diff line number Diff line change
Expand Up @@ -95,11 +95,9 @@ extension _UIKitNumericRawRepresentable {
}
}

@available(swift 4)
extension UIFont.Weight : _UIKitNumericRawRepresentable {}

#if !os(watchOS)
@available(swift 4)
extension UILayoutPriority : _UIKitNumericRawRepresentable {}
#endif

Expand Down
1 change: 0 additions & 1 deletion stdlib/public/core/Integers.swift.gyb
Original file line number Diff line number Diff line change
Expand Up @@ -3841,7 +3841,6 @@ extension SignedNumeric where Self : Comparable {
}
}

@available(swift, obsoleted: 4)
extension BinaryInteger {
@_inlineable // FIXME(sil-serialize-all)
@available(swift, obsoleted: 4)
Expand Down
6 changes: 6 additions & 0 deletions test/attr/attr_availability.swift
Original file line number Diff line number Diff line change
Expand Up @@ -807,3 +807,9 @@ rdar32526620_2(a: 42, b: .bar)
func rdar32526620_3(a: Int, b: E_32526620, c: String) {} // expected-note {{here}}
rdar32526620_3(a: 42, b: .bar, c: "question")
// expected-error@-1 {{'rdar32526620_3(a:b:c:)' has been replaced by instance method 'E_32526620.set(a:c:)'}} {{1-15=E_32526620.bar.set}} {{23-32=}}

@available(*, unavailable) // expected-warning {{'@available' without an OS is ignored on extensions; apply the attribute to each member instead}} {{1-28=}}
extension DummyType {}

@available(*, deprecated) // expected-warning {{'@available' without an OS is ignored on extensions; apply the attribute to each member instead}} {{1-27=}}
extension DummyType {}
33 changes: 33 additions & 0 deletions test/attr/attr_availability_osx.swift
Original file line number Diff line number Diff line change
Expand Up @@ -71,3 +71,36 @@ doSomethingDeprecatedOnOSX() // expected-warning{{'doSomethingDeprecatedOnOSX()'
func doSomethingDeprecatedOniOS() { }

doSomethingDeprecatedOniOS() // okay


struct TestStruct {}

@available(macOS 10.10, *)
extension TestStruct { // expected-note {{enclosing scope here}}
@available(swift 400)
func doTheThing() {} // expected-note {{'doTheThing()' was introduced in Swift 400}}

@available(macOS 10.9, *) // expected-error {{declaration cannot be more available than enclosing scope}}
@available(swift 400)
func doAnotherThing() {} // expected-note {{'doAnotherThing()' was introduced in Swift 400}}

@available(macOS 10.12, *)
@available(swift 400)
func doThirdThing() {} // expected-note {{'doThirdThing()' was introduced in Swift 400}}

@available(macOS 10.12, *)
@available(swift 1)
func doFourthThing() {}

@available(*, deprecated)
func doDeprecatedThing() {}
}

@available(macOS 10.11, *)
func testMemberAvailability() {
TestStruct().doTheThing() // expected-error {{'doTheThing()' is unavailable}}
TestStruct().doAnotherThing() // expected-error {{'doAnotherThing()' is unavailable}}
TestStruct().doThirdThing() // expected-error {{'doThirdThing()' is unavailable}}
TestStruct().doFourthThing() // expected-error {{'doFourthThing()' is only available on OS X 10.12 or newer}} expected-note {{'if #available'}}
TestStruct().doDeprecatedThing() // expected-warning {{'doDeprecatedThing()' is deprecated}}
}
27 changes: 27 additions & 0 deletions test/attr/attr_availability_swift.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,30 @@ func baz() {
@available(swift, introduced: 3.0.1, obsoleted: 3.0.2, message: "tiny bug")
func bug() {
}

struct TestStruct {}

@available(macOS 10.11, *)
extension TestStruct {
@available(swift 400)
func doTheThing() {} // expected-note {{'doTheThing()' was introduced in Swift 400}}
}

@available(swift 400) // expected-warning {{'@available' without an OS is ignored on extensions; apply the attribute to each member instead}} {{1-23=}}
extension TestStruct {
func doAnotherThing() {}
}

@available(macOS 10.11, *)
func testMemberAvailability() {
TestStruct().doTheThing() // expected-error {{'doTheThing()' is unavailable}}
TestStruct().doAnotherThing() // okay (for now)
}

@available(swift 400) // expected-warning {{'@available' without an OS is ignored on extensions; apply the attribute to each member instead}} {{1-23=}}
@available(macOS 10.11, *)
extension TestStruct {}

@available(macOS 10.11, *)
@available(swift 400) // expected-warning {{'@available' without an OS is ignored on extensions; apply the attribute to each member instead}} {{1-23=}}
extension TestStruct {}