Skip to content

Commit 2159073

Browse files
authored
Merge pull request #69758 from DougGregor/typed-throws-rethrows-cleanup
Typed throws rethrows cleanup
2 parents f93c66d + 07d8871 commit 2159073

File tree

4 files changed

+62
-18
lines changed

4 files changed

+62
-18
lines changed

lib/SILGen/SILGenApply.cpp

Lines changed: 33 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5728,6 +5728,8 @@ SILValue SILGenFunction::emitApplyWithRethrow(SILLocation loc, SILValue fn,
57285728
{
57295729
B.emitBlock(errorBB);
57305730

5731+
Scope scope(Cleanups, CleanupLocation(loc));
5732+
57315733
// Grab the inner error.
57325734
SILValue innerError;
57335735
bool hasInnerIndirectError = fnConv.hasIndirectSILErrorResults();
@@ -5755,25 +5757,43 @@ SILValue SILGenFunction::emitApplyWithRethrow(SILLocation loc, SILValue fn,
57555757
outerError = innerError;
57565758
} else {
57575759
// The error requires some kind of translation.
5758-
5759-
// Load the inner error, if it was returned indirectly.
5760-
if (innerError->getType().isAddress()) {
5761-
innerError = emitLoad(loc, innerError, getTypeLowering(innerErrorType),
5762-
SGFContext(), IsTake).forward(*this);
5763-
}
5760+
outerErrorType = outerErrorType.getObjectType();
57645761

57655762
// If we need to convert the error type, do so now.
57665763
if (innerErrorType != outerErrorType) {
5767-
auto conversion = Conversion::getOrigToSubst(
5768-
AbstractionPattern(innerErrorType.getASTType()),
5769-
outerErrorType.getASTType(),
5770-
outerErrorType);
5771-
outerError = emitConvertedRValue(loc, conversion, SGFContext(),
5772-
[innerError](SILGenFunction &SGF, SILLocation loc, SGFContext C) {
5773-
return ManagedValue::forForwardedRValue(SGF, innerError);
5764+
assert(outerErrorType == SILType::getExceptionType(getASTContext()));
5765+
5766+
ProtocolConformanceRef conformances[1] = {
5767+
getModule().getSwiftModule()->conformsToProtocol(
5768+
innerError->getType().getASTType(),
5769+
getASTContext().getErrorDecl())
5770+
};
5771+
5772+
outerError = emitExistentialErasure(
5773+
loc,
5774+
innerErrorType.getASTType(),
5775+
getTypeLowering(innerErrorType),
5776+
getTypeLowering(outerErrorType),
5777+
getASTContext().AllocateCopy(conformances),
5778+
SGFContext(),
5779+
[&](SGFContext C) -> ManagedValue {
5780+
if (innerError->getType().isAddress()) {
5781+
return emitLoad(loc, innerError,
5782+
getTypeLowering(innerErrorType), SGFContext(),
5783+
IsTake);
5784+
}
5785+
5786+
return ManagedValue::forForwardedRValue(*this, innerError);
57745787
}).forward(*this);
5788+
} else if (innerError->getType().isAddress()) {
5789+
// Load the inner error, if it was returned indirectly.
5790+
outerError = emitLoad(loc, innerError, getTypeLowering(innerErrorType),
5791+
SGFContext(), IsTake).forward(*this);
5792+
} else {
5793+
outerError = innerError;
57755794
}
57765795

5796+
57775797
// If the outer error is returned indirectly, copy from the converted
57785798
// inner error to the outer error slot.
57795799
if (IndirectErrorResult) {

lib/Sema/TypeCheckEffects.cpp

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,17 @@ class Classification {
718718
return result;
719719
}
720720

721+
/// Return a classification that promotes a typed throws effect to an
722+
/// untyped throws effect.
723+
Classification promoteToUntypedThrows() const {
724+
if (!hasThrows())
725+
return *this;
726+
727+
Classification result(*this);
728+
result.ThrownError = ThrownError->getASTContext().getErrorExistentialType();
729+
return result;
730+
}
731+
721732
/// Return a classification that only retains the parts of this
722733
/// classification for the requested effect kind.
723734
Classification onlyEffect(EffectKind kind) const {
@@ -1109,9 +1120,15 @@ class ApplyClassifier {
11091120
}
11101121

11111122
for (unsigned i = 0, e = params.size(); i < e; ++i) {
1112-
result.merge(classifyArgument(args->getExpr(i),
1113-
params[i].getParameterType(),
1114-
kind));
1123+
auto argClassification = classifyArgument(
1124+
args->getExpr(i), params[i].getParameterType(), kind);
1125+
1126+
// Rethrows is untyped, so
1127+
if (kind == EffectKind::Throws) {
1128+
argClassification = argClassification.promoteToUntypedThrows();
1129+
}
1130+
1131+
result.merge(argClassification);
11151132
}
11161133

11171134
return;

test/Profiler/coverage_closure_returns_never.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@
66
// CHECK-NOT: increment_profiler_counter
77
// CHECK: [[LOAD:%.*]] = load {{.*}} : $*Never
88
// CHECK-NEXT: debug_value [[LOAD]] : $Never
9-
// CHECK-NEXT: debug_value undef : $any Error, var, name "$error", argno
10-
// CHECK-NEXT: unreachable
9+
// CHECK: unreachable
1110

1211
func closure_with_fatal_error(_ arr: [Never]) {
1312
// CHECK-LABEL: sil_coverage_map {{.*}}// closure #1 (Swift.Never) -> Swift.Never

test/decl/func/typed_throws.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,3 +146,11 @@ extension Either: Error where First: Error, Second: Error { }
146146
func f<E1, E2>(_ error: Either<E1, E2>) throws(Either<E1, E2>) {
147147
throw error
148148
}
149+
150+
// Ensure that calls to 'rethrows' functions are always treated as throwing `any
151+
// Error`.
152+
func rethrowingFunc(body: () throws -> Void) rethrows { }
153+
154+
func typedCallsRethrowingFunc<E>(body: () throws(E) -> Void) throws(E) {
155+
try rethrowingFunc(body: body) // expected-error{{thrown expression type 'any Error' cannot be converted to error type 'E'}}
156+
}

0 commit comments

Comments
 (0)