Skip to content

Commit 2370214

Browse files
committed
Allow rethrow-like typed throws functions as witnesses
Extend an existing source compatibility hack that allows a typed throws-using function that *looks* like a rethrows function to be treated like a rethrows function. Here, do so when a typed-throws function is witnessing a rethrows requirement. Fixes rdar://122588459.
1 parent f9e6478 commit 2370214

File tree

4 files changed

+24
-7
lines changed

4 files changed

+24
-7
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -708,14 +708,9 @@ static Expr *removeErasureToExistentialError(Expr *expr) {
708708

709709
return expr;
710710
}
711+
}
711712

712-
/// Determine whether the given function uses typed throws in a manner
713-
/// than is structurally similar to 'rethrows', e.g.,
714-
///
715-
/// \code
716-
/// func map<T, E>(_ body: (Element) throws(E) -> T) throws(E) -> [T]
717-
/// \endcode
718-
static bool isRethrowLikeTypedThrows(AbstractFunctionDecl *func) {
713+
bool swift::isRethrowLikeTypedThrows(AbstractFunctionDecl *func) {
719714
// This notion is only for compatibility in Swift 5 and is disabled
720715
// when FullTypedThrows is enabled.
721716
ASTContext &ctx = func->getASTContext();
@@ -762,6 +757,8 @@ static bool isRethrowLikeTypedThrows(AbstractFunctionDecl *func) {
762757
return true;
763758
}
764759

760+
namespace {
761+
765762
/// Determine whether the given rethrows context is only allowed to be
766763
/// rethrowing because of the historically-rethrowing behavior of
767764
/// AsyncSequence and AsyncIteratorProtocol.

lib/Sema/TypeCheckEffects.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,14 @@ enum class ThrownErrorSubtyping {
4545
ThrownErrorSubtyping compareThrownErrorsForSubtyping(
4646
Type subThrownError, Type superThrownError, DeclContext *dc);
4747

48+
/// Determine whether the given function uses typed throws in a manner
49+
/// that is structurally similar to 'rethrows', e.g.,
50+
///
51+
/// \code
52+
/// func map<T, E>(_ body: (Element) throws(E) -> T) throws(E) -> [T]
53+
/// \endcode
54+
bool isRethrowLikeTypedThrows(AbstractFunctionDecl *func);
55+
4856
}
4957

5058
#endif // SWIFT_SEMA_TYPECHECKEFFECTS_H

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -603,6 +603,11 @@ RequirementMatch swift::matchWitness(
603603
}
604604

605605
case PolymorphicEffectKind::Always:
606+
// If the witness is using typed throws in a manner that looks
607+
// like rethrows, allow it.
608+
if (isRethrowLikeTypedThrows(funcWitness))
609+
break;
610+
606611
return RequirementMatch(witness, MatchKind::RethrowsConflict);
607612
}
608613
}

test/decl/protocol/conforms/typed_throws.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,10 @@ func testAssociatedTypes() {
6969
func assocFailureType<T: FailureAssociatedType>(_ value: T, _ error: T.Failure) throws(T.Failure) {
7070
throw error
7171
}
72+
73+
// Allow a typed-throws version of a function to witness a rethrowing function.
74+
public protocol HasRethrowingMap: Sequence {
75+
func map<T>(_ transform: (Element) throws -> T) rethrows -> [T]
76+
}
77+
78+
extension Array: HasRethrowingMap {}

0 commit comments

Comments
 (0)