Skip to content

Commit 9aaeaec

Browse files
committed
Add test validating that we preserve existing Swift 4 'try?' behavior.
1 parent 1789d44 commit 9aaeaec

File tree

2 files changed

+260
-0
lines changed

2 files changed

+260
-0
lines changed

test/Parse/try_swift4.swift

Lines changed: 260 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
// RUN: %target-typecheck-verify-swift -swift-version 4
2+
3+
// Intentionally has lower precedence than assignments and ?:
4+
infix operator %%%% : LowPrecedence
5+
precedencegroup LowPrecedence {
6+
associativity: none
7+
lowerThan: AssignmentPrecedence
8+
}
9+
func %%%%<T, U>(x: T, y: U) -> Int { return 0 }
10+
11+
// Intentionally has lower precedence between assignments and ?:
12+
infix operator %%% : MiddlingPrecedence
13+
precedencegroup MiddlingPrecedence {
14+
associativity: none
15+
higherThan: AssignmentPrecedence
16+
lowerThan: TernaryPrecedence
17+
}
18+
func %%%<T, U>(x: T, y: U) -> Int { return 1 }
19+
20+
func foo() throws -> Int { return 0 }
21+
func bar() throws -> Int { return 0 }
22+
23+
var x = try foo() + bar()
24+
x = try foo() + bar()
25+
x += try foo() + bar()
26+
x += try foo() %%%% bar() // expected-error {{'try' following assignment operator does not cover everything to its right}} // expected-error {{call can throw but is not marked with 'try'}} // expected-warning {{result of operator '%%%%' is unused}}
27+
// expected-note@-1 {{did you mean to use 'try'?}} {{21-21=try }}
28+
// expected-note@-2 {{did you mean to handle error as optional value?}} {{21-21=try? }}
29+
// expected-note@-3 {{did you mean to disable error propagation?}} {{21-21=try! }}
30+
x += try foo() %%% bar()
31+
x = foo() + try bar() // expected-error {{'try' cannot appear to the right of a non-assignment operator}} // expected-error {{call can throw but is not marked with 'try'}}
32+
// expected-note@-1 {{did you mean to use 'try'?}} {{5-5=try }}
33+
// expected-note@-2 {{did you mean to handle error as optional value?}} {{5-5=try? }}
34+
// expected-note@-3 {{did you mean to disable error propagation?}} {{5-5=try! }}
35+
36+
var y = true ? try foo() : try bar() + 0
37+
var z = true ? try foo() : try bar() %%% 0 // expected-error {{'try' following conditional operator does not cover everything to its right}}
38+
39+
var a = try! foo() + bar()
40+
a = try! foo() + bar()
41+
a += try! foo() + bar()
42+
a += try! foo() %%%% bar() // expected-error {{'try!' following assignment operator does not cover everything to its right}} // expected-error {{call can throw but is not marked with 'try'}} // expected-warning {{result of operator '%%%%' is unused}}
43+
// expected-note@-1 {{did you mean to use 'try'?}} {{22-22=try }}
44+
// expected-note@-2 {{did you mean to handle error as optional value?}} {{22-22=try? }}
45+
// expected-note@-3 {{did you mean to disable error propagation?}} {{22-22=try! }}
46+
a += try! foo() %%% bar()
47+
a = foo() + try! bar() // expected-error {{'try!' cannot appear to the right of a non-assignment operator}} // expected-error {{call can throw but is not marked with 'try'}}
48+
// expected-note@-1 {{did you mean to use 'try'?}} {{5-5=try }}
49+
// expected-note@-2 {{did you mean to handle error as optional value?}} {{5-5=try? }}
50+
// expected-note@-3 {{did you mean to disable error propagation?}} {{5-5=try! }}
51+
52+
var b = true ? try! foo() : try! bar() + 0
53+
var c = true ? try! foo() : try! bar() %%% 0 // expected-error {{'try!' following conditional operator does not cover everything to its right}}
54+
55+
infix operator ?+= : AssignmentPrecedence
56+
func ?+=(lhs: inout Int?, rhs: Int?) {
57+
lhs = lhs! + rhs!
58+
}
59+
60+
var i = try? foo() + bar()
61+
let _: Double = i // expected-error {{cannot convert value of type 'Int?' to specified type 'Double'}}
62+
i = try? foo() + bar()
63+
i ?+= try? foo() + bar()
64+
i ?+= try? foo() %%%% bar() // expected-error {{'try?' following assignment operator does not cover everything to its right}} // expected-error {{call can throw but is not marked with 'try'}} // expected-warning {{result of operator '%%%%' is unused}}
65+
// expected-note@-1 {{did you mean to use 'try'?}} {{23-23=try }}
66+
// expected-note@-2 {{did you mean to handle error as optional value?}} {{23-23=try? }}
67+
// expected-note@-3 {{did you mean to disable error propagation?}} {{23-23=try! }}
68+
i ?+= try? foo() %%% bar()
69+
_ = foo() == try? bar() // expected-error {{'try?' cannot appear to the right of a non-assignment operator}} // expected-error {{call can throw but is not marked with 'try'}}
70+
// expected-note@-1 {{did you mean to use 'try'?}} {{5-5=try }}
71+
// expected-note@-2 {{did you mean to handle error as optional value?}} {{5-5=try? }}
72+
// expected-note@-3 {{did you mean to disable error propagation?}} {{5-5=try! }}
73+
_ = (try? foo()) == bar() // expected-error {{call can throw but is not marked with 'try'}}
74+
// expected-note@-1 {{did you mean to use 'try'?}} {{21-21=try }}
75+
// expected-note@-2 {{did you mean to handle error as optional value?}} {{21-21=try? }}
76+
// expected-note@-3 {{did you mean to disable error propagation?}} {{21-21=try! }}
77+
_ = foo() == (try? bar()) // expected-error {{call can throw but is not marked with 'try'}}
78+
// expected-note@-1 {{did you mean to use 'try'?}} {{5-5=try }}
79+
// expected-note@-2 {{did you mean to handle error as optional value?}} {{5-5=try? }}
80+
// expected-note@-3 {{did you mean to disable error propagation?}} {{5-5=try! }}
81+
_ = (try? foo()) == (try? bar())
82+
83+
let j = true ? try? foo() : try? bar() + 0
84+
let k = true ? try? foo() : try? bar() %%% 0 // expected-error {{'try?' following conditional operator does not cover everything to its right}}
85+
86+
try let singleLet = foo() // expected-error {{'try' must be placed on the initial value expression}} {{1-5=}} {{21-21=try }}
87+
try var singleVar = foo() // expected-error {{'try' must be placed on the initial value expression}} {{1-5=}} {{21-21=try }}
88+
try let uninit: Int // expected-error {{'try' must be placed on the initial value expression}}
89+
try let (destructure1, destructure2) = (foo(), bar()) // expected-error {{'try' must be placed on the initial value expression}} {{1-5=}} {{40-40=try }}
90+
try let multi1 = foo(), multi2 = bar() // expected-error {{'try' must be placed on the initial value expression}} expected-error 2 {{call can throw but is not marked with 'try'}}
91+
// expected-note@-1 {{did you mean to use 'try'?}} {{18-18=try }} expected-note@-1 {{did you mean to use 'try'?}} {{34-34=try }}
92+
// expected-note@-2 {{did you mean to handle error as optional value?}} {{18-18=try? }} expected-note@-2 {{did you mean to handle error as optional value?}} {{34-34=try? }}
93+
// expected-note@-3 {{did you mean to disable error propagation?}} {{18-18=try! }} expected-note@-3 {{did you mean to disable error propagation?}} {{34-34=try! }}
94+
class TryDecl { // expected-note {{in declaration of 'TryDecl'}}
95+
try let singleLet = foo() // expected-error {{'try' must be placed on the initial value expression}} {{3-7=}} {{23-23=try }}
96+
// expected-error @-1 {{call can throw, but errors cannot be thrown out of a property initializer}}
97+
try var singleVar = foo() // expected-error {{'try' must be placed on the initial value expression}} {{3-7=}} {{23-23=try }}
98+
// expected-error @-1 {{call can throw, but errors cannot be thrown out of a property initializer}}
99+
100+
try // expected-error {{expected declaration}}
101+
func method() {}
102+
}
103+
104+
func test() throws -> Int {
105+
try while true { // expected-error {{'try' cannot be used with 'while'}}
106+
try break // expected-error {{'try' cannot be used with 'break'}}
107+
}
108+
109+
try throw // expected-error {{'try' must be placed on the thrown expression}} {{3-7=}} {{3-3=try }} expected-error {{expected expression in 'throw' statement}}
110+
; // Reset parser.
111+
112+
try return // expected-error {{'try' cannot be used with 'return'}} expected-error {{non-void function should return a value}}
113+
; // Reset parser.
114+
115+
try throw foo() // expected-error {{'try' must be placed on the thrown expression}} {{3-7=}} {{13-13=try }}
116+
// expected-error@-1 {{thrown expression type 'Int' does not conform to 'Error'}}
117+
try return foo() // expected-error {{'try' must be placed on the returned expression}} {{3-7=}} {{14-14=try }}
118+
}
119+
120+
// Test operators.
121+
func *(a : String, b : String) throws -> Int { return 42 }
122+
let _ = "foo"
123+
* // expected-error {{operator can throw but expression is not marked with 'try'}}
124+
// expected-note@-1 {{did you mean to use 'try'?}} {{9-9=try }}
125+
// expected-note@-2 {{did you mean to handle error as optional value?}} {{9-9=try? }}
126+
// expected-note@-3 {{did you mean to disable error propagation?}} {{9-9=try! }}
127+
"bar"
128+
let _ = try! "foo"*"bar"
129+
let _ = try? "foo"*"bar"
130+
let _ = (try? "foo"*"bar") ?? 0
131+
132+
133+
// <rdar://problem/21414023> Assertion failure when compiling function that takes throwing functions and rethrows
134+
func rethrowsDispatchError(handleError: ((Error) throws -> ()), body: () throws -> ()) rethrows {
135+
do {
136+
body() // expected-error {{call can throw but is not marked with 'try'}}
137+
// expected-note@-1 {{did you mean to use 'try'?}} {{5-5=try }}
138+
// expected-note@-2 {{did you mean to handle error as optional value?}} {{5-5=try? }}
139+
// expected-note@-3 {{did you mean to disable error propagation?}} {{5-5=try! }}
140+
} catch {
141+
}
142+
}
143+
144+
// <rdar://problem/21432429> Calling rethrows from rethrows crashes Swift compiler
145+
struct r21432429 {
146+
func x(_ f: () throws -> ()) rethrows {}
147+
func y(_ f: () throws -> ()) rethrows {
148+
x(f) // expected-error {{call can throw but is not marked with 'try'}} expected-note {{call is to 'rethrows' function, but argument function can throw}}
149+
}
150+
}
151+
152+
// <rdar://problem/21427855> Swift 2: Omitting try from call to throwing closure in rethrowing function crashes compiler
153+
func callThrowingClosureWithoutTry(closure: (Int) throws -> Int) rethrows {
154+
closure(0) // expected-error {{call can throw but is not marked with 'try'}} expected-warning {{result of call to function returning 'Int' is unused}}
155+
// expected-note@-1 {{did you mean to use 'try'?}} {{3-3=try }}
156+
// expected-note@-2 {{did you mean to handle error as optional value?}} {{3-3=try? }}
157+
// expected-note@-3 {{did you mean to disable error propagation?}} {{3-3=try! }}
158+
}
159+
160+
func producesOptional() throws -> Int? { return nil }
161+
let _: String = try? producesOptional() // expected-error {{cannot convert value of type 'Int??' to specified type 'String'}}
162+
163+
let _ = (try? foo())!! // expected-error {{cannot force unwrap value of non-optional type 'Int'}}
164+
165+
func producesDoubleOptional() throws -> Int?? { return 3 }
166+
let _: String = try? producesDoubleOptional() // expected-error {{cannot convert value of type 'Int???' to specified type 'String'}}
167+
168+
func maybeThrow() throws {}
169+
try maybeThrow() // okay
170+
try! maybeThrow() // okay
171+
try? maybeThrow() // okay since return type of maybeThrow is Void
172+
_ = try? maybeThrow() // okay
173+
174+
let _: () -> Void = { try! maybeThrow() } // okay
175+
let _: () -> Void = { try? maybeThrow() } // okay since return type of maybeThrow is Void
176+
177+
178+
if try? maybeThrow() { // expected-error {{cannot be used as a boolean}} {{4-4=((}} {{21-21=) != nil)}}
179+
}
180+
let _: Int = try? foo() // expected-error {{value of optional type 'Int?' not unwrapped; did you mean to use 'try!' or chain with '?'?}} {{14-18=try!}}
181+
182+
class X {}
183+
func test(_: X) {}
184+
func producesObject() throws -> AnyObject { return X() }
185+
test(try producesObject()) // expected-error {{'AnyObject' is not convertible to 'X'; did you mean to use 'as!' to force downcast?}} {{26-26= as! X}}
186+
187+
_ = "a\(try maybeThrow())b"
188+
_ = try "a\(maybeThrow())b"
189+
_ = "a\(maybeThrow())" // expected-error {{call can throw but is not marked with 'try'}}
190+
// expected-note@-1 {{did you mean to use 'try'?}} {{9-9=try }}
191+
// expected-note@-2 {{did you mean to handle error as optional value?}} {{9-9=try? }}
192+
// expected-note@-3 {{did you mean to disable error propagation?}} {{9-9=try! }}
193+
194+
extension DefaultStringInterpolation {
195+
mutating func appendInterpolation() throws {}
196+
}
197+
198+
_ = try "a\()b"
199+
_ = "a\()b" // expected-error {{interpolation can throw but is not marked with 'try'}}
200+
// expected-note@-1 {{did you mean to use 'try'?}} {{5-5=try }}
201+
// expected-note@-2 {{did you mean to handle error as optional value?}} {{5-5=try? }}
202+
// expected-note@-3 {{did you mean to disable error propagation?}} {{5-5=try! }}
203+
_ = try "\() \(1)"
204+
205+
func testGenericOptionalTry<T>(_ call: () throws -> T ) {
206+
let _: String = try? call() // expected-error {{cannot convert value of type 'T?' to specified type 'String'}}
207+
}
208+
209+
func genericOptionalTry<T>(_ call: () throws -> T ) -> T? {
210+
let x = try? call() // no error expected
211+
return x
212+
}
213+
214+
// Test with a non-optional type
215+
let _: String = genericOptionalTry({ () throws -> Int in return 3 }) // expected-error {{cannot convert value of type 'Int?' to specified type 'String'}}
216+
217+
// Test with an optional type
218+
let _: String = genericOptionalTry({ () throws -> Int? in return nil }) // expected-error {{cannot convert value of type 'Int??' to specified type 'String'}}
219+
220+
func produceAny() throws -> Any {
221+
return 3
222+
}
223+
224+
let _: Int? = try? produceAny() as? Int // expected-error {{value of optional type 'Int??' not unwrapped; did you mean to use 'try!' or chain with '?'?}}
225+
let _: Int?? = (try? produceAny()) as? Int // good
226+
let _: String = try? produceAny() as? Int // expected-error {{cannot convert value of type 'Int??' to specified type 'String'}}
227+
let _: String = (try? produceAny()) as? Int // expected-error {{cannot convert value of type 'Int?' to specified type 'String'}}
228+
229+
230+
struct ThingProducer {
231+
func produceInt() throws -> Int { return 3 }
232+
func produceIntNoThrowing() -> Int { return 3 }
233+
func produceAny() throws -> Any { return 3 }
234+
func produceOptionalAny() throws -> Any? { return 3 }
235+
func produceDoubleOptionalInt() throws -> Int?? { return 3 }
236+
}
237+
238+
let optProducer: ThingProducer? = ThingProducer()
239+
let _: Int? = try? optProducer?.produceInt() // expected-error {{value of optional type 'Int??' not unwrapped; did you mean to use 'try!' or chain with '?'?}}
240+
let _: Int = try? optProducer?.produceInt() // expected-error {{cannot convert value of type 'Int??' to specified type 'Int'}}
241+
let _: String = try? optProducer?.produceInt() // expected-error {{cannot convert value of type 'Int??' to specified type 'String'}}
242+
let _: Int?? = try? optProducer?.produceInt() // good
243+
244+
let _: Int? = try? optProducer?.produceIntNoThrowing() // expected-error {{value of optional type 'Int??' not unwrapped; did you mean to use 'try!' or chain with '?'?}}
245+
let _: Int?? = try? optProducer?.produceIntNoThrowing() // expected-warning {{no calls to throwing functions occur within 'try' expression}}
246+
247+
let _: Int? = (try? optProducer?.produceAny()) as? Int // good
248+
let _: Int? = try? optProducer?.produceAny() as? Int // expected-error {{value of optional type 'Int??' not unwrapped; did you mean to use 'try!' or chain with '?'?}}
249+
let _: Int?? = try? optProducer?.produceAny() as? Int // good
250+
let _: String = try? optProducer?.produceAny() as? Int // expected-error {{cannot convert value of type 'Int??' to specified type 'String'}}
251+
252+
let _: String = try? optProducer?.produceDoubleOptionalInt() // expected-error {{cannot convert value of type 'Int???' to specified type 'String'}}
253+
254+
let producer = ThingProducer()
255+
256+
let _: Int = try? producer.produceDoubleOptionalInt() // expected-error {{cannot convert value of type 'Int???' to specified type 'Int'}}
257+
let _: Int? = try? producer.produceDoubleOptionalInt() // expected-error {{value of optional type 'Int???' not unwrapped; did you mean to use 'try!' or chain with '?'?}}
258+
let _: Int?? = try? producer.produceDoubleOptionalInt() // expected-error {{value of optional type 'Int???' not unwrapped; did you mean to use 'try!' or chain with '?'?}}
259+
let _: Int??? = try? producer.produceDoubleOptionalInt() // good
260+
let _: String = try? producer.produceDoubleOptionalInt() // expected-error {{cannot convert value of type 'Int???' to specified type 'String'}}
File renamed without changes.

0 commit comments

Comments
 (0)