Skip to content

Commit 0cc5297

Browse files
authored
Merge pull request #70635 from DougGregor/async-sequence-typed-throws
Adopt typed throws in AsyncIteratorProtocol and AsyncSequence
2 parents 8f4adb3 + 4c990dc commit 0cc5297

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+1312
-87
lines changed

include/swift/AST/ASTContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -650,6 +650,9 @@ class ASTContext final {
650650
/// Get AsyncIteratorProtocol.next().
651651
FuncDecl *getAsyncIteratorNext() const;
652652

653+
/// Get AsyncIteratorProtocol.next(actor).
654+
FuncDecl *getAsyncIteratorNextIsolated() const;
655+
653656
/// Check whether the standard library provides all the correct
654657
/// intrinsic support for Optional<T>.
655658
///

include/swift/AST/Effects.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ enum class PolymorphicEffectKind : uint8_t {
8787
/// This is the conformance-based 'rethrows' /'reasync' case.
8888
ByConformance,
8989

90+
/// The function is only permitted to be `rethrows` because it depends
91+
/// on a conformance to `AsyncSequence` or `AsyncIteratorProtocol`,
92+
/// which historically were "@rethrows" protocols.
93+
AsyncSequenceRethrows,
94+
9095
/// The function has this effect unconditionally.
9196
///
9297
/// This is a plain old 'throws' / 'async' function.

include/swift/AST/KnownIdentifiers.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ IDENTIFIER(enqueue)
9090
IDENTIFIER(erasing)
9191
IDENTIFIER(error)
9292
IDENTIFIER(errorDomain)
93+
IDENTIFIER(Failure)
9394
IDENTIFIER(first)
9495
IDENTIFIER(forKeyedSubscript)
9596
IDENTIFIER(Foundation)

include/swift/AST/Stmt.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -971,6 +971,7 @@ class ForEachStmt : public LabeledStmt {
971971

972972
// Set by Sema:
973973
ProtocolConformanceRef sequenceConformance = ProtocolConformanceRef();
974+
Type sequenceType;
974975
PatternBindingDecl *iteratorVar = nullptr;
975976
Expr *nextCall = nullptr;
976977
OpaqueValueExpr *elementExpr = nullptr;
@@ -1001,9 +1002,12 @@ class ForEachStmt : public LabeledStmt {
10011002
void setConvertElementExpr(Expr *expr) { convertElementExpr = expr; }
10021003
Expr *getConvertElementExpr() const { return convertElementExpr; }
10031004

1004-
void setSequenceConformance(ProtocolConformanceRef conformance) {
1005+
void setSequenceConformance(Type type,
1006+
ProtocolConformanceRef conformance) {
1007+
sequenceType = type;
10051008
sequenceConformance = conformance;
10061009
}
1010+
Type getSequenceType() const { return sequenceType; }
10071011
ProtocolConformanceRef getSequenceConformance() const {
10081012
return sequenceConformance;
10091013
}

include/swift/SILOptimizer/Analysis/RegionAnalysis.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,11 @@ class RegionAnalysisValueMap {
299299
/// This only includes function arguments.
300300
std::vector<TrackableValueID> neverTransferredValueIDs;
301301

302+
SILFunction *fn;
303+
302304
public:
305+
RegionAnalysisValueMap(SILFunction *fn) : fn(fn) { }
306+
303307
/// Returns the value for this instruction if it isn't a fake "represenative
304308
/// value" to inject actor isolatedness. Asserts in such a case.
305309
SILValue getRepresentative(Element trackableValueID) const;

lib/AST/ASTContext.cpp

Lines changed: 38 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,10 @@ struct ASTContext::Implementation {
287287
/// The declaration of 'AsyncIteratorProtocol.next()'.
288288
FuncDecl *AsyncIteratorNext = nullptr;
289289

290+
/// The declaration of 'AsyncIteratorProtocol.next(_:)' that takes
291+
/// an actor isolation.
292+
FuncDecl *AsyncIteratorNextIsolated = nullptr;
293+
290294
/// The declaration of Swift.Optional<T>.Some.
291295
EnumElementDecl *OptionalSomeDecl = nullptr;
292296

@@ -948,21 +952,48 @@ FuncDecl *ASTContext::getIteratorNext() const {
948952
return nullptr;
949953
}
950954

955+
static std::pair<FuncDecl *, FuncDecl *>
956+
getAsyncIteratorNextRequirements(const ASTContext &ctx) {
957+
auto proto = ctx.getProtocol(KnownProtocolKind::AsyncIteratorProtocol);
958+
if (!proto)
959+
return { nullptr, nullptr };
960+
961+
FuncDecl *next = nullptr;
962+
FuncDecl *nextThrowing = nullptr;
963+
for (auto result : proto->lookupDirect(ctx.Id_next)) {
964+
if (result->getDeclContext() != proto)
965+
continue;
966+
967+
if (auto func = dyn_cast<FuncDecl>(result)) {
968+
switch (func->getParameters()->size()) {
969+
case 0: next = func; break;
970+
case 1: nextThrowing = func; break;
971+
default: break;
972+
}
973+
}
974+
}
975+
976+
return { next, nextThrowing };
977+
}
978+
951979
FuncDecl *ASTContext::getAsyncIteratorNext() const {
952980
if (getImpl().AsyncIteratorNext) {
953981
return getImpl().AsyncIteratorNext;
954982
}
955983

956-
auto proto = getProtocol(KnownProtocolKind::AsyncIteratorProtocol);
957-
if (!proto)
958-
return nullptr;
984+
auto next = getAsyncIteratorNextRequirements(*this).first;
985+
getImpl().AsyncIteratorNext = next;
986+
return next;
987+
}
959988

960-
if (auto *func = lookupRequirement(proto, Id_next)) {
961-
getImpl().AsyncIteratorNext = func;
962-
return func;
989+
FuncDecl *ASTContext::getAsyncIteratorNextIsolated() const {
990+
if (getImpl().AsyncIteratorNextIsolated) {
991+
return getImpl().AsyncIteratorNextIsolated;
963992
}
964993

965-
return nullptr;
994+
auto nextThrowing = getAsyncIteratorNextRequirements(*this).second;
995+
getImpl().AsyncIteratorNextIsolated = nextThrowing;
996+
return nextThrowing;
966997
}
967998

968999
namespace {

lib/AST/Availability.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -819,6 +819,7 @@ ASTContext::getSwift5PlusAvailability(llvm::VersionTuple swiftVersion) {
819819
case 7: return getSwift57Availability();
820820
case 8: return getSwift58Availability();
821821
case 9: return getSwift59Availability();
822+
case 11: return getSwift511Availability();
822823
default: break;
823824
}
824825
}

lib/AST/Effects.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,9 @@ void swift::simple_display(llvm::raw_ostream &out,
114114
case PolymorphicEffectKind::ByConformance:
115115
out << "by conformance";
116116
break;
117+
case PolymorphicEffectKind::AsyncSequenceRethrows:
118+
out << "by async sequence implicit @rethrows";
119+
break;
117120
case PolymorphicEffectKind::Always:
118121
out << "always";
119122
break;

lib/IRGen/MetadataRequest.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1641,7 +1641,7 @@ static MetadataResponse emitFunctionTypeMetadataRef(IRGenFunction &IGF,
16411641

16421642
default:
16431643
assert((!params.empty() || type->isDifferentiable() ||
1644-
type->getGlobalActor()) &&
1644+
type->getGlobalActor() || type->getThrownError()) &&
16451645
"0 parameter case should be specialized unless it is a "
16461646
"differentiable function or has a global actor");
16471647

lib/SILOptimizer/Analysis/RegionAnalysis.cpp

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2802,8 +2802,9 @@ static bool canComputeRegionsForFunction(SILFunction *fn) {
28022802

28032803
RegionAnalysisFunctionInfo::RegionAnalysisFunctionInfo(
28042804
SILFunction *fn, PostOrderFunctionInfo *pofi)
2805-
: allocator(), fn(fn), translator(), ptrSetFactory(allocator),
2806-
blockStates(), pofi(pofi), solved(false), supportedFunction(true) {
2805+
: allocator(), fn(fn), valueMap(fn), translator(),
2806+
ptrSetFactory(allocator), blockStates(), pofi(pofi), solved(false),
2807+
supportedFunction(true) {
28072808
// Before we do anything, make sure that we support processing this function.
28082809
//
28092810
// NOTE: See documentation on supportedFunction for criteria.
@@ -3005,7 +3006,7 @@ TrackableValue RegionAnalysisValueMap::getTrackableValue(
30053006
}
30063007

30073008
// Otherwise refer to the oracle.
3008-
if (!isNonSendableType(value->getType(), value->getFunction()))
3009+
if (!isNonSendableType(value->getType(), fn))
30093010
iter.first->getSecond().addFlag(TrackableValueFlag::isSendable);
30103011

30113012
// Check if our base is a ref_element_addr from an actor. In such a case,

0 commit comments

Comments
 (0)