@@ -72,6 +72,7 @@ pub(super) fn lower(
72
72
is_lowering_coroutine : false ,
73
73
label_ribs : Vec :: new ( ) ,
74
74
current_binding_owner : None ,
75
+ awaitable_context : None ,
75
76
}
76
77
. collect ( params, body, is_async_fn)
77
78
}
@@ -100,6 +101,8 @@ struct ExprCollector<'a> {
100
101
// resolution
101
102
label_ribs : Vec < LabelRib > ,
102
103
current_binding_owner : Option < ExprId > ,
104
+
105
+ awaitable_context : Option < Awaitable > ,
103
106
}
104
107
105
108
#[ derive( Clone , Debug ) ]
@@ -135,6 +138,11 @@ impl RibKind {
135
138
}
136
139
}
137
140
141
+ enum Awaitable {
142
+ Yes ,
143
+ No ( & ' static str ) ,
144
+ }
145
+
138
146
#[ derive( Debug , Default ) ]
139
147
struct BindingList {
140
148
map : FxHashMap < Name , BindingId > ,
@@ -180,6 +188,18 @@ impl ExprCollector<'_> {
180
188
body : Option < ast:: Expr > ,
181
189
is_async_fn : bool ,
182
190
) -> ( Body , BodySourceMap ) {
191
+ self . awaitable_context . replace ( if is_async_fn {
192
+ Awaitable :: Yes
193
+ } else {
194
+ match self . owner {
195
+ DefWithBodyId :: FunctionId ( ..) => Awaitable :: No ( "non-async function" ) ,
196
+ DefWithBodyId :: StaticId ( ..) => Awaitable :: No ( "static" ) ,
197
+ DefWithBodyId :: ConstId ( ..) | DefWithBodyId :: InTypeConstId ( ..) => {
198
+ Awaitable :: No ( "constant" )
199
+ }
200
+ DefWithBodyId :: VariantId ( ..) => Awaitable :: No ( "enum variant" ) ,
201
+ }
202
+ } ) ;
183
203
if let Some ( ( param_list, mut attr_enabled) ) = param_list {
184
204
let mut params = vec ! [ ] ;
185
205
if let Some ( self_param) =
@@ -280,31 +300,40 @@ impl ExprCollector<'_> {
280
300
}
281
301
Some ( ast:: BlockModifier :: Async ( _) ) => {
282
302
self . with_label_rib ( RibKind :: Closure , |this| {
283
- this. collect_block_ ( e, |id, statements, tail| Expr :: Async {
284
- id,
285
- statements,
286
- tail,
303
+ this. with_awaitable_block ( Awaitable :: Yes , |this| {
304
+ this. collect_block_ ( e, |id, statements, tail| Expr :: Async {
305
+ id,
306
+ statements,
307
+ tail,
308
+ } )
287
309
} )
288
310
} )
289
311
}
290
312
Some ( ast:: BlockModifier :: Const ( _) ) => {
291
313
self . with_label_rib ( RibKind :: Constant , |this| {
292
- let ( result_expr_id, prev_binding_owner) =
293
- this. initialize_binding_owner ( syntax_ptr) ;
294
- let inner_expr = this. collect_block ( e) ;
295
- let it = this. db . intern_anonymous_const ( ConstBlockLoc {
296
- parent : this. owner ,
297
- root : inner_expr,
298
- } ) ;
299
- this. body . exprs [ result_expr_id] = Expr :: Const ( it) ;
300
- this. current_binding_owner = prev_binding_owner;
301
- result_expr_id
314
+ this. with_awaitable_block ( Awaitable :: No ( "constant block" ) , |this| {
315
+ let ( result_expr_id, prev_binding_owner) =
316
+ this. initialize_binding_owner ( syntax_ptr) ;
317
+ let inner_expr = this. collect_block ( e) ;
318
+ let it = this. db . intern_anonymous_const ( ConstBlockLoc {
319
+ parent : this. owner ,
320
+ root : inner_expr,
321
+ } ) ;
322
+ this. body . exprs [ result_expr_id] = Expr :: Const ( it) ;
323
+ this. current_binding_owner = prev_binding_owner;
324
+ result_expr_id
325
+ } )
302
326
} )
303
327
}
304
328
// FIXME
305
- Some ( ast:: BlockModifier :: AsyncGen ( _) ) | Some ( ast :: BlockModifier :: Gen ( _ ) ) | None => {
306
- self . collect_block ( e)
329
+ Some ( ast:: BlockModifier :: AsyncGen ( _) ) => {
330
+ self . with_awaitable_block ( Awaitable :: Yes , |this| this . collect_block ( e) )
307
331
}
332
+ Some ( ast:: BlockModifier :: Gen ( _) ) => self
333
+ . with_awaitable_block ( Awaitable :: No ( "non-async gen block" ) , |this| {
334
+ this. collect_block ( e)
335
+ } ) ,
336
+ None => self . collect_block ( e) ,
308
337
} ,
309
338
ast:: Expr :: LoopExpr ( e) => {
310
339
let label = e. label ( ) . map ( |label| self . collect_label ( label) ) ;
@@ -469,6 +498,12 @@ impl ExprCollector<'_> {
469
498
}
470
499
ast:: Expr :: AwaitExpr ( e) => {
471
500
let expr = self . collect_expr_opt ( e. expr ( ) ) ;
501
+ if let Awaitable :: No ( location) = self . is_lowering_awaitable_block ( ) {
502
+ self . source_map . diagnostics . push ( BodyDiagnostic :: AwaitOutsideOfAsync {
503
+ node : InFile :: new ( self . expander . current_file_id ( ) , AstPtr :: new ( & e) ) ,
504
+ location : location. to_string ( ) ,
505
+ } ) ;
506
+ }
472
507
self . alloc_expr ( Expr :: Await { expr } , syntax_ptr)
473
508
}
474
509
ast:: Expr :: TryExpr ( e) => self . collect_try_operator ( syntax_ptr, e) ,
@@ -527,7 +562,13 @@ impl ExprCollector<'_> {
527
562
let prev_is_lowering_coroutine = mem:: take ( & mut this. is_lowering_coroutine ) ;
528
563
let prev_try_block_label = this. current_try_block_label . take ( ) ;
529
564
530
- let body = this. collect_expr_opt ( e. body ( ) ) ;
565
+ let awaitable = if e. async_token ( ) . is_some ( ) {
566
+ Awaitable :: Yes
567
+ } else {
568
+ Awaitable :: No ( "non-async closure" )
569
+ } ;
570
+ let body =
571
+ this. with_awaitable_block ( awaitable, |this| this. collect_expr_opt ( e. body ( ) ) ) ;
531
572
532
573
let closure_kind = if this. is_lowering_coroutine {
533
574
let movability = if e. static_token ( ) . is_some ( ) {
@@ -2082,6 +2123,21 @@ impl ExprCollector<'_> {
2082
2123
fn alloc_label_desugared ( & mut self , label : Label ) -> LabelId {
2083
2124
self . body . labels . alloc ( label)
2084
2125
}
2126
+
2127
+ fn is_lowering_awaitable_block ( & self ) -> & Awaitable {
2128
+ self . awaitable_context . as_ref ( ) . unwrap_or ( & Awaitable :: No ( "unknown" ) )
2129
+ }
2130
+
2131
+ fn with_awaitable_block < T > (
2132
+ & mut self ,
2133
+ awaitable : Awaitable ,
2134
+ f : impl FnOnce ( & mut Self ) -> T ,
2135
+ ) -> T {
2136
+ let orig = self . awaitable_context . replace ( awaitable) ;
2137
+ let res = f ( self ) ;
2138
+ self . awaitable_context = orig;
2139
+ res
2140
+ }
2085
2141
}
2086
2142
2087
2143
fn comma_follows_token ( t : Option < syntax:: SyntaxToken > ) -> bool {
0 commit comments