@@ -15,7 +15,6 @@ use rustc_hir::def_id::DefId;
15
15
use rustc_hir:: intravisit:: { self , Visitor } ;
16
16
use rustc_hir:: { Arm , Block , Expr , LetStmt , Pat , PatKind , Stmt } ;
17
17
use rustc_index:: Idx ;
18
- use rustc_middle:: bug;
19
18
use rustc_middle:: middle:: region:: * ;
20
19
use rustc_middle:: ty:: TyCtxt ;
21
20
use rustc_session:: lint;
@@ -34,14 +33,6 @@ struct Context {
34
33
struct ScopeResolutionVisitor < ' tcx > {
35
34
tcx : TyCtxt < ' tcx > ,
36
35
37
- // The number of expressions and patterns visited in the current body.
38
- expr_and_pat_count : usize ,
39
- // When this is `true`, we record the `Scopes` we encounter
40
- // when processing a Yield expression. This allows us to fix
41
- // up their indices.
42
- pessimistic_yield : bool ,
43
- // Stores scopes when `pessimistic_yield` is `true`.
44
- fixup_scopes : Vec < Scope > ,
45
36
// The generated scope tree.
46
37
scope_tree : ScopeTree ,
47
38
@@ -199,19 +190,14 @@ fn resolve_arm<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, arm: &'tcx hir:
199
190
visitor. cx = prev_cx;
200
191
}
201
192
193
+ #[ tracing:: instrument( level = "debug" , skip( visitor) ) ]
202
194
fn resolve_pat < ' tcx > ( visitor : & mut ScopeResolutionVisitor < ' tcx > , pat : & ' tcx hir:: Pat < ' tcx > ) {
203
195
// If this is a binding then record the lifetime of that binding.
204
196
if let PatKind :: Binding ( ..) = pat. kind {
205
197
record_var_lifetime ( visitor, pat. hir_id . local_id ) ;
206
198
}
207
199
208
- debug ! ( "resolve_pat - pre-increment {} pat = {:?}" , visitor. expr_and_pat_count, pat) ;
209
-
210
200
intravisit:: walk_pat ( visitor, pat) ;
211
-
212
- visitor. expr_and_pat_count += 1 ;
213
-
214
- debug ! ( "resolve_pat - post-increment {} pat = {:?}" , visitor. expr_and_pat_count, pat) ;
215
201
}
216
202
217
203
fn resolve_stmt < ' tcx > ( visitor : & mut ScopeResolutionVisitor < ' tcx > , stmt : & ' tcx hir:: Stmt < ' tcx > ) {
@@ -243,68 +229,15 @@ fn resolve_stmt<'tcx>(visitor: &mut ScopeResolutionVisitor<'tcx>, stmt: &'tcx hi
243
229
}
244
230
}
245
231
232
+ #[ tracing:: instrument( level = "debug" , skip( visitor) ) ]
246
233
fn resolve_expr < ' tcx > (
247
234
visitor : & mut ScopeResolutionVisitor < ' tcx > ,
248
235
expr : & ' tcx hir:: Expr < ' tcx > ,
249
236
terminating : bool ,
250
237
) {
251
- debug ! ( "resolve_expr - pre-increment {} expr = {:?}" , visitor. expr_and_pat_count, expr) ;
252
-
253
238
let prev_cx = visitor. cx ;
254
239
visitor. enter_node_scope_with_dtor ( expr. hir_id . local_id , terminating) ;
255
240
256
- let prev_pessimistic = visitor. pessimistic_yield ;
257
-
258
- // Ordinarily, we can rely on the visit order of HIR intravisit
259
- // to correspond to the actual execution order of statements.
260
- // However, there's a weird corner case with compound assignment
261
- // operators (e.g. `a += b`). The evaluation order depends on whether
262
- // or not the operator is overloaded (e.g. whether or not a trait
263
- // like AddAssign is implemented).
264
-
265
- // For primitive types (which, despite having a trait impl, don't actually
266
- // end up calling it), the evaluation order is right-to-left. For example,
267
- // the following code snippet:
268
- //
269
- // let y = &mut 0;
270
- // *{println!("LHS!"); y} += {println!("RHS!"); 1};
271
- //
272
- // will print:
273
- //
274
- // RHS!
275
- // LHS!
276
- //
277
- // However, if the operator is used on a non-primitive type,
278
- // the evaluation order will be left-to-right, since the operator
279
- // actually get desugared to a method call. For example, this
280
- // nearly identical code snippet:
281
- //
282
- // let y = &mut String::new();
283
- // *{println!("LHS String"); y} += {println!("RHS String"); "hi"};
284
- //
285
- // will print:
286
- // LHS String
287
- // RHS String
288
- //
289
- // To determine the actual execution order, we need to perform
290
- // trait resolution. Unfortunately, we need to be able to compute
291
- // yield_in_scope before type checking is even done, as it gets
292
- // used by AST borrowcheck.
293
- //
294
- // Fortunately, we don't need to know the actual execution order.
295
- // It suffices to know the 'worst case' order with respect to yields.
296
- // Specifically, we need to know the highest 'expr_and_pat_count'
297
- // that we could assign to the yield expression. To do this,
298
- // we pick the greater of the two values from the left-hand
299
- // and right-hand expressions. This makes us overly conservative
300
- // about what types could possibly live across yield points,
301
- // but we will never fail to detect that a type does actually
302
- // live across a yield point. The latter part is critical -
303
- // we're already overly conservative about what types will live
304
- // across yield points, as the generated MIR will determine
305
- // when things are actually live. However, for typecheck to work
306
- // properly, we can't miss any types.
307
-
308
241
match expr. kind {
309
242
// Conditional or repeating scopes are always terminating
310
243
// scopes, meaning that temporaries cannot outlive them.
@@ -360,55 +293,42 @@ fn resolve_expr<'tcx>(
360
293
let body = visitor. tcx . hir_body ( body) ;
361
294
visitor. visit_body ( body) ;
362
295
}
296
+ // Ordinarily, we can rely on the visit order of HIR intravisit
297
+ // to correspond to the actual execution order of statements.
298
+ // However, there's a weird corner case with compound assignment
299
+ // operators (e.g. `a += b`). The evaluation order depends on whether
300
+ // or not the operator is overloaded (e.g. whether or not a trait
301
+ // like AddAssign is implemented).
302
+ //
303
+ // For primitive types (which, despite having a trait impl, don't actually
304
+ // end up calling it), the evaluation order is right-to-left. For example,
305
+ // the following code snippet:
306
+ //
307
+ // let y = &mut 0;
308
+ // *{println!("LHS!"); y} += {println!("RHS!"); 1};
309
+ //
310
+ // will print:
311
+ //
312
+ // RHS!
313
+ // LHS!
314
+ //
315
+ // However, if the operator is used on a non-primitive type,
316
+ // the evaluation order will be left-to-right, since the operator
317
+ // actually get desugared to a method call. For example, this
318
+ // nearly identical code snippet:
319
+ //
320
+ // let y = &mut String::new();
321
+ // *{println!("LHS String"); y} += {println!("RHS String"); "hi"};
322
+ //
323
+ // will print:
324
+ // LHS String
325
+ // RHS String
326
+ //
327
+ // To determine the actual execution order, we need to perform
328
+ // trait resolution. Fortunately, we don't need to know the actual execution order.
363
329
hir:: ExprKind :: AssignOp ( _, left_expr, right_expr) => {
364
- debug ! (
365
- "resolve_expr - enabling pessimistic_yield, was previously {}" ,
366
- prev_pessimistic
367
- ) ;
368
-
369
- let start_point = visitor. fixup_scopes . len ( ) ;
370
- visitor. pessimistic_yield = true ;
371
-
372
- // If the actual execution order turns out to be right-to-left,
373
- // then we're fine. However, if the actual execution order is left-to-right,
374
- // then we'll assign too low a count to any `yield` expressions
375
- // we encounter in 'right_expression' - they should really occur after all of the
376
- // expressions in 'left_expression'.
377
330
visitor. visit_expr ( right_expr) ;
378
- visitor. pessimistic_yield = prev_pessimistic;
379
-
380
- debug ! ( "resolve_expr - restoring pessimistic_yield to {}" , prev_pessimistic) ;
381
331
visitor. visit_expr ( left_expr) ;
382
- debug ! ( "resolve_expr - fixing up counts to {}" , visitor. expr_and_pat_count) ;
383
-
384
- // Remove and process any scopes pushed by the visitor
385
- let target_scopes = visitor. fixup_scopes . drain ( start_point..) ;
386
-
387
- for scope in target_scopes {
388
- let yield_data =
389
- visitor. scope_tree . yield_in_scope . get_mut ( & scope) . unwrap ( ) . last_mut ( ) . unwrap ( ) ;
390
- let count = yield_data. expr_and_pat_count ;
391
- let span = yield_data. span ;
392
-
393
- // expr_and_pat_count never decreases. Since we recorded counts in yield_in_scope
394
- // before walking the left-hand side, it should be impossible for the recorded
395
- // count to be greater than the left-hand side count.
396
- if count > visitor. expr_and_pat_count {
397
- bug ! (
398
- "Encountered greater count {} at span {:?} - expected no greater than {}" ,
399
- count,
400
- span,
401
- visitor. expr_and_pat_count
402
- ) ;
403
- }
404
- let new_count = visitor. expr_and_pat_count ;
405
- debug ! (
406
- "resolve_expr - increasing count for scope {:?} from {} to {} at span {:?}" ,
407
- scope, count, new_count, span
408
- ) ;
409
-
410
- yield_data. expr_and_pat_count = new_count;
411
- }
412
332
}
413
333
414
334
hir:: ExprKind :: If ( cond, then, Some ( otherwise) ) => {
@@ -453,43 +373,6 @@ fn resolve_expr<'tcx>(
453
373
_ => intravisit:: walk_expr ( visitor, expr) ,
454
374
}
455
375
456
- visitor. expr_and_pat_count += 1 ;
457
-
458
- debug ! ( "resolve_expr post-increment {}, expr = {:?}" , visitor. expr_and_pat_count, expr) ;
459
-
460
- if let hir:: ExprKind :: Yield ( _, source) = & expr. kind {
461
- // Mark this expr's scope and all parent scopes as containing `yield`.
462
- let mut scope = Scope { local_id : expr. hir_id . local_id , data : ScopeData :: Node } ;
463
- loop {
464
- let data = YieldData {
465
- span : expr. span ,
466
- expr_and_pat_count : visitor. expr_and_pat_count ,
467
- source : * source,
468
- } ;
469
- match visitor. scope_tree . yield_in_scope . get_mut ( & scope) {
470
- Some ( yields) => yields. push ( data) ,
471
- None => {
472
- visitor. scope_tree . yield_in_scope . insert ( scope, vec ! [ data] ) ;
473
- }
474
- }
475
-
476
- if visitor. pessimistic_yield {
477
- debug ! ( "resolve_expr in pessimistic_yield - marking scope {:?} for fixup" , scope) ;
478
- visitor. fixup_scopes . push ( scope) ;
479
- }
480
-
481
- // Keep traversing up while we can.
482
- match visitor. scope_tree . parent_map . get ( & scope) {
483
- // Don't cross from closure bodies to their parent.
484
- Some ( & superscope) => match superscope. data {
485
- ScopeData :: CallSite => break ,
486
- _ => scope = superscope,
487
- } ,
488
- None => break ,
489
- }
490
- }
491
- }
492
-
493
376
visitor. cx = prev_cx;
494
377
}
495
378
@@ -612,8 +495,8 @@ fn resolve_local<'tcx>(
612
495
}
613
496
}
614
497
615
- // Make sure we visit the initializer first, so expr_and_pat_count remains correct .
616
- // The correct order, as shared between coroutine_interior, drop_ranges and intravisitor,
498
+ // Make sure we visit the initializer first.
499
+ // The correct order, as shared between drop_ranges and intravisitor,
617
500
// is to walk initializer, followed by pattern bindings, finally followed by the `else` block.
618
501
if let Some ( expr) = init {
619
502
visitor. visit_expr ( expr) ;
@@ -798,26 +681,15 @@ impl<'tcx> ScopeResolutionVisitor<'tcx> {
798
681
}
799
682
800
683
fn enter_body ( & mut self , hir_id : hir:: HirId , f : impl FnOnce ( & mut Self ) ) {
801
- // Save all state that is specific to the outer function
802
- // body. These will be restored once down below, once we've
803
- // visited the body.
804
- let outer_ec = mem:: replace ( & mut self . expr_and_pat_count , 0 ) ;
805
684
let outer_cx = self . cx ;
806
- // The 'pessimistic yield' flag is set to true when we are
807
- // processing a `+=` statement and have to make pessimistic
808
- // control flow assumptions. This doesn't apply to nested
809
- // bodies within the `+=` statements. See #69307.
810
- let outer_pessimistic_yield = mem:: replace ( & mut self . pessimistic_yield , false ) ;
811
685
812
686
self . enter_scope ( Scope { local_id : hir_id. local_id , data : ScopeData :: CallSite } ) ;
813
687
self . enter_scope ( Scope { local_id : hir_id. local_id , data : ScopeData :: Arguments } ) ;
814
688
815
689
f ( self ) ;
816
690
817
691
// Restore context we had at the start.
818
- self . expr_and_pat_count = outer_ec;
819
692
self . cx = outer_cx;
820
- self . pessimistic_yield = outer_pessimistic_yield;
821
693
}
822
694
}
823
695
@@ -919,10 +791,7 @@ pub(crate) fn region_scope_tree(tcx: TyCtxt<'_>, def_id: DefId) -> &ScopeTree {
919
791
let mut visitor = ScopeResolutionVisitor {
920
792
tcx,
921
793
scope_tree : ScopeTree :: default ( ) ,
922
- expr_and_pat_count : 0 ,
923
794
cx : Context { parent : None , var_parent : None } ,
924
- pessimistic_yield : false ,
925
- fixup_scopes : vec ! [ ] ,
926
795
extended_super_lets : Default :: default ( ) ,
927
796
} ;
928
797
0 commit comments