Skip to content

Commit 991e7fd

Browse files
authored
Merge pull request #74454 from hborla/throws-never-diagnostics
[TypeCheckEffects] Diagnose type mismatches for thrown errors in contexts that throw `Never`.
2 parents ca266d3 + 8d64344 commit 991e7fd

File tree

3 files changed

+58
-0
lines changed

3 files changed

+58
-0
lines changed

Diff for: lib/Parse/ParseExpr.cpp

+17
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,23 @@ ParserResult<Expr> Parser::parseExprSequence(Diag<> Message,
372372
if (SequencedExprs.size() == 1)
373373
return makeParserResult(SequenceStatus, SequencedExprs[0]);
374374

375+
// If the left-most sequence expr is a 'try', hoist it up to turn
376+
// '(try x) + y' into 'try (x + y)'. This is necessary to do in the
377+
// parser because 'try' nodes are represented in the ASTScope tree
378+
// to look up catch nodes. The scope tree must be syntactic because
379+
// it's constructed before sequence folding happens during preCheckExpr.
380+
// Otherwise, catch node lookup would find the incorrect catch node for
381+
// 'try x + y' at the source location for 'y'.
382+
//
383+
// 'try' has restrictions for where it can appear within a sequence
384+
// expr. This is still diagnosed in TypeChecker::foldSequence.
385+
if (auto *tryEval = dyn_cast<AnyTryExpr>(SequencedExprs[0])) {
386+
SequencedExprs[0] = tryEval->getSubExpr();
387+
auto *sequence = SequenceExpr::create(Context, SequencedExprs);
388+
tryEval->setSubExpr(sequence);
389+
return makeParserResult(SequenceStatus, tryEval);
390+
}
391+
375392
return makeParserResult(SequenceStatus,
376393
SequenceExpr::create(Context, SequencedExprs));
377394
}

Diff for: lib/Sema/TypeCheckEffects.cpp

+15
Original file line numberDiff line numberDiff line change
@@ -3020,9 +3020,24 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
30203020
Type getCaughtErrorTypeAt(SourceLoc loc) {
30213021
auto dc = CurContext.getDeclContext();
30223022
auto module = dc->getParentModule();
3023+
3024+
// Autoclosures can't be found via ASTScope lookup.
3025+
if (CurContext.isAutoClosure()) {
3026+
auto *closure = dyn_cast<AutoClosureExpr>(CurContext.getDeclContext());
3027+
if (auto type = closure->getEffectiveThrownType())
3028+
return *type;
3029+
3030+
// Otherwise, the closure does not throw.
3031+
return Ctx.getNeverType();
3032+
}
3033+
30233034
if (CatchNode catchNode = ASTScope::lookupCatchNode(module, loc)) {
30243035
if (auto caughtType = catchNode.getThrownErrorTypeInContext(Ctx))
30253036
return *caughtType;
3037+
3038+
// If a catch node returns null for its thrown error type, we're
3039+
// in a non-throwing context.
3040+
return Ctx.getNeverType();
30263041
}
30273042

30283043
// Fall back to the error existential.

Diff for: test/stmt/typed_throws.swift

+26
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)