Skip to content

Commit cd25c00

Browse files
authored
Merge pull request swiftlang#77159 from tshortli/adopt-availability-context-in-export-context
Sema: Adopt AvailabilityContext in ExportContext
2 parents 36e14c7 + ac98262 commit cd25c00

9 files changed

+191
-162
lines changed

include/swift/AST/AvailabilityContext.h

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,20 @@ class AvailabilityContext {
7171
/// Returns true if this context is deprecated on the current platform.
7272
bool isDeprecated() const;
7373

74+
/// Constrain with another `AvailabilityContext`.
75+
void constrainWithContext(const AvailabilityContext &other, ASTContext &ctx);
76+
77+
/// Constrain with the availability attributes of `decl`.
78+
void constrainWithDecl(const Decl *decl);
79+
7480
/// Constrain the platform availability range with `platformRange`.
7581
void constrainWithPlatformRange(const AvailabilityRange &platformRange,
7682
ASTContext &ctx);
7783

78-
/// Constrain the platform availability range with both the availability
79-
/// attributes of `decl` and with `platformRange`.
84+
/// Constrain with the availability attributes of `decl`, intersecting the
85+
/// platform range of `decl` with `platformRange`.
8086
void
81-
constrainWithDeclAndPlatformRange(Decl *decl,
87+
constrainWithDeclAndPlatformRange(const Decl *decl,
8288
const AvailabilityRange &platformRange);
8389

8490
/// Returns true if `other` is as available or is more available.

include/swift/AST/AvailabilityContextStorage.h

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,15 @@ struct AvailabilityContext::PlatformInfo {
4040
/// platform.
4141
unsigned IsDeprecated : 1;
4242

43-
/// Sets `Range` to `other` if `other` is more restrictive. Returns true if
44-
/// any property changed as a result of adding this constraint.
43+
/// Sets each field to the value of the corresponding field in `other` if the
44+
/// other is more restrictive. Returns true if any field changed as a result
45+
/// of adding this constraint.
46+
bool constrainWith(const PlatformInfo &other);
47+
48+
/// Updates each field to reflect the availability of `decl`, if that
49+
/// availability is more restrictive. Returns true if any field was updated.
50+
bool constrainWith(const Decl *decl);
51+
4552
bool constrainRange(const AvailabilityRange &other) {
4653
if (!other.isContainedIn(Range))
4754
return false;
@@ -50,19 +57,9 @@ struct AvailabilityContext::PlatformInfo {
5057
return true;
5158
}
5259

53-
/// Sets `Range` to the platform introduction range of `decl` if that range
54-
/// is more restrictive. Returns true if
55-
/// any property changed as a result of adding this constraint.
56-
bool constrainRange(const Decl *decl);
57-
58-
/// Updates `UnavailablePlatform` and `IsUnavailable` to reflect the status
59-
/// of `decl` if its platform unavailability is more restrictive. Returns
60-
/// true if any property changed as a result of adding this constraint.
61-
bool constrainUnavailability(const Decl *decl);
60+
bool constrainUnavailability(std::optional<PlatformKind> unavailablePlatform);
6261

63-
/// If `decl` is deprecated, sets `IsDeprecated` to true. Returns true if
64-
/// any property changed as a result of adding this constraint.
65-
bool constrainDeprecated(const Decl *decl);
62+
bool constrainDeprecated(bool deprecated);
6663

6764
/// Returns true if `other` is as available or is more available.
6865
bool isContainedIn(const PlatformInfo &other) const;

lib/AST/AvailabilityContext.cpp

Lines changed: 57 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,37 +18,62 @@
1818

1919
using namespace swift;
2020

21-
bool AvailabilityContext::PlatformInfo::constrainRange(const Decl *decl) {
21+
bool AvailabilityContext::PlatformInfo::constrainWith(
22+
const PlatformInfo &other) {
23+
bool isConstrained = false;
24+
isConstrained |= constrainRange(other.Range);
25+
if (other.IsUnavailable) {
26+
isConstrained |= constrainUnavailability(other.UnavailablePlatform);
27+
}
28+
isConstrained |= constrainDeprecated(other.IsDeprecated);
29+
30+
return isConstrained;
31+
}
32+
33+
bool AvailabilityContext::PlatformInfo::constrainWith(const Decl *decl) {
34+
bool isConstrained = false;
35+
auto &ctx = decl->getASTContext();
36+
2237
if (auto range = AvailabilityInference::annotatedAvailableRange(decl))
23-
return constrainRange(*range);
38+
isConstrained |= constrainRange(*range);
39+
40+
if (auto *attr = decl->getAttrs().getUnavailable(ctx))
41+
isConstrained |= constrainUnavailability(attr->Platform);
42+
43+
if (!IsDeprecated)
44+
isConstrained |= constrainDeprecated(decl->getAttrs().isDeprecated(ctx));
2445

25-
return false;
46+
return isConstrained;
2647
}
2748

2849
bool AvailabilityContext::PlatformInfo::constrainUnavailability(
29-
const Decl *decl) {
30-
auto &ctx = decl->getASTContext();
31-
auto *attr = decl->getAttrs().getUnavailable(ctx);
32-
if (!attr)
50+
std::optional<PlatformKind> unavailablePlatform) {
51+
if (!unavailablePlatform)
3352
return false;
3453

35-
// Check whether the decl's unavailability reason is the same.
36-
if (IsUnavailable && UnavailablePlatform == attr->Platform)
37-
return false;
54+
if (IsUnavailable) {
55+
// Universal unavailability cannot be refined.
56+
if (UnavailablePlatform == PlatformKind::none)
57+
return false;
3858

39-
// Check whether the decl's unavailability reason is more specific.
40-
if (attr->Platform != PlatformKind::none &&
41-
inheritsAvailabilityFromPlatform(attr->Platform, UnavailablePlatform))
42-
return false;
59+
// There's nothing to do if the platforms already match.
60+
if (UnavailablePlatform == *unavailablePlatform)
61+
return false;
62+
63+
// The new platform must be more restrictive.
64+
if (*unavailablePlatform != PlatformKind::none &&
65+
inheritsAvailabilityFromPlatform(*unavailablePlatform,
66+
UnavailablePlatform))
67+
return false;
68+
}
4369

4470
IsUnavailable = true;
45-
UnavailablePlatform = attr->Platform;
71+
UnavailablePlatform = *unavailablePlatform;
4672
return true;
4773
}
4874

49-
bool AvailabilityContext::PlatformInfo::constrainDeprecated(const Decl *decl) {
50-
auto &ctx = decl->getASTContext();
51-
if (IsDeprecated || !decl->getAttrs().isDeprecated(ctx))
75+
bool AvailabilityContext::PlatformInfo::constrainDeprecated(bool deprecated) {
76+
if (IsDeprecated || !deprecated)
5277
return false;
5378

5479
IsDeprecated = true;
@@ -116,6 +141,18 @@ bool AvailabilityContext::isDeprecated() const {
116141
return Info->Platform.IsDeprecated;
117142
}
118143

144+
void AvailabilityContext::constrainWithContext(const AvailabilityContext &other,
145+
ASTContext &ctx) {
146+
PlatformInfo platformAvailability{Info->Platform};
147+
if (platformAvailability.constrainWith(other.Info->Platform)) {
148+
Info = Storage::get(platformAvailability, ctx);
149+
}
150+
}
151+
152+
void AvailabilityContext::constrainWithDecl(const Decl *decl) {
153+
constrainWithDeclAndPlatformRange(decl, AvailabilityRange::alwaysAvailable());
154+
}
155+
119156
void AvailabilityContext::constrainWithPlatformRange(
120157
const AvailabilityRange &platformRange, ASTContext &ctx) {
121158
PlatformInfo platformAvailability{Info->Platform};
@@ -126,13 +163,11 @@ void AvailabilityContext::constrainWithPlatformRange(
126163
}
127164

128165
void AvailabilityContext::constrainWithDeclAndPlatformRange(
129-
Decl *decl, const AvailabilityRange &platformRange) {
166+
const Decl *decl, const AvailabilityRange &platformRange) {
130167
PlatformInfo platformAvailability{Info->Platform};
131168
bool isConstrained = false;
132-
isConstrained |= platformAvailability.constrainRange(decl);
169+
isConstrained |= platformAvailability.constrainWith(decl);
133170
isConstrained |= platformAvailability.constrainRange(platformRange);
134-
isConstrained |= platformAvailability.constrainUnavailability(decl);
135-
isConstrained |= platformAvailability.constrainDeprecated(decl);
136171

137172
if (!isConstrained)
138173
return;

0 commit comments

Comments
 (0)