Skip to content

Commit 446ef9c

Browse files
authored
Merge pull request #71129 from DougGregor/nonthrowing-do-catch-adjustment-fix
Use `any Error` for caught error type of an exhaustive, non-throwing do..catch
2 parents aa89306 + be6393b commit 446ef9c

File tree

5 files changed

+35
-8
lines changed

5 files changed

+35
-8
lines changed

lib/Sema/TypeCheckEffects.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3628,8 +3628,17 @@ Type TypeChecker::catchErrorType(DeclContext *dc, DoCatchStmt *stmt) {
36283628
stmt->getBody(), EffectKind::Throws);
36293629

36303630
// If it doesn't throw at all, the type is Never.
3631-
if (!classification.hasThrows())
3631+
if (!classification.hasThrows()) {
3632+
// Source compatibility: if the do..catch was already exhaustive,
3633+
// and we aren't doing full typed throws, treat the caught error
3634+
// type as 'any Error' to allow pattern-matches to continue to
3635+
// type check.
3636+
if (!ctx.LangOpts.hasFeature(Feature::FullTypedThrows) &&
3637+
stmt->isSyntacticallyExhaustive())
3638+
return ctx.getErrorExistentialType();
3639+
36323640
return ctx.getNeverType();
3641+
}
36333642

36343643
return classification.getThrownError();
36353644
}

test/Constraints/patterns.swift

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,11 +347,20 @@ struct One<Two> { // expected-note{{'Two' declared as parameter to type 'One'}}
347347
}
348348
}
349349

350+
enum HomeworkError: Error {
351+
case dogAteIt
352+
case forgot
353+
}
354+
350355
func testOne() {
351356
do {
352357
} catch let error { // expected-warning{{'catch' block is unreachable because no errors are thrown in 'do' block}}
353358
if case One.E.SomeError = error {} // expected-error{{generic parameter 'Two' could not be inferred}}
354359
}
360+
do {
361+
} catch HomeworkError.forgot { // expected-warning{{'catch' block is unreachable because no errors are thrown in 'do' block}}
362+
} catch {
363+
}
355364
}
356365

357366
// https://github.com/apple/swift/issues/50875

test/IDE/complete_exception.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,14 +147,14 @@ func test006() {
147147
} catch {
148148
#^INSIDE_CATCH1^#
149149
}
150-
// IMPLICIT_ERROR: Decl[LocalVar]/Local: error[#Never#]; name=error
150+
// IMPLICIT_ERROR: Decl[LocalVar]/Local: error[#any Error#]; name=error
151151
}
152152
func test007() {
153153
do {
154154
} catch let e {
155155
#^INSIDE_CATCH2^#
156156
}
157-
// EXPLICIT_ERROR_E: Decl[LocalVar]/Local: e[#Never#]; name=e
157+
// EXPLICIT_ERROR_E: Decl[LocalVar]/Local: e[#any Error#]; name=e
158158
}
159159
func test008() {
160160
do {
@@ -195,7 +195,7 @@ func test012() {
195195
error.#^INSIDE_CATCH_ERR_DOT1^#
196196
}
197197
}
198-
// ERROR_DOT: Keyword[self]/CurrNominal: self[#Never#]; name=self
198+
// ERROR_DOT: Keyword[self]/CurrNominal: self[#any Error#]; name=self
199199
func test013() {
200200
do {
201201
} catch let e {

test/Parse/errors.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,12 @@ func one() {
1919
do {
2020

2121
} catch { // expected-warning {{'catch' block is unreachable because no errors are thrown in 'do' block}}
22-
let error2 = error // expected-warning{{constant 'error2' inferred to have type 'Never', which is an enum with no cases}}
23-
// expected-note@-1{{add an explicit type annotation to silence this warning}}
22+
let error2 = error
2423
}
2524

2625
do {
2726
} catch where true { // expected-warning {{'catch' block is unreachable because no errors are thrown in 'do' block}}
28-
let error2 = error // expected-warning{{constant 'error2' inferred to have type 'Never', which is an enum with no cases}}
29-
// expected-note@-1{{add an explicit type annotation to silence this warning}}
27+
let error2 = error
3028
} catch {
3129
}
3230

test/stmt/typed_throws.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,17 @@ func testTryIncompatibleTyped(cond: Bool) throws(HomeworkError) {
139139
}
140140
}
141141

142+
func doSomethingWithoutThrowing() { }
143+
144+
func testDoCatchWithoutThrowing() {
145+
do {
146+
try doSomethingWithoutThrowing() // expected-warning{{no calls to throwing functions occur within 'try' expression}}
147+
} catch HomeworkError.forgot { // expected-warning{{'catch' block is unreachable because no errors are thrown in 'do' block}}
148+
// expected-error@-1{{pattern of type 'HomeworkError' cannot match 'Never'}}
149+
} catch {
150+
}
151+
}
152+
142153
// "Rethrow-like" functions are only allowed to be called from rethrows
143154
// functions as a compatibility hack, which is removed under FullTypedThrows.
144155
func rethrowsLike<E>(_ body: () throws(E) -> Void) throws(E) { }

0 commit comments

Comments
 (0)