Skip to content

Commit 009ff8a

Browse files
authored
Merge pull request swiftlang#77144 from tshortli/expand-availability-context
AST: Refactor AvailabilityContext into a value type
2 parents d84b23b + b346385 commit 009ff8a

11 files changed

+446
-163
lines changed

include/swift/AST/Availability.h

-72
Original file line numberDiff line numberDiff line change
@@ -335,78 +335,6 @@ class AvailabilityRange {
335335
}
336336
};
337337

338-
/// An `AvailabilityContext` summarizes the availability constraints for a
339-
/// specific scope, such as within a declaration or at a particular source
340-
/// location in a function body. This context is sufficient to determine whether
341-
/// a declaration is available or not in that scope.
342-
class AvailabilityContext : public llvm::FoldingSetNode {
343-
/// Summarizes platform specific availability constraints.
344-
struct PlatformInfo {
345-
/// The introduction version.
346-
AvailabilityRange Range;
347-
348-
/// Sets `Range` to `other` if `other` is more restrictive. Returns true if
349-
/// any property changed as a result of adding this constraint.
350-
bool constrainRange(const AvailabilityRange &other) {
351-
if (!other.isContainedIn(Range))
352-
return false;
353-
354-
Range = other;
355-
return true;
356-
}
357-
358-
/// Sets `Range` to the platform introduction range of `decl` if that range
359-
/// is more restrictive. Returns true if
360-
/// any property changed as a result of adding this constraint.
361-
bool constrainRange(const Decl *decl);
362-
363-
void Profile(llvm::FoldingSetNodeID &ID) const {
364-
Range.getRawVersionRange().Profile(ID);
365-
}
366-
};
367-
PlatformInfo PlatformAvailability;
368-
369-
AvailabilityContext(const PlatformInfo &platformInfo)
370-
: PlatformAvailability(platformInfo){};
371-
372-
static const AvailabilityContext *get(const PlatformInfo &platformInfo,
373-
ASTContext &ctx);
374-
375-
public:
376-
/// Retrieves the default `AvailabilityContext`, which is maximally available.
377-
/// The platform availability range will be set to the deployment target (or
378-
/// minimum inlining target when applicable).
379-
static const AvailabilityContext *getDefault(ASTContext &ctx);
380-
381-
/// Retrieves a uniqued `AvailabilityContext` with the given platform
382-
/// availability parameters.
383-
static const AvailabilityContext *
384-
get(const AvailabilityRange &platformAvailability, ASTContext &ctx) {
385-
PlatformInfo platformInfo{platformAvailability};
386-
return get(platformInfo, ctx);
387-
}
388-
389-
/// Returns the range of platform versions which may execute code in the
390-
/// availability context, starting at its introduction version.
391-
AvailabilityRange getPlatformRange() const {
392-
return PlatformAvailability.Range;
393-
}
394-
395-
/// Returns the unique context that is the result of constraining the current
396-
/// context's platform availability range with `platformRange`.
397-
const AvailabilityContext *
398-
constrainWithPlatformRange(const AvailabilityRange &platformRange,
399-
ASTContext &ctx) const;
400-
401-
/// Returns the unique context that is the result of constraining the current
402-
/// context both with the availability attributes of `decl` and with
403-
/// `platformRange`.
404-
const AvailabilityContext *constrainWithDeclAndPlatformRange(
405-
Decl *decl, const AvailabilityRange &platformRange) const;
406-
407-
void Profile(llvm::FoldingSetNodeID &ID) const;
408-
};
409-
410338
class AvailabilityInference {
411339
public:
412340
/// Returns the decl that should be considered the parent decl of the given
+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
//===--- AvailabilityContext.h - Swift Availability Structures --*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines the AvailabilityContext data structure, which summarizes
14+
// availability constraints for a specific scope.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
#ifndef SWIFT_AST_AVAILABILITY_CONTEXT_H
19+
#define SWIFT_AST_AVAILABILITY_CONTEXT_H
20+
21+
#include "swift/AST/Availability.h"
22+
#include "swift/AST/PlatformKind.h"
23+
#include "swift/Basic/LLVM.h"
24+
#include <optional>
25+
26+
namespace swift {
27+
class ASTContext;
28+
class AvailableAttr;
29+
class Decl;
30+
31+
/// An `AvailabilityContext` summarizes the availability constraints for a
32+
/// specific scope, such as within a declaration or at a particular source
33+
/// location in a function body. This context is sufficient to determine whether
34+
/// a declaration is available or not in that scope.
35+
class AvailabilityContext {
36+
public:
37+
class Storage;
38+
39+
private:
40+
struct PlatformInfo;
41+
42+
/// A non-null pointer to uniqued storage for this availability context.
43+
const Storage *Info;
44+
45+
AvailabilityContext(const Storage *info) : Info(info) { assert(info); };
46+
47+
public:
48+
AvailabilityContext(const AvailabilityContext &other) : Info(other.Info){};
49+
50+
/// Retrieves the default `AvailabilityContext`, which is maximally available.
51+
/// The platform availability range will be set to the deployment target (or
52+
/// minimum inlining target when applicable).
53+
static AvailabilityContext getDefault(ASTContext &ctx);
54+
55+
/// Retrieves a uniqued `AvailabilityContext` with the given platform
56+
/// availability parameters.
57+
static AvailabilityContext
58+
get(const AvailabilityRange &platformAvailability,
59+
std::optional<PlatformKind> unavailablePlatform, bool deprecated,
60+
ASTContext &ctx);
61+
62+
/// Returns the range of platform versions which may execute code in the
63+
/// availability context, starting at its introduction version.
64+
AvailabilityRange getPlatformRange() const;
65+
66+
/// When the context is unavailable on the current platform this returns the
67+
/// broadest `PlatformKind` for which the context is unavailable. Otherwise,
68+
/// returns `nullopt`.
69+
std::optional<PlatformKind> getUnavailablePlatformKind() const;
70+
71+
/// Returns true if this context is deprecated on the current platform.
72+
bool isDeprecated() const;
73+
74+
/// Constrain the platform availability range with `platformRange`.
75+
void constrainWithPlatformRange(const AvailabilityRange &platformRange,
76+
ASTContext &ctx);
77+
78+
/// Constrain the platform availability range with both the availability
79+
/// attributes of `decl` and with `platformRange`.
80+
void
81+
constrainWithDeclAndPlatformRange(Decl *decl,
82+
const AvailabilityRange &platformRange);
83+
84+
/// Returns true if `other` is as available or is more available.
85+
bool isContainedIn(const AvailabilityContext other) const;
86+
87+
friend bool operator==(const AvailabilityContext &lhs,
88+
const AvailabilityContext &rhs) {
89+
return lhs.Info == rhs.Info;
90+
}
91+
92+
friend bool operator!=(const AvailabilityContext &lhs,
93+
const AvailabilityContext &rhs) {
94+
return lhs.Info != rhs.Info;
95+
}
96+
97+
void print(llvm::raw_ostream &os) const;
98+
SWIFT_DEBUG_DUMP;
99+
};
100+
101+
} // end namespace swift
102+
103+
#endif
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
//===--- AvailabilityContextStorage.h - Swift AvailabilityContext ---------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2024 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines types used in the implementation of AvailabilityContext.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_AST_AVAILABILITY_CONTEXT_STORAGE_H
18+
#define SWIFT_AST_AVAILABILITY_CONTEXT_STORAGE_H
19+
20+
#include "swift/AST/AvailabilityContext.h"
21+
#include "llvm/ADT/FoldingSet.h"
22+
#include <optional>
23+
24+
namespace swift {
25+
26+
/// Summarizes platform specific availability constraints.
27+
struct AvailabilityContext::PlatformInfo {
28+
/// The introduction version.
29+
AvailabilityRange Range;
30+
31+
/// When `IsUnavailable` is true, this value stores the broadest platform
32+
/// kind for which the context is unavailable.
33+
PlatformKind UnavailablePlatform;
34+
35+
/// Whether or not the context is considered unavailable on the current
36+
/// platform.
37+
unsigned IsUnavailable : 1;
38+
39+
/// Whether or not the context is considered deprecated on the current
40+
/// platform.
41+
unsigned IsDeprecated : 1;
42+
43+
/// Sets `Range` to `other` if `other` is more restrictive. Returns true if
44+
/// any property changed as a result of adding this constraint.
45+
bool constrainRange(const AvailabilityRange &other) {
46+
if (!other.isContainedIn(Range))
47+
return false;
48+
49+
Range = other;
50+
return true;
51+
}
52+
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);
62+
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);
66+
67+
/// Returns true if `other` is as available or is more available.
68+
bool isContainedIn(const PlatformInfo &other) const;
69+
70+
void Profile(llvm::FoldingSetNodeID &ID) const {
71+
Range.getRawVersionRange().Profile(ID);
72+
ID.AddBoolean(IsUnavailable);
73+
ID.AddInteger(static_cast<uint8_t>(UnavailablePlatform));
74+
ID.AddBoolean(IsDeprecated);
75+
}
76+
};
77+
78+
/// As an implementation detail, the values that make up an `Availability`
79+
/// context are uniqued and stored as folding set nodes.
80+
class AvailabilityContext::Storage final : public llvm::FoldingSetNode {
81+
Storage(const PlatformInfo &platformInfo) : Platform(platformInfo){};
82+
83+
public:
84+
PlatformInfo Platform;
85+
86+
static const Storage *get(const PlatformInfo &platformInfo, ASTContext &ctx);
87+
88+
void Profile(llvm::FoldingSetNodeID &ID) const;
89+
};
90+
91+
} // end namespace swift
92+
93+
#endif

