@@ -192,3 +192,140 @@ func func77933460() {
192192 // expected-note@-3 {{captured value declared here}}
193193 // expected-warning@-4 {{variable 'obj' was never mutated; consider changing to 'let' constant}}
194194}
195+
196+ // MARK: - Forward Declared Lets
197+
198+ // https://github.com/swiftlang/swift/issues/84909
199+ // Make sure we can't capture an uninitialized 'let' temporary allocation either.
200+
201+ protocol P { }
202+
203+ enum E {
204+ static func static_gen_fwd< T> ( _ g: ( ) -> T ) -> T { g ( ) }
205+ }
206+
207+ func global_fwd( _ a: ( ) -> Any ) -> Any { a ( ) }
208+ func global_gen_fwd< T> ( _ g: ( ) -> T ) -> T { g ( ) }
209+ func global_fwd_p( _ p: ( ) -> any P ) -> any P { p ( ) }
210+
211+ func forward_declared_let_captures( ) {
212+ do {
213+ let bad : Any = { bad } ( )
214+ // expected-error@-1 {{closure captures 'bad' before it is declared}}
215+ // expected-note@-2 {{captured here}}
216+ // expected-note@-3 {{captured value declared here}}
217+ }
218+
219+ do {
220+ func fwd( _ i: ( ) -> Any ) -> Any { i ( ) }
221+ let bad = fwd { bad }
222+ // expected-error@-1 {{closure captures 'bad' before it is declared}}
223+ // expected-note@-2 {{captured here}}
224+ // expected-note@-3 {{captured value declared here}}
225+ }
226+
227+ do {
228+ func bad_local_f( ) -> Any { bad }
229+ // expected-error@-1 {{closure captures 'bad' before it is declared}}
230+ // expected-note@-2 {{captured here}}
231+ let bad = bad_local_f ( )
232+ // expected-note@-1 {{captured value declared here}}
233+ }
234+
235+ do {
236+ let bad = global_fwd { bad }
237+ // expected-error@-1 {{closure captures 'bad' before it is declared}}
238+ // expected-note@-2 {{captured here}}
239+ // expected-note@-3 {{captured value declared here}}
240+ }
241+
242+ do {
243+ let bad : Any = global_gen_fwd { bad }
244+ // expected-error@-1 {{closure captures 'bad' before it is declared}}
245+ // expected-note@-2 {{captured here}}
246+ // expected-note@-3 {{captured value declared here}}
247+ }
248+
249+ do {
250+ let bad : Any = E . static_gen_fwd { bad }
251+ // expected-error@-1 {{closure captures 'bad' before it is declared}}
252+ // expected-note@-2 {{captured here}}
253+ // expected-note@-3 {{captured value declared here}}
254+ }
255+
256+ do {
257+ let badNested : Any = global_fwd { { [ badNested] in badNested } ( ) }
258+ // expected-error@-1 {{closure captures 'badNested' before it is declared}}
259+ // expected-note@-2 {{captured here}}
260+ // expected-note@-3 {{captured value declared here}}
261+ }
262+
263+ do {
264+ let badOpt : Any ? = { ( ) -> Any ? in badOpt } ( )
265+ // expected-error@-1 {{closure captures 'badOpt' before it is declared}}
266+ // expected-note@-2 {{captured here}}
267+ // expected-note@-3 {{captured value declared here}}
268+ }
269+
270+ do {
271+ let badTup : ( Any , Any ) = { ( badTup. 0 , badTup. 1 ) } ( )
272+ // expected-error@-1 {{closure captures 'badTup' before it is declared}}
273+ // expected-note@-2 {{captured here}}
274+ // expected-note@-3 {{captured value declared here}}
275+ }
276+
277+ do {
278+ let badTup : ( Int , Any ) = { ( badTup. 0 , badTup. 1 ) } ( )
279+ // expected-error@-1 {{closure captures 'badTup' before it is declared}}
280+ // expected-note@-2 {{captured here}}
281+ // expected-note@-3 {{captured value declared here}}
282+ }
283+
284+ do {
285+ let ( badTup3, badTup4) : ( Any , Any ) = { ( badTup4, badTup3) } ( )
286+ // expected-error@-1 {{closure captures 'badTup4' before it is declared}}
287+ // expected-note@-2 {{captured here}}
288+ // expected-note@-3 {{captured value declared here}}
289+ // expected-error@-4 {{closure captures 'badTup3' before it is declared}}
290+ // expected-note@-5 {{captured here}}
291+ // expected-note@-6 {{captured value declared here}}
292+ }
293+
294+ do {
295+ struct S { var p : Any }
296+ let badStruct : S = { S ( p: badStruct. p) } ( )
297+ // expected-error@-1 {{closure captures 'badStruct' before it is declared}}
298+ // expected-note@-2 {{captured here}}
299+ // expected-note@-3 {{captured value declared here}}
300+ }
301+
302+ do {
303+ enum EE {
304+ case boring
305+ case weird( Any )
306+ case strange( Any )
307+ }
308+
309+ let badEnum : EE = { . weird( EE . strange ( badEnum) ) } ( )
310+ // expected-error@-1 {{closure captures 'badEnum' before it is declared}}
311+ // expected-note@-2 {{captured here}}
312+ // expected-note@-3 {{captured value declared here}}
313+ }
314+
315+ do {
316+ let badproto : any P = global_fwd_p { badproto }
317+ // expected-error@-1 {{closure captures 'badproto' before it is declared}}
318+ // expected-note@-2 {{captured here}}
319+ // expected-note@-3 {{captured value declared here}}
320+ }
321+ }
322+
323+ // FIXME: should/could these be diagnosed instead of accepted?
324+ func forward_declared_local_lazy_captures( ) {
325+ // runtime stack overflow, maybe UB?
326+ lazy var infiniteRecurse : Any = { infiniteRecurse } ( )
327+
328+ // ??? not entirely sure what's going on here...
329+ // this can be called and doesn't seem to trip the sanitizers...
330+ lazy var hmm : ( ) -> Any = { hmm }
331+ }
0 commit comments