Skip to content

Commit 28b13a1

Browse files
authored
Merge pull request #4985 from graydon/SR-2709-available-swift-version
SR-2709: @available(swift, ...)
2 parents 623a163 + 3ca7555 commit 28b13a1

30 files changed

+669
-260
lines changed

include/swift/AST/Attr.h

Lines changed: 35 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "swift/Basic/UUID.h"
2222
#include "swift/Basic/STLExtras.h"
2323
#include "swift/Basic/Range.h"
24+
#include "swift/Basic/Version.h"
2425
#include "swift/AST/Identifier.h"
2526
#include "swift/AST/AttrKind.h"
2627
#include "swift/AST/ConcreteDeclRef.h"
@@ -542,33 +543,33 @@ class SwiftNativeObjCRuntimeBaseAttr : public DeclAttribute {
542543
};
543544

544545
/// Determine the result of comparing an availability attribute to a specific
545-
/// minimum platform version.
546-
enum class MinVersionComparison {
546+
/// platform or language version.
547+
enum class AvailableVersionComparison {
547548
/// The entity is guaranteed to be available.
548549
Available,
549550

550551
/// The entity is never available.
551552
Unavailable,
552553

553-
/// The entity might be unavailable, because it was introduced after
554-
/// the minimum version.
554+
/// The entity might be unavailable at runtime, because it was introduced
555+
/// after the requested minimum platform version.
555556
PotentiallyUnavailable,
556557

557558
/// The entity has been obsoleted.
558559
Obsoleted,
559560
};
560561

561-
/// Describes the unconditional availability of a declaration.
562-
enum class UnconditionalAvailabilityKind {
563-
/// The declaration is not unconditionally unavailable.
562+
/// Describes the platform-agnostic availability of a declaration.
563+
enum class PlatformAgnosticAvailabilityKind {
564+
/// The associated availability attribute is not platform-agnostic.
564565
None,
565566
/// The declaration is deprecated, but can still be used.
566567
Deprecated,
567568
/// The declaration is unavailable in Swift, specifically
568569
UnavailableInSwift,
569-
/// The declaration is unavailable in the current version of Swift,
570-
/// but was available in previous Swift versions.
571-
UnavailableInCurrentSwift,
570+
/// The declaration is available in some but not all versions
571+
/// of Swift, as specified by the VersionTuple members.
572+
SwiftVersionSpecific,
572573
/// The declaration is unavailable for other reasons.
573574
Unavailable,
574575
};
@@ -585,14 +586,14 @@ class AvailableAttr : public DeclAttribute {
585586
const clang::VersionTuple &Introduced,
586587
const clang::VersionTuple &Deprecated,
587588
const clang::VersionTuple &Obsoleted,
588-
UnconditionalAvailabilityKind Unconditional,
589+
PlatformAgnosticAvailabilityKind PlatformAgnostic,
589590
bool Implicit)
590591
: DeclAttribute(DAK_Available, AtLoc, Range, Implicit),
591592
Message(Message), Rename(Rename),
592593
INIT_VER_TUPLE(Introduced),
593594
INIT_VER_TUPLE(Deprecated),
594595
INIT_VER_TUPLE(Obsoleted),
595-
Unconditional(Unconditional),
596+
PlatformAgnostic(PlatformAgnostic),
596597
Platform(Platform)
597598
{}
598599

@@ -618,21 +619,24 @@ class AvailableAttr : public DeclAttribute {
618619
/// Indicates when the symbol was obsoleted.
619620
const Optional<clang::VersionTuple> Obsoleted;
620621

621-
/// Indicates if the declaration has unconditional availability.
622-
const UnconditionalAvailabilityKind Unconditional;
622+
/// Indicates if the declaration has platform-agnostic availability.
623+
const PlatformAgnosticAvailabilityKind PlatformAgnostic;
623624

624625
/// The platform of the availability.
625626
const PlatformKind Platform;
626627

628+
/// Whether this is a language-version-specific entity.
629+
bool isLanguageVersionSpecific() const;
630+
627631
/// Whether this is an unconditionally unavailable entity.
628632
bool isUnconditionallyUnavailable() const;
629633

630634
/// Whether this is an unconditionally deprecated entity.
631635
bool isUnconditionallyDeprecated() const;
632636

633-
/// Returns the unconditional unavailability.
634-
UnconditionalAvailabilityKind getUnconditionalAvailability() const {
635-
return Unconditional;
637+
/// Returns the platform-agnostic availability.
638+
PlatformAgnosticAvailabilityKind getPlatformAgnosticAvailability() const {
639+
return PlatformAgnostic;
636640
}
637641

638642
/// Determine if a given declaration should be considered unavailable given
@@ -660,17 +664,19 @@ class AvailableAttr : public DeclAttribute {
660664
/// Returns true if this attribute is active given the current platform.
661665
bool isActivePlatform(const ASTContext &ctx) const;
662666

663-
/// Compare this attribute's version information against the minimum platform
664-
/// version (assuming the this attribute pertains to the active platform).
665-
MinVersionComparison getMinVersionAvailability(
666-
clang::VersionTuple minVersion) const;
667+
/// Compare this attribute's version information against the platform or
668+
/// language version (assuming the this attribute pertains to the active
669+
/// platform).
670+
AvailableVersionComparison getVersionAvailability(const ASTContext &ctx) const;
667671

668672
/// Create an AvailableAttr that indicates specific availability
669673
/// for all platforms.
670674
static AvailableAttr *
671-
createUnconditional(ASTContext &C, StringRef Message, StringRef Rename = "",
672-
UnconditionalAvailabilityKind Reason
673-
= UnconditionalAvailabilityKind::Unavailable);
675+
createPlatformAgnostic(ASTContext &C, StringRef Message, StringRef Rename = "",
676+
PlatformAgnosticAvailabilityKind Reason
677+
= PlatformAgnosticAvailabilityKind::Unavailable,
678+
clang::VersionTuple Obsoleted
679+
= clang::VersionTuple());
674680

675681
static bool classof(const DeclAttribute *DA) {
676682
return DA->getKind() == DAK_Available;
@@ -1081,9 +1087,11 @@ class DeclAttributes {
10811087
return getUnavailable(ctx) != nullptr;
10821088
}
10831089

1084-
/// Determine whether there is an "unavailable in current Swift"
1085-
/// attribute.
1086-
bool isUnavailableInCurrentSwift() const;
1090+
/// Determine whether there is a swiftVersionSpecific attribute that's
1091+
/// unavailable relative to the provided language version (defaulting to
1092+
/// current language version).
1093+
bool isUnavailableInSwiftVersion(const version::Version &effectiveVersion =
1094+
version::Version::getCurrentLanguageVersion()) const;
10871095

10881096
/// Returns the first @available attribute that indicates
10891097
/// a declaration is unavailable, or null otherwise.

include/swift/AST/AvailabilitySpec.h

Lines changed: 54 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,15 @@ class ASTContext;
2828
enum class VersionComparison { GreaterThanEqual };
2929

3030
enum class AvailabilitySpecKind {
31-
/// A version constraint of the form PlatformName X.Y.Z
32-
VersionConstraint,
31+
/// A platform-version constraint of the form "PlatformName X.Y.Z"
32+
PlatformVersionConstraint,
3333

3434
/// A wildcard constraint, spelled '*', that is be equivalent
3535
/// to CurrentPlatformName >= MinimumDeploymentTargetVersion
36-
OtherPlatform
36+
OtherPlatform,
37+
38+
/// A language-version constraint of the form "swift X.Y.Z"
39+
LanguageVersionConstraint,
3740
};
3841

3942
/// The root class for specifications of API availability in availability
@@ -57,22 +60,22 @@ class AvailabilitySpec {
5760

5861
/// \brief An availability specification that guards execution based on the
5962
/// run-time platform and version, e.g., OS X >= 10.10.
60-
class VersionConstraintAvailabilitySpec : public AvailabilitySpec {
63+
class PlatformVersionConstraintAvailabilitySpec : public AvailabilitySpec {
6164
PlatformKind Platform;
6265
SourceLoc PlatformLoc;
6366

6467
clang::VersionTuple Version;
6568
SourceRange VersionSrcRange;
6669

6770
public:
68-
VersionConstraintAvailabilitySpec(PlatformKind Platform,
69-
SourceLoc PlatformLoc,
70-
clang::VersionTuple Version,
71-
SourceRange VersionSrcRange)
72-
: AvailabilitySpec(AvailabilitySpecKind::VersionConstraint),
73-
Platform(Platform),
74-
PlatformLoc(PlatformLoc), Version(Version),
75-
VersionSrcRange(VersionSrcRange) {}
71+
PlatformVersionConstraintAvailabilitySpec(PlatformKind Platform,
72+
SourceLoc PlatformLoc,
73+
clang::VersionTuple Version,
74+
SourceRange VersionSrcRange)
75+
: AvailabilitySpec(AvailabilitySpecKind::PlatformVersionConstraint),
76+
Platform(Platform),
77+
PlatformLoc(PlatformLoc), Version(Version),
78+
VersionSrcRange(VersionSrcRange) {}
7679

7780
/// The required platform.
7881
PlatformKind getPlatform() const { return Platform; }
@@ -87,12 +90,49 @@ class VersionConstraintAvailabilitySpec : public AvailabilitySpec {
8790
void print(raw_ostream &OS, unsigned Indent) const;
8891

8992
static bool classof(const AvailabilitySpec *Spec) {
90-
return Spec->getKind() == AvailabilitySpecKind::VersionConstraint;
93+
return Spec->getKind() == AvailabilitySpecKind::PlatformVersionConstraint;
94+
}
95+
96+
void *
97+
operator new(size_t Bytes, ASTContext &C,
98+
unsigned Alignment = alignof(PlatformVersionConstraintAvailabilitySpec)){
99+
return AvailabilitySpec::operator new(Bytes, C, Alignment);
100+
}
101+
};
102+
103+
/// \brief An availability specification that guards execution based on the
104+
/// compile-time language version, e.g., swift >= 3.0.1.
105+
class LanguageVersionConstraintAvailabilitySpec : public AvailabilitySpec {
106+
SourceLoc SwiftLoc;
107+
108+
clang::VersionTuple Version;
109+
SourceRange VersionSrcRange;
110+
111+
public:
112+
LanguageVersionConstraintAvailabilitySpec(SourceLoc SwiftLoc,
113+
clang::VersionTuple Version,
114+
SourceRange VersionSrcRange)
115+
: AvailabilitySpec(AvailabilitySpecKind::LanguageVersionConstraint),
116+
SwiftLoc(SwiftLoc), Version(Version),
117+
VersionSrcRange(VersionSrcRange) {}
118+
119+
SourceLoc getSwiftLoc() const { return SwiftLoc; }
120+
121+
// The platform version to compare against.
122+
clang::VersionTuple getVersion() const { return Version; }
123+
SourceRange getVersionSrcRange() const { return VersionSrcRange; }
124+
125+
SourceRange getSourceRange() const;
126+
127+
void print(raw_ostream &OS, unsigned Indent) const;
128+
129+
static bool classof(const AvailabilitySpec *Spec) {
130+
return Spec->getKind() == AvailabilitySpecKind::LanguageVersionConstraint;
91131
}
92132

93133
void *
94134
operator new(size_t Bytes, ASTContext &C,
95-
unsigned Alignment = alignof(VersionConstraintAvailabilitySpec)){
135+
unsigned Alignment = alignof(LanguageVersionConstraintAvailabilitySpec)){
96136
return AvailabilitySpec::operator new(Bytes, C, Alignment);
97137
}
98138
};

include/swift/AST/DiagnosticsParse.def

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1380,6 +1380,12 @@ ERROR(avail_query_version_comparison_not_needed,
13801380
ERROR(availability_query_wildcard_required, none,
13811381
"must handle potential future platforms with '*'", ())
13821382

1383+
ERROR(availability_swift_must_occur_alone, none,
1384+
"'swift' version-availability must be specified alone", ())
1385+
1386+
ERROR(pound_available_swift_not_allowed, none,
1387+
"Swift language version checks not allowed in #available(...)", ())
1388+
13831389
ERROR(availability_query_repeated_platform, none,
13841390
"version for '%0' already specified", (StringRef))
13851391

include/swift/AST/DiagnosticsSema.def

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3108,6 +3108,10 @@ ERROR(availability_decl_unavailable_in_swift_msg, none,
31083108
NOTE(availability_marked_unavailable, none,
31093109
"%0 has been explicitly marked unavailable here", (DeclName))
31103110

3111+
NOTE(availability_introduced_in_swift, none,
3112+
"%0 was introduced in Swift %1",
3113+
(DeclName, clang::VersionTuple))
3114+
31113115
NOTE(availability_obsoleted, none,
31123116
"%0 was obsoleted in %1 %2",
31133117
(DeclName, StringRef, clang::VersionTuple))

include/swift/Basic/Version.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "llvm/ADT/Optional.h"
2525
#include "llvm/ADT/SmallVector.h"
2626
#include "llvm/ADT/StringRef.h"
27+
#include "clang/Basic/VersionTuple.h"
2728
#include <string>
2829

2930
namespace swift {
@@ -89,6 +90,10 @@ class Version {
8990
return Components.empty();
9091
}
9192

93+
/// Convert to a (maximum-4-element) clang::VersionTuple, truncating
94+
/// away any 5th component that might be in this version.
95+
operator clang::VersionTuple() const;
96+
9297
/// Return whether this version is a valid Swift language version number
9398
/// to set the compiler to using -swift-version; this is not the same as
9499
/// the set of Swift versions that have ever existed, just those that we

include/swift/Parse/Parser.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1245,7 +1245,10 @@ class Parser {
12451245
parseAvailabilitySpecList(SmallVectorImpl<AvailabilitySpec *> &Specs);
12461246

12471247
ParserResult<AvailabilitySpec> parseAvailabilitySpec();
1248-
ParserResult<VersionConstraintAvailabilitySpec> parseVersionConstraintSpec();
1248+
ParserResult<PlatformVersionConstraintAvailabilitySpec>
1249+
parsePlatformVersionConstraintSpec();
1250+
ParserResult<LanguageVersionConstraintAvailabilitySpec>
1251+
parseLanguageVersionConstraintSpec();
12491252
};
12501253

12511254
/// Describes a parsed declaration name.

lib/AST/ASTDumper.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1215,8 +1215,11 @@ class PrintStmt : public StmtVisitor<PrintStmt> {
12151215
for (auto *Query : C.getAvailability()->getQueries()) {
12161216
OS << '\n';
12171217
switch (Query->getKind()) {
1218-
case AvailabilitySpecKind::VersionConstraint:
1219-
cast<VersionConstraintAvailabilitySpec>(Query)->print(OS, Indent + 2);
1218+
case AvailabilitySpecKind::PlatformVersionConstraint:
1219+
cast<PlatformVersionConstraintAvailabilitySpec>(Query)->print(OS, Indent + 2);
1220+
break;
1221+
case AvailabilitySpecKind::LanguageVersionConstraint:
1222+
cast<LanguageVersionConstraintAvailabilitySpec>(Query)->print(OS, Indent + 2);
12201223
break;
12211224
case AvailabilitySpecKind::OtherPlatform:
12221225
cast<OtherPlatformAvailabilitySpec>(Query)->print(OS, Indent + 2);

lib/AST/ASTPrinter.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1448,8 +1448,8 @@ bool swift::shouldPrint(const Decl *D, PrintOptions &Options) {
14481448
D->getAttrs().isUnavailable(D->getASTContext()))
14491449
return false;
14501450

1451-
// Skip stub declarations used for prior variants of Swift.
1452-
if (D->getAttrs().isUnavailableInCurrentSwift())
1451+
// Skip stub declarations used for prior or later variants of Swift.
1452+
if (D->getAttrs().isUnavailableInSwiftVersion())
14531453
return false;
14541454

14551455
if (Options.ExplodeEnumCaseDecls) {

0 commit comments

Comments
 (0)