include/swift/AST/TypeRefinementContext.h

+14-13
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#define SWIFT_TYPEREFINEMENTCONTEXT_H
2020

2121
#include "swift/AST/Availability.h"
22+
#include "swift/AST/AvailabilityContext.h"
2223
#include "swift/AST/Identifier.h"
2324
#include "swift/AST/Stmt.h" // for PoundAvailableInfo
2425
#include "swift/Basic/Debug.h"
@@ -171,7 +172,7 @@ class TypeRefinementContext : public ASTAllocated<TypeRefinementContext> {
171172

172173
/// A canonical availability info for this context, computed top-down from the
173174
/// root context.
174-
const AvailabilityContext *AvailabilityInfo;
175+
const AvailabilityContext AvailabilityInfo;
175176

176177
std::vector<TypeRefinementContext *> Children;
177178

@@ -184,33 +185,33 @@ class TypeRefinementContext : public ASTAllocated<TypeRefinementContext> {
184185

185186
TypeRefinementContext(ASTContext &Ctx, IntroNode Node,
186187
TypeRefinementContext *Parent, SourceRange SrcRange,
187-
const AvailabilityContext *Info);
188+
const AvailabilityContext Info);
188189

189190
public:
190191
/// Create the root refinement context for the given SourceFile.
191192
static TypeRefinementContext *
192-
createForSourceFile(SourceFile *SF, const AvailabilityContext *Info);
193+
createForSourceFile(SourceFile *SF, const AvailabilityContext Info);
193194

194195
/// Create a refinement context for the given declaration.
195196
static TypeRefinementContext *createForDecl(ASTContext &Ctx, Decl *D,
196197
TypeRefinementContext *Parent,
197-
const AvailabilityContext *Info,
198+
const AvailabilityContext Info,
198199
SourceRange SrcRange);
199200

200201
/// Create a refinement context for the given declaration.
201202
static TypeRefinementContext *
202203
createForDeclImplicit(ASTContext &Ctx, Decl *D, TypeRefinementContext *Parent,
203-
const AvailabilityContext *Info, SourceRange SrcRange);
204+
const AvailabilityContext Info, SourceRange SrcRange);
204205

