Skip to content

Commit 775191c

Browse files
committed
[TypeCheckEffects] Diagnose type mismatches for thrown errors in contexts that
throw `Never`. Previously, this mistake slipped through the effects checker because it used a fallback type of `any Error` if a catch node had a null thrown error type. This change also fixes an issue where thrown error type mismatches were not diagnosed at all in autoclosures.
1 parent 32aba12 commit 775191c

File tree

2 files changed

+41
-0
lines changed

2 files changed

+41
-0
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3010,9 +3010,24 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
30103010
Type getCaughtErrorTypeAt(SourceLoc loc) {
30113011
auto dc = CurContext.getDeclContext();
30123012
auto module = dc->getParentModule();
3013+
3014+
// Autoclosures can't be found via ASTScope lookup.
3015+
if (CurContext.isAutoClosure()) {
3016+
auto *closure = dyn_cast<AutoClosureExpr>(CurContext.getDeclContext());
3017+
if (auto type = closure->getEffectiveThrownType())
3018+
return *type;
3019+
3020+
// Otherwise, the closure does not throw.
3021+
return Ctx.getNeverType();
3022+
}
3023+
30133024
if (CatchNode catchNode = ASTScope::lookupCatchNode(module, loc)) {
30143025
if (auto caughtType = catchNode.getThrownErrorTypeInContext(Ctx))
30153026
return *caughtType;
3027+
3028+
// If a catch node returns null for its thrown error type, we're
3029+
// in a non-throwing context.
3030+
return Ctx.getNeverType();
30163031
}
30173032

30183033
// Fall back to the error existential.

test/stmt/typed_throws.swift

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,3 +311,29 @@ func testDoCatchInClosure(cond: Bool, x: ThrowingMembers) {
311311
}
312312
}
313313
}
314+
315+
func takesThrowingAutoclosure(_: @autoclosure () throws(MyError) -> Int) {}
316+
func takesNonThrowingAutoclosure(_: @autoclosure () throws(Never) -> Int) {}
317+
318+
func getInt() throws -> Int { 0 }
319+
320+
func throwingAutoclosures() {
321+
takesThrowingAutoclosure(try getInt())
322+
// expected-error@-1 {{thrown expression type 'any Error' cannot be converted to error type 'MyError'}}
323+
324+
takesNonThrowingAutoclosure(try getInt())
325+
// expected-error@-1 {{thrown expression type 'any Error' cannot be converted to error type 'Never'}}
326+
}
327+
328+
func noThrow() throws(Never) {
329+
throw MyError.epicFailed
330+
// expected-error@-1 {{thrown expression type 'MyError' cannot be converted to error type 'Never'}}
331+
332+
try doSomething()
333+
// expected-error@-1 {{thrown expression type 'MyError' cannot be converted to error type 'Never'}}
334+
335+
do throws(Never) {
336+
throw MyError.epicFailed
337+
// expected-error@-1 {{thrown expression type 'MyError' cannot be converted to error type 'Never'}}
338+
} catch {}
339+
}

0 commit comments

Comments
 (0)