mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
Allow @available(swift, ...) nested within @available(macOS, ...)
Previously, we treated this as an attempt to widen the availability of a member beyond its context, but it's really a different axis of availability. Also, warn about using @available on extensions without an OS, which we just completely ignore right now. rdar://problem/32632327
This commit is contained in:
@@ -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", ())
|
||||
|
||||
@@ -70,7 +70,6 @@ public:
|
||||
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)
|
||||
@@ -115,6 +114,14 @@ public:
|
||||
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)) {
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
@@ -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}}
|
||||
}
|
||||
|
||||
@@ -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 {}
|
||||
|
||||
Reference in New Issue
Block a user