205206
/// Create a refinement context for the Then branch of the given IfStmt.
206207
static TypeRefinementContext *
207208
createForIfStmtThen(ASTContext &Ctx, IfStmt *S, TypeRefinementContext *Parent,
208-
const AvailabilityContext *Info);
209+
const AvailabilityContext Info);
209210

210211
/// Create a refinement context for the Else branch of the given IfStmt.
211212
static TypeRefinementContext *
212213
createForIfStmtElse(ASTContext &Ctx, IfStmt *S, TypeRefinementContext *Parent,
213-
const AvailabilityContext *Info);
214+
const AvailabilityContext Info);
214215

215216
/// Create a refinement context for the true-branch control flow to
216217
/// further StmtConditionElements following a #available() query in
@@ -219,24 +220,24 @@ class TypeRefinementContext : public ASTAllocated<TypeRefinementContext> {
219220
createForConditionFollowingQuery(ASTContext &Ctx, PoundAvailableInfo *PAI,
220221
const StmtConditionElement &LastElement,
221222
TypeRefinementContext *Parent,
222-
const AvailabilityContext *Info);
223+
const AvailabilityContext Info);
223224

224225
/// Create a refinement context for the fallthrough of a GuardStmt.
225226
static TypeRefinementContext *createForGuardStmtFallthrough(
226227
ASTContext &Ctx, GuardStmt *RS, BraceStmt *ContainingBraceStmt,
227-
TypeRefinementContext *Parent, const AvailabilityContext *Info);
228+
TypeRefinementContext *Parent, const AvailabilityContext Info);
228229

229230
/// Create a refinement context for the else branch of a GuardStmt.
230231
static TypeRefinementContext *
231232
createForGuardStmtElse(ASTContext &Ctx, GuardStmt *RS,
232233
TypeRefinementContext *Parent,
233-
const AvailabilityContext *Info);
234+
const AvailabilityContext Info);
234235

235236
/// Create a refinement context for the body of a WhileStmt.
236237
static TypeRefinementContext *
237238
createForWhileStmtBody(ASTContext &Ctx, WhileStmt *WS,
238239
TypeRefinementContext *Parent,
239-
const AvailabilityContext *Info);
240+
const AvailabilityContext Info);
240241

241242
Decl *getDeclOrNull() const {
242243
auto IntroReason = getReason();
@@ -277,14 +278,14 @@ class TypeRefinementContext : public ASTAllocated<TypeRefinementContext> {
277278
SourceRange getSourceRange() const { return SrcRange; }
278279

279280
/// Returns the availability context of code contained in this context.
280-
const AvailabilityContext *getAvailabilityContext() const {
281+
const AvailabilityContext getAvailabilityContext() const {
281282
return AvailabilityInfo;
282283
}
283284

284285
/// Returns the platform version range that can be assumed present at run
285286
/// time when running code contained in this context.
286287
const AvailabilityRange getPlatformAvailabilityRange() const {
287-
return AvailabilityInfo->getPlatformRange();
288+
return AvailabilityInfo.getPlatformRange();
288289
}
289290

290291
/// Adds a child refinement context.

0 commit comments

Comments
 (0)