-
Notifications
You must be signed in to change notification settings - Fork 10.4k
/
Copy pathdefer.swift
163 lines (134 loc) · 4.09 KB
/
defer.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// RUN: %target-typecheck-verify-swift
func voidReturn1() {}
func breakContinue(_: Int) -> Int {}
func testDefer(_ a : Int) {
defer { voidReturn1() }
defer { breakContinue(1)+42 } // expected-warning {{result of operator '+' is unused}}
// Ok:
defer { while false { break } }
// Not ok.
while false { defer { break } } // expected-error {{'break' cannot transfer control out of a defer statement}}
// expected-warning@-1 {{'defer' statement at end of scope always executes immediately}}{{17-22=do}}
defer { return } // expected-error {{'return' cannot transfer control out of a defer statement}}
// expected-warning@-1 {{'defer' statement at end of scope always executes immediately}}{{3-8=do}}
}
class SomeTestClass {
var x = 42
func method() {
defer { x = 97 } // self. not required here!
// expected-warning@-1 {{'defer' statement at end of scope always executes immediately}}{{5-10=do}}
}
}
enum DeferThrowError: Error {
case someError
}
func throwInDefer() {
defer { throw DeferThrowError.someError } // expected-error {{errors cannot be thrown out of a defer body}}
print("Foo")
}
func throwInDeferOK1() {
defer {
do {
throw DeferThrowError.someError
} catch {}
}
print("Bar")
}
func throwInDeferOK2() throws {
defer {
do {
throw DeferThrowError.someError
} catch {}
}
print("Bar")
}
func throwingFuncInDefer1() throws {
defer { try throwingFunctionCalledInDefer() } // expected-error {{errors cannot be thrown out of a defer body}}
print("Bar")
}
func throwingFuncInDefer1a() throws {
defer {
do {
try throwingFunctionCalledInDefer()
} catch {}
}
print("Bar")
}
func throwingFuncInDefer2() throws {
defer { throwingFunctionCalledInDefer() } // expected-error {{errors cannot be thrown out of a defer body}}
print("Bar")
}
func throwingFuncInDefer2a() throws {
defer {
do {
throwingFunctionCalledInDefer()
// expected-error@-1 {{call can throw but is not marked with 'try'}}
// expected-note@-2 {{did you mean to use 'try'?}}
// expected-note@-3 {{did you mean to handle error as optional value?}}
// expected-note@-4 {{did you mean to disable error propagation?}}
} catch {}
}
print("Bar")
}
func throwingFuncInDefer3() {
defer { try throwingFunctionCalledInDefer() } // expected-error {{errors cannot be thrown out of a defer body}}
print("Bar")
}
func throwingFuncInDefer3a() {
defer {
do {
try throwingFunctionCalledInDefer()
} catch {}
}
print("Bar")
}
func throwingFuncInDefer4() {
defer { throwingFunctionCalledInDefer() } // expected-error {{errors cannot be thrown out of a defer body}}
print("Bar")
}
func throwingFuncInDefer4a() {
defer {
do {
throwingFunctionCalledInDefer()
// expected-error@-1 {{call can throw but is not marked with 'try'}}
// expected-note@-2 {{did you mean to use 'try'?}}
// expected-note@-3 {{did you mean to handle error as optional value?}}
// expected-note@-4 {{did you mean to disable error propagation?}}
} catch {}
}
print("Bar")
}
func throwingFunctionCalledInDefer() throws {
throw DeferThrowError.someError
}
class SomeDerivedClass: SomeTestClass {
override init() {
defer {
super.init() // expected-error {{initializer chaining ('super.init') cannot be nested in another expression}}
}
}
}
// rdar://75088379 -- 'defer' should not be able to forward-reference captures
func badForwardReference() {
defer {
_ = x2 // expected-error {{use of local variable 'x2' before its declaration}}
let x1 = 0
let y1 = 0
defer {
_ = x1
_ = x2 // expected-error {{use of local variable 'x2' before its declaration}}
_ = y1
_ = y2 // expected-error {{use of local variable 'y2' before its declaration}}
}
let y2 = 0 // expected-note {{'y2' declared here}}
}
let x2 = 0 // expected-note 2{{'x2' declared here}}
func localFunc() {
defer {
_ = z1 // expected-error {{use of local variable 'z1' before its declaration}}
_ = z2
}
let z1 = 0 // expected-note {{'z1' declared here}}
}
let z2 = 0
}