Skip to content

Commit 3d96990

Browse files
committed
Merge remote-tracking branch 'origin/main' into rebranch
2 parents 6bbdf7d + cd25c00 commit 3d96990

15 files changed

+274
-169
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;

include/swift/SIL/MemAccessUtils.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1650,6 +1650,21 @@ inline bool isAccessStorageIdentityCast(SingleValueInstruction *svi) {
16501650
}
16511651
}
16521652

1653+
// Strip access markers and casts that preserve the address type.
1654+
//
1655+
// Consider using RelativeAccessStorageWithBase::compute().
1656+
inline SILValue stripAccessAndIdentityCasts(SILValue v) {
1657+
if (auto *bai = dyn_cast<BeginAccessInst>(v)) {
1658+
return stripAccessAndIdentityCasts(bai->getOperand());
1659+
}
1660+
if (auto *svi = dyn_cast<SingleValueInstruction>(v)) {
1661+
if (isAccessStorageIdentityCast(svi)) {
1662+
return stripAccessAndIdentityCasts(svi->getAllOperands()[0].get());
1663+
}
1664+
}
1665+
return v;
1666+
}
1667+
16531668
/// An address, pointer, or box cast that occurs outside of the formal
16541669
/// access. These convert the base of accessed storage without affecting the
16551670
/// AccessPath. Useful for both use-def and def-use traversal. The source

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;

lib/SILOptimizer/Mandatory/MoveOnlyAddressCheckerUtils.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2379,7 +2379,7 @@ bool GatherUsesVisitor::visitUse(Operand *op) {
23792379
if (moveChecker.canonicalizer.foundAnyConsumingUses()) {
23802380
LLVM_DEBUG(llvm::dbgs()
23812381
<< "Found mark must check [nocopy] error: " << *user);
2382-
auto operand = stripAccessMarkers(markedValue->getOperand());
2382+
auto operand = stripAccessAndIdentityCasts(markedValue->getOperand());
23832383
auto *fArg = dyn_cast<SILFunctionArgument>(operand);
23842384
auto *ptrToAddr = dyn_cast<PointerToAddressInst>(operand);
23852385

lib/SILOptimizer/Mandatory/MoveOnlyBorrowToDestructureUtils.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,6 +1540,12 @@ static bool gatherBorrows(SILValue rootValue,
15401540
// escape. Is it legal to canonicalize ForwardingUnowned?
15411541
case OperandOwnership::ForwardingUnowned:
15421542
case OperandOwnership::PointerEscape:
1543+
if (auto *md = dyn_cast<MarkDependenceInst>(use->getUser())) {
1544+
// mark_depenence uses only keep its base value alive; they do not use
1545+
// the base value itself and are irrelevant for destructuring.
1546+
if (use == &md->getOperandRef(MarkDependenceInst::Base))
1547+
continue;
1548+
}
15431549
return false;
15441550

15451551
case OperandOwnership::InstantaneousUse:

lib/SILOptimizer/Mandatory/MoveOnlyObjectCheckerUtils.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -219,15 +219,12 @@ bool MoveOnlyObjectCheckerPImpl::checkForSameInstMultipleUseErrors(
219219
case OperandOwnership::NonUse:
220220
continue;
221221

222-
// Conservatively treat a conversion to an unowned value as a pointer
223-
// escape. If we see this in the SIL, fail and return false so we emit a
224-
// "compiler doesn't understand error".
225222
case OperandOwnership::ForwardingUnowned:
226223
case OperandOwnership::PointerEscape:
227224
case OperandOwnership::BitwiseEscape:
228-
LLVM_DEBUG(llvm::dbgs()
229-
<< " Found forwarding unowned or escape!\n");
230-
return false;
225+
// None of the "unowned" uses can consume the original value. Simply
226+
// ignore them.
227+
continue;
231228

232229
case OperandOwnership::TrivialUse:
233230
case OperandOwnership::InstantaneousUse:

lib/SILOptimizer/Utils/VariableNameUtils.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,7 @@ SILValue VariableNameInferrer::findDebugInfoProvidingValueHelper(
642642
isa<ProjectBoxInst>(searchValue) || isa<CopyValueInst>(searchValue) ||
643643
isa<ConvertFunctionInst>(searchValue) ||
644644
isa<MarkUninitializedInst>(searchValue) ||
645+
isa<MarkDependenceInst>(searchValue) ||
645646
isa<CopyableToMoveOnlyWrapperAddrInst>(searchValue) ||
646647
isa<MoveOnlyWrapperToCopyableAddrInst>(searchValue) ||
647648
isa<MoveOnlyWrapperToCopyableValueInst>(searchValue) ||

0 commit comments

Comments
 (0)