Skip to content

Commit 1c99f31

Browse files
committed
Basic motions towards moving yields into AnyFunctionType.
Still not intending to do this anytime soon.
1 parent 5d8252b commit 1c99f31

File tree

3 files changed

+145
-26
lines changed

3 files changed

+145
-26
lines changed

include/swift/AST/AnyFunctionRef.h

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -83,29 +83,14 @@ class AnyFunctionRef {
8383
return TheFunction.get<AbstractClosureExpr *>()->getResultType();
8484
}
8585

86-
struct YieldResult {
87-
Type Ty;
88-
VarDecl::Specifier Specifier;
89-
};
86+
ArrayRef<AnyFunctionType::Yield>
87+
getYieldResults(SmallVectorImpl<AnyFunctionType::Yield> &buffer) const {
88+
return getYieldResultsImpl(buffer, /*mapIntoContext*/ false);
89+
}
9090

91-
ArrayRef<YieldResult>
92-
getBodyYieldResults(SmallVectorImpl<YieldResult> &buffer) const {
93-
assert(buffer.empty());
94-
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
95-
if (auto *AD = dyn_cast<AccessorDecl>(AFD)) {
96-
if (AD->isCoroutine()) {
97-
auto valueTy = AD->getStorage()->getValueInterfaceType();
98-
valueTy = AD->mapTypeIntoContext(valueTy);
99-
auto specifier =
100-
AD->getAccessorKind() == AccessorKind::Modify
101-
? VarDecl::Specifier::InOut
102-
: VarDecl::Specifier::Shared;
103-
buffer.push_back({valueTy, specifier});
104-
return buffer;
105-
}
106-
}
107-
}
108-
return {};
91+
ArrayRef<AnyFunctionType::Yield>
92+
getBodyYieldResults(SmallVectorImpl<AnyFunctionType::Yield> &buffer) const {
93+
return getYieldResultsImpl(buffer, /*mapIntoContext*/ true);
10994
}
11095

11196
BraceStmt *getBody() const {
@@ -196,6 +181,28 @@ class AnyFunctionRef {
196181
}
197182
llvm_unreachable("unexpected AnyFunctionRef representation");
198183
}
184+
185+
private:
186+
ArrayRef<AnyFunctionType::Yield>
187+
getYieldResultsImpl(SmallVectorImpl<AnyFunctionType::Yield> &buffer,
188+
bool mapIntoContext) const {
189+
assert(buffer.empty());
190+
if (auto *AFD = TheFunction.dyn_cast<AbstractFunctionDecl *>()) {
191+
if (auto *AD = dyn_cast<AccessorDecl>(AFD)) {
192+
if (AD->isCoroutine()) {
193+
auto valueTy = AD->getStorage()->getValueInterfaceType();
194+
if (mapIntoContext)
195+
valueTy = AD->mapTypeIntoContext(valueTy);
196+
YieldTypeFlags flags(AD->getAccessorKind() == AccessorKind::Modify
197+
? ValueOwnership::InOut
198+
: ValueOwnership::Shared);
199+
buffer.push_back(AnyFunctionType::Yield(valueTy, flags));
200+
return buffer;
201+
}
202+
}
203+
}
204+
return {};
205+
}
199206
};
200207
#if SWIFT_COMPILER_IS_MSVC
201208
#pragma warning(pop)

include/swift/AST/Types.h

Lines changed: 113 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1745,6 +1745,70 @@ class ParameterTypeFlags {
17451745
uint8_t toRaw() const { return value.toRaw(); }
17461746
};
17471747

