Skip to content

Commit bf5d09b

Browse files
authored
Merge pull request #71500 from DougGregor/rethrows-inheriting-async-sequence
Treat `@rethrows` protocols inheriting AsyncSequence like AsyncSequence
2 parents b5db452 + 7e3911e commit bf5d09b

File tree

2 files changed

+37
-0
lines changed

2 files changed

+37
-0
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,25 @@ PolymorphicEffectRequirementsRequest::evaluate(Evaluator &evaluator,
9696
ctx.AllocateCopy(conformances));
9797
}
9898

99+
/// Determine whether the given protocol inherits from either
100+
/// AsyncIteratorProtocol or AsyncSequence.
101+
static bool inheritsFromAsyncSequenceProtocol(ProtocolDecl *proto) {
102+
// If it's exactly one of these, shortcut.
103+
if (proto->isSpecificProtocol(KnownProtocolKind::AsyncIteratorProtocol) ||
104+
proto->isSpecificProtocol(KnownProtocolKind::AsyncSequence))
105+
return false;
106+
107+
auto &ctx = proto->getASTContext();
108+
if (auto iter = ctx.getProtocol(KnownProtocolKind::AsyncIteratorProtocol))
109+
if (proto->inheritsFrom(iter))
110+
return true;
111+
if (auto seq = ctx.getProtocol(KnownProtocolKind::AsyncSequence))
112+
if (proto->inheritsFrom(seq))
113+
return true;
114+
115+
return false;
116+
}
117+
99118
PolymorphicEffectKind
100119
PolymorphicEffectKindRequest::evaluate(Evaluator &evaluator,
101120
EffectKind kind,
@@ -117,6 +136,13 @@ PolymorphicEffectKindRequest::evaluate(Evaluator &evaluator,
117136
auto proto = req.getProtocolDecl();
118137

119138
if (proto->hasPolymorphicEffect(kind)) {
139+
// @rethrows protocols that inherit from AsyncIteratorProtocol or
140+
// AsyncSequence should be categorized like AsyncIteratorProtocol or
141+
// AsyncSequence.
142+
if (kind == EffectKind::Throws &&
143+
inheritsFromAsyncSequenceProtocol(proto))
144+
return PolymorphicEffectKind::AsyncSequenceRethrows;
145+
120146
return PolymorphicEffectKind::ByConformance;
121147
}
122148

test/Concurrency/async_sequence_rethrows.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,14 @@ func testCalls(x: some AsyncSequence<Int, Never>, y: any AsyncSequence<Int, any
4040
await f3(x, x)
4141
try await f3(x, y)
4242
}
43+
44+
// Treat @rethrows protocols that inherit AsyncSequence like they are
45+
// AsyncSequence for the purpose of rethrowing methods.
46+
@rethrows
47+
protocol InheritsAsyncSequence: AsyncSequence { }
48+
49+
extension InheritsAsyncSequence {
50+
func blah() async rethrows -> [Element] {
51+
try await self.reduce(into: [Element]()) { $0.append($1) }
52+
}
53+
}

0 commit comments

Comments
 (0)