Skip to content

Commit 6c18bf2

Browse files
authored
Merge pull request #76989 from tshortli/remove-trc-explicit-availability
2 parents d3c6688 + 6bc9cf5 commit 6c18bf2

File tree

3 files changed

+74
-64
lines changed

3 files changed

+74
-64
lines changed

include/swift/AST/TypeRefinementContext.h

Lines changed: 13 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@
1818
#ifndef SWIFT_TYPEREFINEMENTCONTEXT_H
1919
#define SWIFT_TYPEREFINEMENTCONTEXT_H
2020

21-
#include "swift/AST/Identifier.h"
2221
#include "swift/AST/Availability.h"
22+
#include "swift/AST/Identifier.h"
2323
#include "swift/AST/Stmt.h" // for PoundAvailableInfo
2424
#include "swift/Basic/Debug.h"
2525
#include "swift/Basic/LLVM.h"
26-
#include "swift/Basic/SourceLoc.h"
2726
#include "swift/Basic/STLExtras.h"
27+
#include "swift/Basic/SourceLoc.h"
2828
#include "llvm/ADT/PointerUnion.h"
2929
#include "llvm/Support/ErrorHandling.h"
3030

@@ -173,11 +173,6 @@ class TypeRefinementContext : public ASTAllocated<TypeRefinementContext> {
173173
/// root context.
174174
AvailabilityRange AvailabilityInfo;
175175

176-
/// If this context was annotated with an availability attribute, this property captures that.
177-
/// It differs from the above `AvailabilityInfo` by being independent of the deployment target,
178-
/// and is used for providing availability attribute redundancy warning diagnostics.
179-
AvailabilityRange ExplicitAvailabilityInfo;
180-
181176
std::vector<TypeRefinementContext *> Children;
182177

183178
struct {
@@ -189,20 +184,18 @@ class TypeRefinementContext : public ASTAllocated<TypeRefinementContext> {
189184

190185
TypeRefinementContext(ASTContext &Ctx, IntroNode Node,
191186
TypeRefinementContext *Parent, SourceRange SrcRange,
192-
const AvailabilityRange &Info,
193-
const AvailabilityRange &ExplicitInfo);
187+
const AvailabilityRange &Info);
194188

195189
public:
196-
197190
/// Create the root refinement context for the given SourceFile.
198191
static TypeRefinementContext *
199192
createForSourceFile(SourceFile *SF, const AvailabilityRange &Info);
200193

201194
/// Create a refinement context for the given declaration.
202-
static TypeRefinementContext *
203-
createForDecl(ASTContext &Ctx, Decl *D, TypeRefinementContext *Parent,
204-
const AvailabilityRange &Info,
205-
const AvailabilityRange &ExplicitInfo, SourceRange SrcRange);
195+
static TypeRefinementContext *createForDecl(ASTContext &Ctx, Decl *D,
196+
TypeRefinementContext *Parent,
197+
const AvailabilityRange &Info,
198+
SourceRange SrcRange);
206199

207200
/// Create a refinement context for the given declaration.
208201
static TypeRefinementContext *
@@ -276,6 +269,10 @@ class TypeRefinementContext : public ASTAllocated<TypeRefinementContext> {
276269
PlatformKind Platform,
277270
const llvm::VersionTuple &Version) const;
278271

272+
/// Returns the availability version range that was explicitly written in
273+
/// source, if applicable. Otherwise, returns null.
274+
std::optional<const AvailabilityRange> getExplicitAvailabilityRange() const;
275+
279276
/// Returns the source range on which this context refines types.
280277
SourceRange getSourceRange() const { return SrcRange; }
281278

@@ -285,16 +282,10 @@ class TypeRefinementContext : public ASTAllocated<TypeRefinementContext> {
285282
return AvailabilityInfo;
286283
}
287284

288-
/// Returns the information on what availability was specified by the programmer
289-
/// on this context (if any).
290-
const AvailabilityRange &getExplicitAvailabilityInfo() const {
291-
return ExplicitAvailabilityInfo;
292-
}
293-
294285
/// Adds a child refinement context.
295286
void addChild(TypeRefinementContext *Child, ASTContext &Ctx);
296287

297-
/// Returns the inner-most TypeRefinementContext descendant of this context
288+
/// Returns the innermost TypeRefinementContext descendant of this context
298289
/// for the given source location.
299290
TypeRefinementContext *findMostRefinedSubContext(SourceLoc Loc,
300291
ASTContext &Ctx);
@@ -306,7 +297,7 @@ class TypeRefinementContext : public ASTAllocated<TypeRefinementContext> {
306297
}
307298

308299
/// Recursively check the tree for integrity. If any errors are found, emits
309-
/// diagnosticts to stderr and aborts.
300+
/// diagnostics to stderr and aborts.
310301
void verify(ASTContext &ctx);
311302

312303
SWIFT_DEBUG_DUMPER(dump(SourceManager &SrcMgr));

lib/AST/TypeRefinementContext.cpp

Lines changed: 51 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -28,12 +28,11 @@
2828

2929
using namespace swift;
3030

31-
TypeRefinementContext::TypeRefinementContext(
32-
ASTContext &Ctx, IntroNode Node, TypeRefinementContext *Parent,
33-
SourceRange SrcRange, const AvailabilityRange &Info,
34-
const AvailabilityRange &ExplicitInfo)
35-
: Node(Node), SrcRange(SrcRange), AvailabilityInfo(Info),
36-
ExplicitAvailabilityInfo(ExplicitInfo) {
31+
TypeRefinementContext::TypeRefinementContext(ASTContext &Ctx, IntroNode Node,
32+
TypeRefinementContext *Parent,
33+
SourceRange SrcRange,
34+
const AvailabilityRange &Info)
35+
: Node(Node), SrcRange(SrcRange), AvailabilityInfo(Info) {
3736
if (Parent) {
3837
assert(SrcRange.isValid());
3938
Parent->addChild(this, Ctx);
@@ -78,18 +77,15 @@ TypeRefinementContext::createForSourceFile(SourceFile *SF,
7877
}
7978

8079
return new (Ctx)
81-
TypeRefinementContext(Ctx, SF, parentContext, range, availabilityRange,
82-
AvailabilityRange::alwaysAvailable());
80+
TypeRefinementContext(Ctx, SF, parentContext, range, availabilityRange);
8381
}
8482

8583
TypeRefinementContext *TypeRefinementContext::createForDecl(
8684
ASTContext &Ctx, Decl *D, TypeRefinementContext *Parent,
87-
const AvailabilityRange &Info, const AvailabilityRange &ExplicitInfo,
88-
SourceRange SrcRange) {
85+
const AvailabilityRange &Info, SourceRange SrcRange) {
8986
assert(D);
9087
assert(Parent);
91-
return new (Ctx)
92-
TypeRefinementContext(Ctx, D, Parent, SrcRange, Info, ExplicitInfo);
88+
return new (Ctx) TypeRefinementContext(Ctx, D, Parent, SrcRange, Info);
9389
}
9490

9591
TypeRefinementContext *TypeRefinementContext::createForDeclImplicit(
@@ -98,8 +94,7 @@ TypeRefinementContext *TypeRefinementContext::createForDeclImplicit(
9894
assert(D);
9995
assert(Parent);
10096
return new (Ctx) TypeRefinementContext(
101-
Ctx, IntroNode(D, Reason::DeclImplicit), Parent, SrcRange, Info,
102-
AvailabilityRange::alwaysAvailable());
97+
Ctx, IntroNode(D, Reason::DeclImplicit), Parent, SrcRange, Info);
10398
}
10499

105100
TypeRefinementContext *
@@ -110,8 +105,7 @@ TypeRefinementContext::createForIfStmtThen(ASTContext &Ctx, IfStmt *S,
110105
assert(Parent);
111106
return new (Ctx)
112107
TypeRefinementContext(Ctx, IntroNode(S, /*IsThen=*/true), Parent,
113-
S->getThenStmt()->getSourceRange(),
114-
Info, /* ExplicitInfo */Info);
108+
S->getThenStmt()->getSourceRange(), Info);
115109
}
116110

117111
TypeRefinementContext *
@@ -122,8 +116,7 @@ TypeRefinementContext::createForIfStmtElse(ASTContext &Ctx, IfStmt *S,
122116
assert(Parent);
123117
return new (Ctx)
124118
TypeRefinementContext(Ctx, IntroNode(S, /*IsThen=*/false), Parent,
125-
S->getElseStmt()->getSourceRange(),
126-
Info, /* ExplicitInfo */Info);
119+
S->getElseStmt()->getSourceRange(), Info);
127120
}
128121

129122
TypeRefinementContext *TypeRefinementContext::createForConditionFollowingQuery(
@@ -133,8 +126,7 @@ TypeRefinementContext *TypeRefinementContext::createForConditionFollowingQuery(
133126
assert(PAI);
134127
assert(Parent);
135128
SourceRange Range(PAI->getEndLoc(), LastElement.getEndLoc());
136-
return new (Ctx) TypeRefinementContext(Ctx, PAI, Parent, Range,
137-
Info, /* ExplicitInfo */Info);
129+
return new (Ctx) TypeRefinementContext(Ctx, PAI, Parent, Range, Info);
138130
}
139131

140132
TypeRefinementContext *TypeRefinementContext::createForGuardStmtFallthrough(
@@ -144,9 +136,8 @@ TypeRefinementContext *TypeRefinementContext::createForGuardStmtFallthrough(
144136
assert(ContainingBraceStmt);
145137
assert(Parent);
146138
SourceRange Range(RS->getEndLoc(), ContainingBraceStmt->getEndLoc());
147-
return new (Ctx) TypeRefinementContext(Ctx,
148-
IntroNode(RS, /*IsFallthrough=*/true),
149-
Parent, Range, Info, /* ExplicitInfo */Info);
139+
return new (Ctx) TypeRefinementContext(
140+
Ctx, IntroNode(RS, /*IsFallthrough=*/true), Parent, Range, Info);
150141
}
151142

152143
TypeRefinementContext *
@@ -157,7 +148,7 @@ TypeRefinementContext::createForGuardStmtElse(ASTContext &Ctx, GuardStmt *RS,
157148
assert(Parent);
158149
return new (Ctx)
159150
TypeRefinementContext(Ctx, IntroNode(RS, /*IsFallthrough=*/false), Parent,
160-
RS->getBody()->getSourceRange(), Info, /* ExplicitInfo */Info);
151+
RS->getBody()->getSourceRange(), Info);
161152
}
162153

163154
TypeRefinementContext *
@@ -166,8 +157,8 @@ TypeRefinementContext::createForWhileStmtBody(ASTContext &Ctx, WhileStmt *S,
166157
const AvailabilityRange &Info) {
167158
assert(S);
168159
assert(Parent);
169-
return new (Ctx) TypeRefinementContext(
170-
Ctx, S, Parent, S->getBody()->getSourceRange(), Info, /* ExplicitInfo */Info);
160+
return new (Ctx) TypeRefinementContext(Ctx, S, Parent,
161+
S->getBody()->getSourceRange(), Info);
171162
}
172163

173164
void TypeRefinementContext::addChild(TypeRefinementContext *Child,
@@ -365,6 +356,38 @@ TypeRefinementContext::getAvailabilityConditionVersionSourceRange(
365356
llvm_unreachable("Unhandled Reason in switch.");
366357
}
367358

359+
std::optional<const AvailabilityRange>
360+
TypeRefinementContext::getExplicitAvailabilityRange() const {
361+
switch (getReason()) {
362+
case Reason::Root:
363+
return std::nullopt;
364+
365+
case Reason::Decl: {
366+
auto decl = Node.getAsDecl();
367+
auto &ctx = decl->getASTContext();
368+
if (auto attr =
369+
AvailabilityInference::attrForAnnotatedAvailableRange(decl, ctx))
370+
return AvailabilityInference::availableRange(attr, ctx);
371+
372+
return std::nullopt;
373+
}
374+
375+
case Reason::DeclImplicit:
376+
return std::nullopt;
377+
378+
case Reason::IfStmtThenBranch:
379+
case Reason::IfStmtElseBranch:
380+
case Reason::ConditionFollowingAvailabilityQuery:
381+
case Reason::GuardStmtFallthrough:
382+
case Reason::GuardStmtElseBranch:
383+
case Reason::WhileStmtBody:
384+
// Availability is inherently explicit for all of these nodes.
385+
return getAvailabilityInfo();
386+
}
387+
388+
llvm_unreachable("Unhandled Reason in switch.");
389+
}
390+
368391
static std::string
369392
stringForAvailability(const AvailabilityRange &availability) {
370393
if (availability.isAlwaysAvailable())
@@ -425,9 +448,8 @@ void TypeRefinementContext::print(raw_ostream &OS, SourceManager &SrcMgr,
425448
}
426449
}
427450

428-
if (!ExplicitAvailabilityInfo.isAlwaysAvailable())
429-
OS << " explicit_version="
430-
<< stringForAvailability(ExplicitAvailabilityInfo);
451+
if (auto explicitAvailability = getExplicitAvailabilityRange())
452+
OS << " explicit_version=" << stringForAvailability(*explicitAvailability);
431453

432454
for (TypeRefinementContext *Child : Children) {
433455
OS << '\n';

lib/Sema/TypeCheckAvailability.cpp

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -689,14 +689,13 @@ class TypeRefinementContextBuilder : private ASTWalker {
689689
return nullptr;
690690

691691
// Declarations with an explicit availability attribute always get a TRC.
692-
if (hasActiveAvailableAttribute(D, Context)) {
693-
AvailabilityRange DeclaredAvailability =
694-
swift::AvailabilityInference::availableRange(D, Context);
695-
692+
AvailabilityRange DeclaredAvailability =
693+
swift::AvailabilityInference::availableRange(D, Context);
694+
if (!DeclaredAvailability.isAlwaysAvailable()) {
696695
return TypeRefinementContext::createForDecl(
697696
Context, D, getCurrentTRC(),
698697
getEffectiveAvailabilityForDeclSignature(D, DeclaredAvailability),
699-
DeclaredAvailability, refinementSourceRangeForDecl(D));
698+
refinementSourceRangeForDecl(D));
700699
}
701700

702701
// Declarations without explicit availability get a TRC if they are
@@ -1096,8 +1095,6 @@ class TypeRefinementContextBuilder : private ASTWalker {
10961095
for (StmtConditionElement Element : Cond) {
10971096
TypeRefinementContext *CurrentTRC = getCurrentTRC();
10981097
AvailabilityRange CurrentInfo = CurrentTRC->getAvailabilityInfo();
1099-
AvailabilityRange CurrentExplicitInfo =
1100-
CurrentTRC->getExplicitAvailabilityInfo();
11011098

11021099
// If the element is not a condition, walk it in the current TRC.
11031100
if (Element.getKind() != StmtConditionElement::CK_Availability) {
@@ -1178,7 +1175,8 @@ class TypeRefinementContextBuilder : private ASTWalker {
11781175
// current TRC is completely contained in the range for the spec, then
11791176
// a version query can never be false, so the spec is useless.
11801177
// If so, report this.
1181-
if (CurrentExplicitInfo.isContainedIn(NewConstraint)) {
1178+
auto ExplicitRange = CurrentTRC->getExplicitAvailabilityRange();
1179+
if (ExplicitRange && ExplicitRange->isContainedIn(NewConstraint)) {
11821180
// Unavailability refinements are always "useless" from a symbol
11831181
// availability point of view, so only useless availability specs are
11841182
// reported.
@@ -1939,16 +1937,15 @@ static bool fixAvailabilityByNarrowingNearbyVersionCheck(
19391937
if (!TRC)
19401938
return false;
19411939

1942-
AvailabilityRange AvailabilityAtLoc = TRC->getExplicitAvailabilityInfo();
1943-
if (!AvailabilityAtLoc.isAlwaysAvailable() &&
1944-
!RequiredAvailability.isAlwaysAvailable() &&
1940+
auto ExplicitAvailability = TRC->getExplicitAvailabilityRange();
1941+
if (ExplicitAvailability && !RequiredAvailability.isAlwaysAvailable() &&
19451942
TRC->getReason() != TypeRefinementContext::Reason::Root &&
1946-
RequiredAvailability.isContainedIn(AvailabilityAtLoc)) {
1943+
RequiredAvailability.isContainedIn(*ExplicitAvailability)) {
19471944

19481945
// Only fix situations that are "nearby" versions, meaning
19491946
// disagreement on a minor-or-less version (subminor-or-less version for
19501947
// macOS 10.x.y).
1951-
auto RunningVers = AvailabilityAtLoc.getRawMinimumVersion();
1948+
auto RunningVers = ExplicitAvailability->getRawMinimumVersion();
19521949
auto RequiredVers = RequiredAvailability.getRawMinimumVersion();
19531950
auto Platform = targetPlatform(Context.LangOpts);
19541951
if (RunningVers.getMajor() != RequiredVers.getMajor())

0 commit comments

Comments
 (0)