@@ -33,42 +33,72 @@ type IndirectlyMutableResults<'mir, 'tcx> =
33
33
type QualifResults < ' mir , ' tcx , Q > =
34
34
dataflow:: ResultsCursor < ' mir , ' tcx , FlowSensitiveAnalysis < ' mir , ' mir , ' tcx , Q > > ;
35
35
36
+ #[ derive( Default ) ]
36
37
pub struct Qualifs < ' mir , ' tcx > {
37
- has_mut_interior : QualifResults < ' mir , ' tcx , HasMutInterior > ,
38
- needs_drop : QualifResults < ' mir , ' tcx , NeedsDrop > ,
39
- indirectly_mutable : IndirectlyMutableResults < ' mir , ' tcx > ,
38
+ has_mut_interior : Option < QualifResults < ' mir , ' tcx , HasMutInterior > > ,
39
+ needs_drop : Option < QualifResults < ' mir , ' tcx , NeedsDrop > > ,
40
+ indirectly_mutable : Option < IndirectlyMutableResults < ' mir , ' tcx > > ,
40
41
}
41
42
42
43
impl Qualifs < ' mir , ' tcx > {
43
44
fn indirectly_mutable (
44
45
& mut self ,
45
- _ : & Item < ' mir , ' tcx > ,
46
+ ccx : & ' mir ConstCx < ' mir , ' tcx > ,
46
47
local : Local ,
47
48
location : Location ,
48
49
) -> bool {
49
- self . indirectly_mutable . seek_before ( location) ;
50
- self . indirectly_mutable . get ( ) . contains ( local)
50
+ let indirectly_mutable = self . indirectly_mutable . get_or_insert_with ( || {
51
+ let ConstCx { tcx, body, def_id, param_env, .. } = * ccx;
52
+
53
+ // We can use `unsound_ignore_borrow_on_drop` here because custom drop impls are not
54
+ // allowed in a const.
55
+ //
56
+ // FIXME(ecstaticmorse): Someday we want to allow custom drop impls. How do we do this
57
+ // without breaking stable code?
58
+ MaybeMutBorrowedLocals :: mut_borrows_only ( tcx, & body, param_env)
59
+ . unsound_ignore_borrow_on_drop ( )
60
+ . into_engine ( tcx, & body, def_id)
61
+ . iterate_to_fixpoint ( )
62
+ . into_results_cursor ( & body)
63
+ } ) ;
64
+
65
+ indirectly_mutable. seek_before ( location) ;
66
+ indirectly_mutable. get ( ) . contains ( local)
51
67
}
52
68
53
69
/// Returns `true` if `local` is `NeedsDrop` at the given `Location`.
54
70
///
55
71
/// Only updates the cursor if absolutely necessary
56
- fn needs_drop ( & mut self , item : & Item < ' mir , ' tcx > , local : Local , location : Location ) -> bool {
57
- let ty = item. body . local_decls [ local] . ty ;
58
- if !NeedsDrop :: in_any_value_of_ty ( item, ty) {
72
+ fn needs_drop (
73
+ & mut self ,
74
+ ccx : & ' mir ConstCx < ' mir , ' tcx > ,
75
+ local : Local ,
76
+ location : Location ,
77
+ ) -> bool {
78
+ let ty = ccx. body . local_decls [ local] . ty ;
79
+ if !NeedsDrop :: in_any_value_of_ty ( ccx, ty) {
59
80
return false ;
60
81
}
61
82
62
- self . needs_drop . seek_before ( location) ;
63
- self . needs_drop . get ( ) . contains ( local) || self . indirectly_mutable ( item, local, location)
83
+ let needs_drop = self . needs_drop . get_or_insert_with ( || {
84
+ let ConstCx { tcx, body, def_id, .. } = * ccx;
85
+
86
+ FlowSensitiveAnalysis :: new ( NeedsDrop , ccx)
87
+ . into_engine ( tcx, & body, def_id)
88
+ . iterate_to_fixpoint ( )
89
+ . into_results_cursor ( & body)
90
+ } ) ;
91
+
92
+ needs_drop. seek_before ( location) ;
93
+ needs_drop. get ( ) . contains ( local) || self . indirectly_mutable ( ccx, local, location)
64
94
}
65
95
66
96
/// Returns `true` if `local` is `HasMutInterior` at the given `Location`.
67
97
///
68
98
/// Only updates the cursor if absolutely necessary.
69
99
fn has_mut_interior (
70
100
& mut self ,
71
- item : & Item < ' mir , ' tcx > ,
101
+ ccx : & ' mir ConstCx < ' mir , ' tcx > ,
72
102
local : Local ,
73
103
location : Location ,
74
104
) -> bool {
@@ -77,12 +107,20 @@ impl Qualifs<'mir, 'tcx> {
77
107
return false ;
78
108
}
79
109
80
- self . has_mut_interior . seek_before ( location) ;
81
- self . has_mut_interior . get ( ) . contains ( local)
82
- || self . indirectly_mutable ( item, local, location)
110
+ let has_mut_interior = self . has_mut_interior . get_or_insert_with ( || {
111
+ let ConstCx { tcx, body, def_id, .. } = * ccx;
112
+
113
+ FlowSensitiveAnalysis :: new ( HasMutInterior , ccx)
114
+ . into_engine ( tcx, & body, def_id)
115
+ . iterate_to_fixpoint ( )
116
+ . into_results_cursor ( & body)
117
+ } ) ;
118
+
119
+ has_mut_interior. seek_before ( location) ;
120
+ has_mut_interior. get ( ) . contains ( local) || self . indirectly_mutable ( ccx, local, location)
83
121
}
84
122
85
- fn in_return_place ( & mut self , item : & Item < ' mir , ' tcx > ) -> ConstQualifs {
123
+ fn in_return_place ( & mut self , ccx : & ' mir ConstCx < ' mir , ' tcx > ) -> ConstQualifs {
86
124
// Find the `Return` terminator if one exists.
87
125
//
88
126
// If no `Return` terminator exists, this MIR is divergent. Just return the conservative
@@ -128,33 +166,8 @@ impl Deref for Validator<'mir, 'tcx> {
128
166
}
129
167
130
168
impl Validator < ' mir , ' tcx > {
131
- pub fn new ( item : & ' mir Item < ' mir , ' tcx > ) -> Self {
132
- let Item { tcx, body, def_id, param_env, .. } = * item;
133
-
134
- // We can use `unsound_ignore_borrow_on_drop` here because custom drop impls are not
135
- // allowed in a const.
136
- //
137
- // FIXME(ecstaticmorse): Someday we want to allow custom drop impls. How do we do this
138
- // without breaking stable code?
139
- let indirectly_mutable = MaybeMutBorrowedLocals :: mut_borrows_only ( tcx, body, param_env)
140
- . unsound_ignore_borrow_on_drop ( )
141
- . into_engine ( tcx, body, def_id)
142
- . iterate_to_fixpoint ( )
143
- . into_results_cursor ( body) ;
144
-
145
- let needs_drop = FlowSensitiveAnalysis :: new ( NeedsDrop , item)
146
- . into_engine ( item. tcx , & item. body , item. def_id )
147
- . iterate_to_fixpoint ( )
148
- . into_results_cursor ( * item. body ) ;
149
-
150
- let has_mut_interior = FlowSensitiveAnalysis :: new ( HasMutInterior , item)
151
- . into_engine ( item. tcx , & item. body , item. def_id )
152
- . iterate_to_fixpoint ( )
153
- . into_results_cursor ( * item. body ) ;
154
-
155
- let qualifs = Qualifs { needs_drop, has_mut_interior, indirectly_mutable } ;
156
-
157
- Validator { span : ccx. body . span , ccx, qualifs }
169
+ pub fn new ( ccx : & ' mir ConstCx < ' mir , ' tcx > ) -> Self {
170
+ Validator { span : ccx. body . span , ccx, qualifs : Default :: default ( ) }
158
171
}
159
172
160
173
pub fn check_body ( & mut self ) {
0 commit comments