Skip to content

Commit f54782e

Browse files
committed
[SILGen] Correctly determine the thrown error type for closures
When a closure throws a generic error type, we were retrieving the substituted error type (involving archetypes) when we needed to be working with the interface type. Fixes rdar://124484012.
1 parent 1cd7a56 commit f54782e

File tree

4 files changed

+33
-13
lines changed

4 files changed

+33
-13
lines changed

include/swift/SIL/AbstractionPattern.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1537,6 +1537,11 @@ class AbstractionPattern {
15371537
std::optional<std::pair<AbstractionPattern, CanType>>
15381538
getFunctionThrownErrorType(CanAnyFunctionType substFnInterfaceType) const;
15391539

1540+
/// For the abstraction pattern produced by `getFunctionThrownErrorType()`,
1541+
/// produce the effective thrown error type to be used when we don't have
1542+
/// a substituted error type.
1543+
CanType getEffectiveThrownErrorType() const;
1544+
15401545
/// Given that the value being abstracted is a function type, return
15411546
/// the abstraction pattern for one of its parameter types.
15421547
AbstractionPattern getFunctionParamType(unsigned index) const;

lib/SIL/IR/AbstractionPattern.cpp

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,7 +1340,6 @@ AbstractionPattern::getFunctionThrownErrorType(
13401340
if (!optOrigErrorType)
13411341
return std::nullopt;
13421342

1343-
auto &ctx = substFnInterfaceType->getASTContext();
13441343
auto substErrorType = substFnInterfaceType->getEffectiveThrownErrorType();
13451344

13461345
if (isTypeParameterOrOpaqueArchetype()) {
@@ -1352,16 +1351,21 @@ AbstractionPattern::getFunctionThrownErrorType(
13521351
}
13531352

13541353
if (!substErrorType) {
1355-
if (optOrigErrorType->getType()->hasTypeParameter())
1356-
substErrorType = ctx.getNeverType();
1357-
else
1358-
substErrorType = optOrigErrorType->getType();
1354+
substErrorType = optOrigErrorType->getEffectiveThrownErrorType();
13591355
}
13601356

13611357
return std::make_pair(*optOrigErrorType,
13621358
(*substErrorType)->getCanonicalType());
13631359
}
13641360

1361+
CanType AbstractionPattern::getEffectiveThrownErrorType() const {
1362+
CanType type = getType();
1363+
if (type->hasTypeParameter())
1364+
return type->getASTContext().getNeverType()->getCanonicalType();
1365+
1366+
return type;
1367+
}
1368+
13651369
AbstractionPattern
13661370
AbstractionPattern::getObjCMethodAsyncCompletionHandlerType(
13671371
CanType swiftCompletionHandlerType) const {

lib/SILGen/SILGenProlog.cpp

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1470,14 +1470,9 @@ uint16_t SILGenFunction::emitBasicProlog(
14701470

14711471
std::optional<AbstractionPattern> origErrorType;
14721472
if (origClosureType && !origClosureType->isTypeParameterOrOpaqueArchetype()) {
1473-
CanType substClosureType = origClosureType->getType()
1474-
.subst(origClosureType->getGenericSubstitutions())->getCanonicalType();
1475-
CanAnyFunctionType substClosureFnType =
1476-
cast<AnyFunctionType>(substClosureType);
1477-
if (auto optPair = origClosureType->getFunctionThrownErrorType(substClosureFnType)) {
1478-
origErrorType = optPair->first;
1479-
errorType = optPair->second;
1480-
}
1473+
origErrorType = origClosureType->getFunctionThrownErrorType();
1474+
if (origErrorType && !errorType)
1475+
errorType = origErrorType->getEffectiveThrownErrorType();
14811476
} else if (errorType) {
14821477
origErrorType = AbstractionPattern(genericSig.getCanonicalSignature(),
14831478
(*errorType)->getCanonicalType());

test/SILGen/typed_throws_generic.swift

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,22 @@ extension P2 {
332332
func f() throws(Failure) { }
333333
}
334334

335+
public func withUnsafeRawBuffer<T, E>(
336+
_ body: (UnsafeMutableRawBufferPointer) throws(E) -> Void
337+
) throws(E) -> T {
338+
fatalError("boom")
339+
}
340+
341+
// CHECK-LABEL: sil private [ossa] @$s20typed_throws_generic16withUnsafeBufferyxySryxGq_YKXEq_YKs5ErrorR_r0_lFySwq_YKXEfU_ : $@convention(thin) <T, E where E : Error> (UnsafeMutableRawBufferPointer, @guaranteed @noescape @callee_guaranteed @substituted <τ_0_0, τ_0_1> (UnsafeMutableBufferPointer<τ_0_0>) -> @error_indirect τ_0_1 for <T, E>) -> @error_indirect E {
342+
// CHECK: try_apply{{.*}}@error_indirect τ_0_1 for <T, E>
343+
public func withUnsafeBuffer<T, E>(
344+
_ body: (UnsafeMutableBufferPointer<T>) throws(E) -> Void
345+
) throws(E) -> T {
346+
try withUnsafeRawBuffer { (buf_ptr: UnsafeMutableRawBufferPointer) throws(E) in
347+
try body(buf_ptr.bindMemory(to: T.self))
348+
}
349+
}
350+
335351
// CHECK-LABEL: sil private [transparent] [thunk] [ossa] @$s20typed_throws_generic1SVAA2P2A2aDP1fyy7FailureQzYKFTW : $@convention(witness_method: P2) (@in_guaranteed S) -> @error_indirect Never
336352
// CHECK: bb0(%0 : $*Never, %1 : $*S)
337353
struct S: P2 {

0 commit comments

Comments
 (0)