1748+
class YieldTypeFlags {
1749+
enum YieldFlags : uint8_t {
1750+
None = 0,
1751+
InOut = 1 << 1,
1752+
Shared = 1 << 2,
1753+
Owned = 1 << 3,
1754+
1755+
NumBits = 3
1756+
};
1757+
OptionSet<YieldFlags> value;
1758+
1759+
static_assert(NumBits < 8 * sizeof(OptionSet<YieldFlags>), "overflowed");
1760+
1761+
YieldTypeFlags(OptionSet<YieldFlags, uint8_t> val) : value(val) {}
1762+
1763+
public:
1764+
YieldTypeFlags() = default;
1765+
static YieldTypeFlags fromRaw(uint8_t raw) {
1766+
return YieldTypeFlags(OptionSet<YieldFlags>(raw));
1767+
}
1768+
1769+
YieldTypeFlags(ValueOwnership ownership)
1770+
: value((ownership == ValueOwnership::InOut ? InOut : 0) |
1771+
(ownership == ValueOwnership::Shared ? Shared : 0) |
1772+
(ownership == ValueOwnership::Owned ? Owned : 0)) {}
1773+
1774+
bool isInOut() const { return value.contains(InOut); }
1775+
bool isShared() const { return value.contains(Shared); }
1776+
bool isOwned() const { return value.contains(Owned); }
1777+
1778+
ValueOwnership getValueOwnership() const {
1779+
if (isInOut())
1780+
return ValueOwnership::InOut;
1781+
else if (isShared())
1782+
return ValueOwnership::Shared;
1783+
else if (isOwned())
1784+
return ValueOwnership::Owned;
1785+
1786+
return ValueOwnership::Default;
1787+
}
1788+
1789+
YieldTypeFlags withInOut(bool isInout) const {
1790+
return YieldTypeFlags(isInout ? value | InOut : value - InOut);
1791+
}
1792+
1793+
YieldTypeFlags withShared(bool isShared) const {
1794+
return YieldTypeFlags(isShared ? value | Shared : value - Shared);
1795+
}
1796+
1797+
YieldTypeFlags withOwned(bool isOwned) const {
1798+
return YieldTypeFlags(isOwned ? value | Owned : value - Owned);
1799+
}
1800+
1801+
bool operator ==(const YieldTypeFlags &other) const {
1802+
return value.toRaw() == other.value.toRaw();
1803+
}
1804+
1805+
bool operator!=(const YieldTypeFlags &other) const {
1806+
return value.toRaw() != other.value.toRaw();
1807+
}
1808+
1809+
uint8_t toRaw() const { return value.toRaw(); }
1810+
};
1811+
17481812
/// ParenType - A paren type is a type that's been written in parentheses.
17491813
class ParenType : public SugarType {
17501814
friend class ASTContext;
@@ -2560,7 +2624,7 @@ class AnyFunctionType : public TypeBase {
25602624

25612625
public:
25622626
using Representation = FunctionTypeRepresentation;
2563-
2627+
25642628
class Param {
25652629
public:
25662630
explicit Param(const TupleTypeElt &tte);
@@ -2635,6 +2699,50 @@ class AnyFunctionType : public TypeBase {
26352699
using CanParamArrayRef =
26362700
ArrayRefView<Param,CanParam,CanParam::getFromParam,/*AccessOriginal*/true>;
26372701

2702+
class CanYield;
2703+
class Yield {
2704+
Type Ty;
2705+
YieldTypeFlags Flags;
2706+
public:
2707+
explicit Yield(Type type, YieldTypeFlags flags)
2708+
: Ty(type), Flags(flags) {}
2709+
2710+
Type getType() const { return Ty; }
2711+
2712+
YieldTypeFlags getFlags() const { return Flags; }
2713+
ValueOwnership getValueOwnership() const {
2714+
return getFlags().getValueOwnership();
2715+
}
2716+
bool isInOut() const { return getFlags().isInOut(); }
2717+
2718+
CanYield getCanonical() const;
2719+
2720+
Yield subst(SubstitutionMap subs, SubstOptions options = None) const {
2721+
return Yield(getType().subst(subs, options), getFlags());
2722+
}
2723+
2724+
bool operator==(const Yield &other) const {
2725+
return getType()->isEqual(other.getType()) &&
2726+
getFlags() == other.getFlags();
2727+
}
2728+
bool operator!=(const Yield &other) const {
2729+
return !operator==(other);
2730+
}
2731+
};
2732+
2733+
class CanYield : public Yield {
2734+
public:
2735+
explicit CanYield(CanType type, YieldTypeFlags flags)
2736+
: Yield(type, flags) {}
2737+
2738+
CanType getType() const { return CanType(Yield::getType()); }
2739+
2740+
CanYield subst(SubstitutionMap subs, SubstOptions options = None) const {
2741+
return CanYield(getType().subst(subs, options)->getCanonicalType(),
2742+
getFlags());
2743+
}
2744+
};
2745+
26382746
/// \brief A class which abstracts out some details necessary for
26392747
/// making a call.
26402748
class ExtInfo {
@@ -2896,6 +3004,10 @@ BEGIN_CAN_TYPE_WRAPPER(AnyFunctionType, Type)
28963004
}
28973005
END_CAN_TYPE_WRAPPER(AnyFunctionType, Type)
28983006

3007+
inline AnyFunctionType::CanYield AnyFunctionType::Yield::getCanonical() const {
3008+
return CanYield(getType()->getCanonicalType(), getFlags());
3009+
}
3010+
28993011
/// FunctionType - A monomorphic function type, specified with an arrow.
29003012
///
29013013
/// For example:

lib/Sema/TypeCheckStmt.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -482,7 +482,7 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
482482
return YS;
483483
}
484484

485-
SmallVector<AnyFunctionRef::YieldResult, 4> buffer;
485+
SmallVector<AnyFunctionType::Yield, 4> buffer;
486486
auto yieldResults = TheFunc->getBodyYieldResults(buffer);
487487

488488
auto yieldExprs = YS->getMutableYields();
@@ -493,15 +493,15 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
493493
}
494494

495495
for (auto i : indices(yieldExprs)) {
496-
Type yieldType = yieldResults[i].Ty;
496+
Type yieldType = yieldResults[i].getType();
497497
auto exprToCheck = yieldExprs[i];
498498

499499
InOutExpr *inout = nullptr;
500500

501501
// Classify whether we're yielding by reference or by value.
502502
ContextualTypePurpose contextTypePurpose;
503503
Type contextType = yieldType;
504-
if (yieldResults[i].Specifier == VarDecl::Specifier::InOut) {
504+
if (yieldResults[i].isInOut()) {
505505
contextTypePurpose = CTP_YieldByReference;
506506
contextType = LValueType::get(contextType);
507507

0 commit comments

Comments
 (0)