Skip to content

Commit 1c9b003

Browse files
authored
Merge pull request #61242 from tshortli/diagnose-decl-more-available-than-unavailable-enclosing-scope
Sema: Diagnose declarations that are annotated to be more available than their unavailable enclosing scope
2 parents 0312a93 + cebfe57 commit 1c9b003

File tree

4 files changed

+28
-5
lines changed

4 files changed

+28
-5
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5696,14 +5696,22 @@ ERROR(availability_decl_more_than_enclosing, none,
56965696
"%0 cannot be more available than enclosing scope",
56975697
(DescriptiveDeclKind))
56985698

5699+
WARNING(availability_decl_more_than_unavailable_enclosing, none,
5700+
"%0 cannot be more available than unavailable enclosing scope",
5701+
(DescriptiveDeclKind))
5702+
56995703
NOTE(availability_implicit_decl_here, none,
57005704
"%0 implicitly declared here with availability of %1 %2 or newer",
57015705
(DescriptiveDeclKind, StringRef, llvm::VersionTuple))
57025706

5703-
NOTE(availability_decl_more_than_enclosing_enclosing_here, none,
5707+
NOTE(availability_decl_more_than_enclosing_here, none,
57045708
"enclosing scope requires availability of %0 %1 or newer",
57055709
(StringRef, llvm::VersionTuple))
57065710

5711+
NOTE(availability_decl_more_than_unavailable_enclosing_here, none,
5712+
"enclosing scope has been explicitly marked unavailable here",
5713+
())
5714+
57075715
ERROR(availability_decl_only_version_newer, none,
57085716
"%0 is only available in %1 %2 or newer",
57095717
(DeclName, StringRef, llvm::VersionTuple))

lib/Sema/TypeCheckAttr.cpp

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,9 +1814,15 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
18141814
// is fully contained within that declaration's range. If there is no such
18151815
// enclosing declaration, then there is nothing to check.
18161816
Optional<AvailabilityContext> EnclosingAnnotatedRange;
1817+
bool EnclosingDeclIsUnavailable = false;
18171818
Decl *EnclosingDecl = getEnclosingDeclForDecl(D);
18181819

18191820
while (EnclosingDecl) {
1821+
if (EnclosingDecl->getAttrs().getUnavailable(Ctx)) {
1822+
EnclosingDeclIsUnavailable = true;
1823+
break;
1824+
}
1825+
18201826
EnclosingAnnotatedRange =
18211827
AvailabilityInference::annotatedAvailableRange(EnclosingDecl, Ctx);
18221828

@@ -1830,7 +1836,13 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
18301836
VersionRange::allGTE(attr->Introduced.getValue())};
18311837

18321838
if (EnclosingDecl) {
1833-
if (!AttrRange.isContainedIn(EnclosingAnnotatedRange.getValue())) {
1839+
if (EnclosingDeclIsUnavailable) {
1840+
diagnose(D->isImplicit() ? EnclosingDecl->getLoc() : attr->getLocation(),
1841+
diag::availability_decl_more_than_unavailable_enclosing,
1842+
D->getDescriptiveKind());
1843+
diagnose(EnclosingDecl->getLoc(),
1844+
diag::availability_decl_more_than_unavailable_enclosing_here);
1845+
} else if (!AttrRange.isContainedIn(EnclosingAnnotatedRange.getValue())) {
18341846
diagnose(D->isImplicit() ? EnclosingDecl->getLoc() : attr->getLocation(),
18351847
diag::availability_decl_more_than_enclosing,
18361848
D->getDescriptiveKind());
@@ -1841,7 +1853,7 @@ void AttributeChecker::visitAvailableAttr(AvailableAttr *attr) {
18411853
prettyPlatformString(targetPlatform(Ctx.LangOpts)),
18421854
AttrRange.getOSVersion().getLowerEndpoint());
18431855
diagnose(EnclosingDecl->getLoc(),
1844-
diag::availability_decl_more_than_enclosing_enclosing_here,
1856+
diag::availability_decl_more_than_enclosing_here,
18451857
prettyPlatformString(targetPlatform(Ctx.LangOpts)),
18461858
EnclosingAnnotatedRange->getOSVersion().getLowerEndpoint());
18471859
}

test/Sema/availability_versions.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1725,10 +1725,12 @@ struct HasUnavailableExtension {
17251725

17261726
@available(OSX, unavailable)
17271727
extension HasUnavailableExtension {
1728+
// expected-note@-1 {{enclosing scope has been explicitly marked unavailable here}}
1729+
17281730
public func inheritsUnavailable() { }
17291731
// expected-note@-1 {{'inheritsUnavailable()' has been explicitly marked unavailable here}}
17301732

1731-
@available(OSX 10.9, *)
1733+
@available(OSX 10.9, *) // expected-warning {{instance method cannot be more available than unavailable enclosing scope}}
17321734
public func moreAvailableButStillUnavailable() { }
17331735
// expected-note@-1 {{'moreAvailableButStillUnavailable()' has been explicitly marked unavailable here}}
17341736
}

test/attr/attr_availability_transitive_osx.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ extension Outer {
105105
}
106106

107107
@available(OSX, unavailable)
108+
// expected-note@+1 {{enclosing scope has been explicitly marked unavailable here}}
108109
extension Outer {
109110
// expected-note@+1 {{'outer_osx_init_osx' has been explicitly marked unavailable here}}
110111
static var outer_osx_init_osx = osx() // OK
@@ -123,7 +124,7 @@ extension Outer {
123124
}
124125

125126
// This @available should be ignored; inherited unavailability takes precedence
126-
@available(OSX 999, *)
127+
@available(OSX 999, *) // expected-warning {{instance method cannot be more available than unavailable enclosing scope}}
127128
// expected-note@+1 {{'osx_more_available_but_still_unavailable_call_osx()' has been explicitly marked unavailable here}}
128129
func osx_more_available_but_still_unavailable_call_osx() {
129130
osx() // OK

0 commit comments

Comments
 (0)