Skip to content

Commit f04c0d4

Browse files
committed
---
yaml --- r: 347339 b: refs/heads/master c: b3956ba h: refs/heads/master i: 347337: 5aacf5e 347335: 4d39c90
1 parent daca1c0 commit f04c0d4

File tree

5 files changed

+91
-6
lines changed

5 files changed

+91
-6
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 99bcb43e199eb0d719701c957399e71ab0e6f183
2+
refs/heads/master: b3956bae7b4663ca5d2b78e682f75458954df543
33
refs/heads/master-next: 203b3026584ecad859eb328b2e12490099409cd5
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea

trunk/lib/Sema/TypeCheckConstraints.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4040,6 +4040,33 @@ CheckedCastKind TypeChecker::typeCheckCheckedCast(Type fromType,
40404040
if (toType->isAnyObject() || fromType->isAnyObject())
40414041
return CheckedCastKind::ValueCast;
40424042

4043+
// A cast from an existential type to a concrete type does not succeed. For
4044+
// example:
4045+
//
4046+
// struct S {}
4047+
// enum FooError: Error { case bar }
4048+
//
4049+
// func foo() {
4050+
// do {
4051+
// throw FooError.bar
4052+
// } catch is X { /* Will always fail */
4053+
// print("Caught bar error")
4054+
// }
4055+
// }
4056+
if (fromExistential) {
4057+
if (auto NTD = toType->getAnyNominal()) {
4058+
if (!isa<ProtocolDecl>(NTD)) {
4059+
auto protocolDecl =
4060+
dyn_cast_or_null<ProtocolDecl>(fromType->getAnyNominal());
4061+
if (protocolDecl &&
4062+
!conformsToProtocol(toType, protocolDecl, dc,
4063+
ConformanceCheckFlags::InExpression)) {
4064+
return failed();
4065+
}
4066+
}
4067+
}
4068+
}
4069+
40434070
bool toRequiresClass;
40444071
if (toType->isExistentialType())
40454072
toRequiresClass = toType->getExistentialLayout().requiresClass();

trunk/test/Constraints/casts.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ func protocol_concrete_casts(_ p1: P1, p2: P2, p12: P1 & P2) {
111111

112112
_ = p1 as! P1 & P2
113113

114-
_ = p2 as! S1
114+
_ = p2 as! S1 // expected-warning {{cast from 'P2' to unrelated type 'S1' always fails}}
115115

116116
_ = p12 as! S1
117117
_ = p12 as! S2
@@ -126,7 +126,7 @@ func protocol_concrete_casts(_ p1: P1, p2: P2, p12: P1 & P2) {
126126

127127
var _:Bool = p1 is P1 & P2
128128

129-
var _:Bool = p2 is S1
129+
var _:Bool = p2 is S1 // expected-warning {{cast from 'P2' to unrelated type 'S1' always fails}}
130130

131131
var _:Bool = p12 is S1
132132
var _:Bool = p12 is S2

trunk/test/Constraints/patterns.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ case is B,
5555
is D,
5656
is S:
5757
()
58-
case is E:
58+
case is E: // expected-warning {{cast from 'P' to unrelated type 'E' always fails}}
5959
()
6060
default:
6161
()
@@ -69,7 +69,7 @@ case let d as D:
6969
d.d()
7070
case let s as S:
7171
s.s()
72-
case let e as E:
72+
case let e as E: // expected-warning {{cast from 'P' to unrelated type 'E' always fails}}
7373
e.e()
7474
default:
7575
()
@@ -120,7 +120,7 @@ case iPadHair<E>.HairForceOne:
120120
()
121121
case iPadHair.HairForceOne: // expected-error{{generic enum type 'iPadHair' is ambiguous without explicit generic parameters when matching value of type 'HairType'}}
122122
()
123-
case Watch.Edition: // TODO: should warn that cast can't succeed with currently known conformances
123+
case Watch.Edition: // expected-warning {{cast from 'HairType' to unrelated type 'Watch' always fails}}
124124
()
125125
case .HairForceOne: // expected-error{{type 'HairType' has no member 'HairForceOne'}}
126126
()

trunk/test/stmt/errors.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -165,3 +165,61 @@ 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+
protocol SR_6400_FakeApplicationDelegate: AnyObject {}
179+
class SR_6400_FakeViewController {}
180+
181+
func sr_6400() throws {
182+
do {
183+
throw SR_6400_E.castError
184+
} catch is SR_6400_S_1 { // expected-warning {{cast from 'Error' to unrelated type 'SR_6400_S_1' always fails}}
185+
print("Caught error")
186+
}
187+
188+
do {
189+
throw SR_6400_E.castError
190+
} catch is SR_6400_S_2 {
191+
print("Caught error") // Ok
192+
}
193+
}
194+
195+
func sr_6400_1<T>(error: Error, as type: T.Type) -> Bool {
196+
return (error as? T) != nil // Ok
197+
}
198+
199+
func sr_6400_2(error: Error) {
200+
_ = error as? (SR_6400_FakeViewController & Error) // Ok
201+
}
202+
func sr_6400_3(error: Error) {
203+
_ = error as? (Error & SR_6400_FakeApplicationDelegate) // Ok
204+
}
205+
206+
class SR_6400_A {}
207+
class SR_6400_B: SR_6400_FakeApplicationDelegate & Error {}
208+
209+
func sr_6400_4() {
210+
do {
211+
throw SR_6400_E.castError
212+
} catch let error as SR_6400_A { // expected-warning {{cast from 'Error' to unrelated type 'SR_6400_A' always fails}} // expected-warning {{immutable value 'error' was never used; consider replacing with '_' or removing it}}
213+
print("Foo")
214+
} catch {
215+
print("Bar")
216+
}
217+
218+
do {
219+
throw SR_6400_E.castError
220+
} catch let error as SR_6400_B { // expected-warning {{immutable value 'error' was never used; consider replacing with '_' or removing it}}
221+
print("Foo")
222+
} catch {
223+
print("Bar")
224+
}
225+
}

0 commit comments

Comments
 (0)