Skip to content

Commit 4b773a4

Browse files
committed
AST: Move AvailabilityDomain ordering to Availabilty.cpp.
Availability attribute inferrence is currently the only thing that depends on having a total ordering on AvailabilityDomains.
1 parent 96862b4 commit 4b773a4

File tree

2 files changed

+35
-19
lines changed

2 files changed

+35
-19
lines changed

include/swift/AST/AvailabilityDomain.h

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -196,23 +196,6 @@ class AvailabilityDomain final {
196196
return !(*this == other);
197197
}
198198

199-
/// A total, stable ordering on domains.
200-
bool operator<(const AvailabilityDomain &other) const {
201-
if (getKind() != other.getKind())
202-
return getKind() < other.getKind();
203-
204-
switch (getKind()) {
205-
case Kind::Universal:
206-
case Kind::SwiftLanguage:
207-
case Kind::PackageDescription:
208-
case Kind::Embedded:
209-
// These availability domains are singletons.
210-
return false;
211-
case Kind::Platform:
212-
return getPlatformKind() < other.getPlatformKind();
213-
}
214-
}
215-
216199
void Profile(llvm::FoldingSetNodeID &ID) const {
217200
ID.AddPointer(getOpaqueValue());
218201
}
@@ -249,6 +232,10 @@ struct DenseMapInfo<AvailabilityDomain> {
249232
static inline AvailabilityDomain getTombstoneKey() {
250233
return DenseMapInfo<AvailabilityDomain::Storage>::getTombstoneKey();
251234
}
235+
static inline unsigned getHashValue(AvailabilityDomain domain) {
236+
return DenseMapInfo<AvailabilityDomain::Storage>::getHashValue(
237+
domain.storage);
238+
}
252239
static bool isEqual(const AvailabilityDomain LHS,
253240
const AvailabilityDomain RHS) {
254241
return LHS == RHS;

lib/AST/Availability.cpp

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,9 +201,37 @@ void AvailabilityInference::applyInferredAvailableAttrs(
201201
Decl *ToDecl, ArrayRef<const Decl *> InferredFromDecls) {
202202
auto &Context = ToDecl->getASTContext();
203203

204+
/// A wrapper for AvailabilityDomain that implements a stable, total ordering for
205+
/// domains. This is needed to ensure that the inferred attributes are added to
206+
/// the declaration in a consistent order, preserving interface printing output
207+
/// stability across compilations.
208+
class OrderedAvailabilityDomain {
209+
public:
210+
AvailabilityDomain domain;
211+
212+
OrderedAvailabilityDomain(AvailabilityDomain domain) : domain(domain) {}
213+
214+
bool operator<(const OrderedAvailabilityDomain &other) const {
215+
auto kind = domain.getKind();
216+
auto otherKind = other.domain.getKind();
217+
if (kind != otherKind)
218+
return kind < otherKind;
219+
220+
switch (kind) {
221+
case AvailabilityDomain::Kind::Universal:
222+
case AvailabilityDomain::Kind::SwiftLanguage:
223+
case AvailabilityDomain::Kind::PackageDescription:
224+
case AvailabilityDomain::Kind::Embedded:
225+
return false;
226+
case AvailabilityDomain::Kind::Platform:
227+
return domain.getPlatformKind() < other.domain.getPlatformKind();
228+
}
229+
}
230+
};
231+
204232
// Iterate over the declarations and infer required availability on
205233
// a per-platform basis.
206-
std::map<AvailabilityDomain, InferredAvailability> Inferred;
234+
std::map<OrderedAvailabilityDomain, InferredAvailability> Inferred;
207235
for (const Decl *D : InferredFromDecls) {
208236
llvm::SmallVector<SemanticAvailableAttr, 8> MergedAttrs;
209237

@@ -238,7 +266,8 @@ void AvailabilityInference::applyInferredAvailableAttrs(
238266
// Create an availability attribute for each observed platform and add
239267
// to ToDecl.
240268
for (auto &Pair : Inferred) {
241-
if (auto Attr = createAvailableAttr(Pair.first, Pair.second, Context))
269+
if (auto Attr =
270+
createAvailableAttr(Pair.first.domain, Pair.second, Context))
242271
Attrs.add(Attr);
243272
}
244273
}

0 commit comments

Comments
 (0)