@@ -72,6 +72,7 @@ use rustc_index::vec::IndexVec;
72
72
use rustc_middle:: mir:: tcx:: PlaceTy ;
73
73
use rustc_middle:: mir:: * ;
74
74
use rustc_middle:: ty:: { self , Ty , TyCtxt } ;
75
+ use rustc_span:: DUMMY_SP ;
75
76
use rustc_target:: abi:: VariantIdx ;
76
77
77
78
use crate :: {
@@ -550,7 +551,7 @@ pub struct Map {
550
551
}
551
552
552
553
impl Map {
553
- pub fn new ( ) -> Self {
554
+ fn new ( ) -> Self {
554
555
Self {
555
556
locals : IndexVec :: new ( ) ,
556
557
projections : FxHashMap :: default ( ) ,
@@ -559,23 +560,35 @@ impl Map {
559
560
}
560
561
}
561
562
562
- /// Register all places with suitable types up to a certain derefence depth (to prevent cycles).
563
- pub fn register_with_filter < ' tcx > (
563
+ /// Register all suitable places with matching types (up to a certain depth).
564
+ pub fn from_filter < ' tcx > (
565
+ tcx : TyCtxt < ' tcx > ,
566
+ body : & Body < ' tcx > ,
567
+ filter : impl FnMut ( Ty < ' tcx > ) -> bool ,
568
+ ) -> Self {
569
+ let mut map = Self :: new ( ) ;
570
+ map. register_with_filter ( tcx, body, 3 , filter) ;
571
+ map
572
+ }
573
+
574
+ fn register_with_filter < ' tcx > (
564
575
& mut self ,
565
576
tcx : TyCtxt < ' tcx > ,
566
- source : & impl HasLocalDecls < ' tcx > ,
577
+ body : & Body < ' tcx > ,
567
578
max_derefs : u32 ,
568
579
mut filter : impl FnMut ( Ty < ' tcx > ) -> bool ,
569
580
) {
581
+ let param_env = tcx. param_env_reveal_all_normalized ( body. source . def_id ( ) ) ;
570
582
let mut projection = Vec :: new ( ) ;
571
- for ( local, decl) in source . local_decls ( ) . iter_enumerated ( ) {
583
+ for ( local, decl) in body . local_decls . iter_enumerated ( ) {
572
584
self . register_with_filter_rec (
573
585
tcx,
574
586
max_derefs,
575
587
local,
576
588
& mut projection,
577
589
decl. ty ,
578
590
& mut filter,
591
+ param_env,
579
592
) ;
580
593
}
581
594
}
@@ -588,16 +601,28 @@ impl Map {
588
601
projection : & mut Vec < PlaceElem < ' tcx > > ,
589
602
ty : Ty < ' tcx > ,
590
603
filter : & mut impl FnMut ( Ty < ' tcx > ) -> bool ,
604
+ param_env : ty:: ParamEnv < ' tcx > ,
591
605
) {
592
606
if filter ( ty) {
593
607
// This might fail if `ty` is not scalar.
594
608
let _ = self . register_with_ty ( local, projection, ty) ;
595
609
}
596
610
if max_derefs > 0 {
597
- if let Some ( ty:: TypeAndMut { ty, .. } ) = ty. builtin_deref ( false ) {
598
- projection. push ( PlaceElem :: Deref ) ;
599
- self . register_with_filter_rec ( tcx, max_derefs - 1 , local, projection, ty, filter) ;
600
- projection. pop ( ) ;
611
+ if let Some ( ty:: TypeAndMut { ty : deref_ty, .. } ) = ty. builtin_deref ( false ) {
612
+ // References can only be tracked if the target is `!Freeze`.
613
+ if deref_ty. is_freeze ( tcx. at ( DUMMY_SP ) , param_env) {
614
+ projection. push ( PlaceElem :: Deref ) ;
615
+ self . register_with_filter_rec (
616
+ tcx,
617
+ max_derefs - 1 ,
618
+ local,
619
+ projection,
620
+ deref_ty,
621
+ filter,
622
+ param_env,
623
+ ) ;
624
+ projection. pop ( ) ;
625
+ }
601
626
}
602
627
}
603
628
iter_fields ( ty, tcx, |variant, field, ty| {
@@ -606,7 +631,9 @@ impl Map {
606
631
return ;
607
632
}
608
633
projection. push ( PlaceElem :: Field ( field, ty) ) ;
609
- self . register_with_filter_rec ( tcx, max_derefs, local, projection, ty, filter) ;
634
+ self . register_with_filter_rec (
635
+ tcx, max_derefs, local, projection, ty, filter, param_env,
636
+ ) ;
610
637
projection. pop ( ) ;
611
638
} ) ;
612
639
}
@@ -639,7 +666,8 @@ impl Map {
639
666
Ok ( index)
640
667
}
641
668
642
- pub fn register < ' tcx > (
669
+ #[ allow( unused) ]
670
+ fn register < ' tcx > (
643
671
& mut self ,
644
672
local : Local ,
645
673
projection : & [ PlaceElem < ' tcx > ] ,
@@ -671,12 +699,6 @@ impl Map {
671
699
return Err ( ( ) ) ;
672
700
}
673
701
674
- if !ty. is_trivially_freeze ( ) {
675
- // Due to the way we deal with shared references, only `Freeze` types may be tracked.
676
- // We are a little bit to restrictive here by only allowing trivially `Freeze` types.
677
- return Err ( ( ) ) ;
678
- }
679
-
680
702
let place = self . make_place ( local, projection) ?;
681
703
682
704
// Allocate a value slot if it doesn't have one.
0 commit comments