Skip to content

Commit 0ee0084

Browse files
Suyash SrijanSuyash Srijan
authored andcommitted
[typechecker] Emit error diagnostic if the type in is-pattern does not conform to error and we're in a catch statement
1 parent d6eb168 commit 0ee0084

File tree

2 files changed

+44
-0
lines changed

2 files changed

+44
-0
lines changed

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4028,6 +4028,27 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
40284028
if (toType->isAnyObject() || fromType->isAnyObject())
40294029
return CheckedCastKind::ValueCast;
40304030

4031+
// A checked cast from Swift.Error to a type that does not conform to
4032+
// Swift.Error cannot succeed.
4033+
//
4034+
// struct S {}
4035+
// enum FooError: Error { case bar }
4036+
// func foo() throws {
4037+
// do {
4038+
// throw FooError.bar
4039+
// } catch is X {
4040+
// print("Caught bar error")
4041+
// }
4042+
// }
4043+
auto exceptionType = getExceptionType(dc, SourceLoc());
4044+
auto toTypeConformsToError =
4045+
conformsToProtocol(toType, Context.getErrorDecl(), dc,
4046+
ConformanceCheckFlags::InExpression);
4047+
if (fromType->isEqual(exceptionType) && !toTypeConformsToError) {
4048+
diagnose(diagLoc, diag::type_does_not_conform, toType, exceptionType);
4049+
return failed();
4050+
}
4051+
40314052
bool toRequiresClass;
40324053
if (toType->isExistentialType())
40334054
toRequiresClass = toType->getExistentialLayout().requiresClass();

test/stmt/errors.swift

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,26 @@ func thirteen() {
165165
}
166166
}
167167
}
168+
169+
// SR 6400
170+
171+
enum SR_6400_E: Error {
172+
case castError
173+
}
174+
175+
struct SR_6400_S_1 {}
176+
struct SR_6400_S_2: Error {}
177+
178+
func sr_6400() throws {
179+
do {
180+
throw SR_6400_E.castError
181+
} catch is SR_6400_S_1 { // expected-error {{type 'SR_6400_S_1' does not conform to protocol 'Error'}} expected-warning {{cast from 'Error' to unrelated type 'SR_6400_S_1' always fails}}
182+
print("Caught error")
183+
}
184+
185+
do {
186+
throw SR_6400_E.castError
187+
} catch is SR_6400_S_2 {
188+
print("Caught error") // Ok
189+
}
190+
}

0 commit comments

Comments
 (0)