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,
|
NOTE(availability_query_useless_enclosing_scope_here, none,
|
||||||
"enclosing scope here", ())
|
"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,
|
ERROR(availability_global_script_no_potential,
|
||||||
none, "global variable cannot be marked potentially "
|
none, "global variable cannot be marked potentially "
|
||||||
"unavailable with '@available' in script mode", ())
|
"unavailable with '@available' in script mode", ())
|
||||||
|
|||||||
@@ -70,7 +70,6 @@ public:
|
|||||||
bool visitDeclAttribute(DeclAttribute *A) = delete;
|
bool visitDeclAttribute(DeclAttribute *A) = delete;
|
||||||
|
|
||||||
#define IGNORED_ATTR(X) void visit##X##Attr(X##Attr *) {}
|
#define IGNORED_ATTR(X) void visit##X##Attr(X##Attr *) {}
|
||||||
IGNORED_ATTR(Available)
|
|
||||||
IGNORED_ATTR(CDecl)
|
IGNORED_ATTR(CDecl)
|
||||||
IGNORED_ATTR(ClangImporterSynthesizedType)
|
IGNORED_ATTR(ClangImporterSynthesizedType)
|
||||||
IGNORED_ATTR(Convenience)
|
IGNORED_ATTR(Convenience)
|
||||||
@@ -115,6 +114,14 @@ public:
|
|||||||
IGNORED_ATTR(WeakLinked)
|
IGNORED_ATTR(WeakLinked)
|
||||||
#undef IGNORED_ATTR
|
#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.
|
// @noreturn has been replaced with a 'Never' return type.
|
||||||
void visitNoReturnAttr(NoReturnAttr *attr) {
|
void visitNoReturnAttr(NoReturnAttr *attr) {
|
||||||
if (auto FD = dyn_cast<FuncDecl>(D)) {
|
if (auto FD = dyn_cast<FuncDecl>(D)) {
|
||||||
@@ -1073,8 +1080,10 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
|
|||||||
if (TC.getLangOpts().DisableAvailabilityChecking)
|
if (TC.getLangOpts().DisableAvailabilityChecking)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!attr->isActivePlatform(TC.Context) || !attr->Introduced.hasValue())
|
if (!attr->hasPlatform() || !attr->isActivePlatform(TC.Context) ||
|
||||||
|
!attr->Introduced.hasValue()) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
SourceLoc attrLoc = attr->getLocation();
|
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}}
|
func rdar32526620_3(a: Int, b: E_32526620, c: String) {} // expected-note {{here}}
|
||||||
rdar32526620_3(a: 42, b: .bar, c: "question")
|
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=}}
|
// 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() { }
|
func doSomethingDeprecatedOniOS() { }
|
||||||
|
|
||||||
doSomethingDeprecatedOniOS() // okay
|
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")
|
@available(swift, introduced: 3.0.1, obsoleted: 3.0.2, message: "tiny bug")
|
||||||
func 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