@@ -33,8 +33,9 @@ fn is_stable(place: PlaceRef<'_>) -> bool {
33
33
} )
34
34
}
35
35
36
- /// Determine whether this type may be a reference (or box), and thus needs retagging.
37
- fn may_be_reference ( ty : Ty < ' _ > ) -> bool {
36
+ /// Determine whether this type may contain a reference (or box), and thus needs retagging.
37
+ /// We will only recurse `depth` times into Tuples/ADTs to bound the cost of this.
38
+ fn may_contain_reference < ' tcx > ( ty : Ty < ' tcx > , depth : u32 , tcx : TyCtxt < ' tcx > ) -> bool {
38
39
match ty. kind ( ) {
39
40
// Primitive types that are not references
40
41
ty:: Bool
@@ -50,8 +51,20 @@ fn may_be_reference(ty: Ty<'_>) -> bool {
50
51
// References
51
52
ty:: Ref ( ..) => true ,
52
53
ty:: Adt ( ..) if ty. is_box ( ) => true ,
53
- // Compound types are not references
54
- ty:: Array ( ..) | ty:: Slice ( ..) | ty:: Tuple ( ..) | ty:: Adt ( ..) => false ,
54
+ // Compound types: recurse
55
+ ty:: Array ( ty, _) | ty:: Slice ( ty) => {
56
+ // This does not branch so we keep the depth the same.
57
+ may_contain_reference ( * ty, depth, tcx)
58
+ }
59
+ ty:: Tuple ( tys) => {
60
+ depth == 0 || tys. iter ( ) . any ( |ty| may_contain_reference ( ty, depth - 1 , tcx) )
61
+ }
62
+ ty:: Adt ( adt, subst) => {
63
+ depth == 0
64
+ || adt. variants ( ) . iter ( ) . any ( |v| {
65
+ v. fields . iter ( ) . any ( |f| may_contain_reference ( f. ty ( tcx, subst) , depth - 1 , tcx) )
66
+ } )
67
+ }
55
68
// Conservative fallback
56
69
_ => true ,
57
70
}
@@ -83,7 +96,7 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
83
96
// FIXME: Instead of giving up for unstable places, we should introduce
84
97
// a temporary and retag on that.
85
98
is_stable ( place. as_ref ( ) )
86
- && may_be_reference ( place. ty ( & * local_decls, tcx) . ty )
99
+ && may_contain_reference ( place. ty ( & * local_decls, tcx) . ty , /*depth*/ 3 , tcx )
87
100
&& is_not_temp ( & local_decls[ place. local ] )
88
101
} ;
89
102
let place_base_raw = |place : & Place < ' tcx > | {
0 commit comments