@@ -33,42 +33,72 @@ type IndirectlyMutableResults<'mir, 'tcx> =
3333type QualifResults < ' mir , ' tcx , Q > =
3434 dataflow:: ResultsCursor < ' mir , ' tcx , FlowSensitiveAnalysis < ' mir , ' mir , ' tcx , Q > > ;
3535
36+ #[ derive( Default ) ]
3637pub 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 > > ,
4041}
4142
4243impl Qualifs < ' mir , ' tcx > {
4344 fn indirectly_mutable (
4445 & mut self ,
45- _ : & Item < ' mir , ' tcx > ,
46+ ccx : & ' mir ConstCx < ' mir , ' tcx > ,
4647 local : Local ,
4748 location : Location ,
4849 ) -> 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)
5167 }
5268
5369 /// Returns `true` if `local` is `NeedsDrop` at the given `Location`.
5470 ///
5571 /// 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) {
5980 return false ;
6081 }
6182
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)
6494 }
6595
6696 /// Returns `true` if `local` is `HasMutInterior` at the given `Location`.
6797 ///
6898 /// Only updates the cursor if absolutely necessary.
6999 fn has_mut_interior (
70100 & mut self ,
71- item : & Item < ' mir , ' tcx > ,
101+ ccx : & ' mir ConstCx < ' mir , ' tcx > ,
72102 local : Local ,
73103 location : Location ,
74104 ) -> bool {
@@ -77,12 +107,20 @@ impl Qualifs<'mir, 'tcx> {
77107 return false ;
78108 }
79109
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)
83121 }
84122
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 {
86124 // Find the `Return` terminator if one exists.
87125 //
88126 // If no `Return` terminator exists, this MIR is divergent. Just return the conservative
@@ -128,33 +166,8 @@ impl Deref for Validator<'mir, 'tcx> {
128166}
129167
130168impl 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 ( ) }
158171 }
159172
160173 pub fn check_body ( & mut self ) {
0 commit comments