Skip to content

Commit 1284437

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. (cherry picked from commit 775191c)
1 parent 7bd3046 commit 1284437

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
@@ -309,3 +309,29 @@ func testDoCatchInClosure(cond: Bool, x: ThrowingMembers) {
309309
}
310310
}
311311
}
312+
313+
func takesThrowingAutoclosure(_: @autoclosure () throws(MyError) -> Int) {}
314+
func takesNonThrowingAutoclosure(_: @autoclosure () throws(Never) -> Int) {}
315+
316+
func getInt() throws -> Int { 0 }
317+
318+
func throwingAutoclosures() {
319+
takesThrowingAutoclosure(try getInt())
320+
// expected-error@-1 {{thrown expression type 'any Error' cannot be converted to error type 'MyError'}}
321+
322+
takesNonThrowingAutoclosure(try getInt())
323+
// expected-error@-1 {{thrown expression type 'any Error' cannot be converted to error type 'Never'}}
324+
}
325+
326+
func noThrow() throws(Never) {
327+
throw MyError.epicFailed
328+
// expected-error@-1 {{thrown expression type 'MyError' cannot be converted to error type 'Never'}}
329+
330+
try doSomething()
331+
// expected-error@-1 {{thrown expression type 'MyError' cannot be converted to error type 'Never'}}
332+
333+
do throws(Never) {
334+
throw MyError.epicFailed
335+
// expected-error@-1 {{thrown expression type 'MyError' cannot be converted to error type 'Never'}}
336+
} catch {}
337+
}

0 commit comments

Comments
 (0)