@@ -154,6 +154,49 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
154154 }
155155 Ok ( ( ) )
156156 }
157+
158+ /// returns `true` if a stackframe was pushed
159+ fn global_item (
160+ & mut self ,
161+ def_id : DefId ,
162+ substs : & ' tcx Substs < ' tcx > ,
163+ span : Span ,
164+ mutability : Mutability ,
165+ ) -> EvalResult < ' tcx , bool > {
166+ let instance = self . resolve_associated_const ( def_id, substs) ;
167+ let cid = GlobalId { instance, promoted : None } ;
168+ if self . globals . contains_key ( & cid) {
169+ return Ok ( false ) ;
170+ }
171+ if self . tcx . has_attr ( def_id, "linkage" ) {
172+ // FIXME: check that it's `#[linkage = "extern_weak"]`
173+ trace ! ( "Initializing an extern global with NULL" ) ;
174+ self . globals . insert ( cid, Global :: initialized ( self . tcx . type_of ( def_id) , Value :: ByVal ( PrimVal :: Bytes ( 0 ) ) , mutability) ) ;
175+ return Ok ( false ) ;
176+ }
177+ let mir = self . load_mir ( instance. def ) ?;
178+ self . globals . insert ( cid, Global :: uninitialized ( mir. return_ty ) ) ;
179+ let internally_mutable = !mir. return_ty . is_freeze (
180+ self . tcx ,
181+ ty:: ParamEnv :: empty ( Reveal :: All ) ,
182+ span) ;
183+ let mutability = if mutability == Mutability :: Mutable || internally_mutable {
184+ Mutability :: Mutable
185+ } else {
186+ Mutability :: Immutable
187+ } ;
188+ let cleanup = StackPopCleanup :: MarkStatic ( mutability) ;
189+ let name = ty:: tls:: with ( |tcx| tcx. item_path_str ( def_id) ) ;
190+ trace ! ( "pushing stack frame for global: {}" , name) ;
191+ self . push_stack_frame (
192+ instance,
193+ span,
194+ mir,
195+ Lvalue :: Global ( cid) ,
196+ cleanup,
197+ ) ?;
198+ Ok ( true )
199+ }
157200}
158201
159202// WARNING: make sure that any methods implemented on this type don't ever access ecx.stack
@@ -169,56 +212,19 @@ struct ConstantExtractor<'a, 'b: 'a, 'tcx: 'b, M: Machine<'tcx> + 'a> {
169212}
170213
171214impl < ' a , ' b , ' tcx , M : Machine < ' tcx > > ConstantExtractor < ' a , ' b , ' tcx , M > {
172- fn global_item (
173- & mut self ,
174- def_id : DefId ,
175- substs : & ' tcx Substs < ' tcx > ,
176- span : Span ,
177- mutability : Mutability ,
178- ) {
179- let instance = self . ecx . resolve_associated_const ( def_id, substs) ;
180- let cid = GlobalId { instance, promoted : None } ;
181- if self . ecx . globals . contains_key ( & cid) {
182- return ;
183- }
184- if self . ecx . tcx . has_attr ( def_id, "linkage" ) {
185- trace ! ( "Initializing an extern global with NULL" ) ;
186- self . ecx . globals . insert ( cid, Global :: initialized ( self . ecx . tcx . type_of ( def_id) , Value :: ByVal ( PrimVal :: Bytes ( 0 ) ) , mutability) ) ;
187- return ;
188- }
189- self . try ( |this| {
190- let mir = this. ecx . load_mir ( instance. def ) ?;
191- this. ecx . globals . insert ( cid, Global :: uninitialized ( mir. return_ty ) ) ;
192- let internally_mutable = !mir. return_ty . is_freeze (
193- this. ecx . tcx ,
194- ty:: ParamEnv :: empty ( Reveal :: All ) ,
195- span) ;
196- let mutability = if mutability == Mutability :: Mutable || internally_mutable {
197- Mutability :: Mutable
198- } else {
199- Mutability :: Immutable
200- } ;
201- let cleanup = StackPopCleanup :: MarkStatic ( mutability) ;
202- let name = ty:: tls:: with ( |tcx| tcx. item_path_str ( def_id) ) ;
203- trace ! ( "pushing stack frame for global: {}" , name) ;
204- this. ecx . push_stack_frame (
205- instance,
206- span,
207- mir,
208- Lvalue :: Global ( cid) ,
209- cleanup,
210- )
211- } ) ;
212- }
213-
214- fn try < F : FnOnce ( & mut Self ) -> EvalResult < ' tcx > > ( & mut self , f : F ) {
215- if let Ok ( ref mut n) = * self . new_constants {
216- * n += 1 ;
217- } else {
218- return ;
219- }
220- if let Err ( e) = f ( self ) {
221- * self . new_constants = Err ( e) ;
215+ fn try < F : FnOnce ( & mut Self ) -> EvalResult < ' tcx , bool > > ( & mut self , f : F ) {
216+ // previous constant errored
217+ let n = match * self . new_constants {
218+ Ok ( n) => n,
219+ Err ( _) => return ,
220+ } ;
221+ match f ( self ) {
222+ // everything ok + a new stackframe
223+ Ok ( true ) => * self . new_constants = Ok ( n + 1 ) ,
224+ // constant correctly evaluated, but no new stackframe
225+ Ok ( false ) => { } ,
226+ // constant eval errored
227+ Err ( err) => * self . new_constants = Err ( err) ,
222228 }
223229 }
224230}
@@ -230,7 +236,7 @@ impl<'a, 'b, 'tcx, M: Machine<'tcx>> Visitor<'tcx> for ConstantExtractor<'a, 'b,
230236 // already computed by rustc
231237 mir:: Literal :: Value { .. } => { }
232238 mir:: Literal :: Item { def_id, substs } => {
233- self . global_item ( def_id, substs, constant. span , Mutability :: Immutable ) ;
239+ self . try ( |this| this . ecx . global_item ( def_id, substs, constant. span , Mutability :: Immutable ) ) ;
234240 } ,
235241 mir:: Literal :: Promoted { index } => {
236242 let cid = GlobalId {
@@ -250,7 +256,8 @@ impl<'a, 'b, 'tcx, M: Machine<'tcx>> Visitor<'tcx> for ConstantExtractor<'a, 'b,
250256 mir,
251257 Lvalue :: Global ( cid) ,
252258 StackPopCleanup :: MarkStatic ( Mutability :: Immutable ) ,
253- )
259+ ) ?;
260+ Ok ( true )
254261 } ) ;
255262 }
256263 }
@@ -270,7 +277,7 @@ impl<'a, 'b, 'tcx, M: Machine<'tcx>> Visitor<'tcx> for ConstantExtractor<'a, 'b,
270277 if let Some ( node_item) = self . ecx . tcx . hir . get_if_local ( def_id) {
271278 if let hir:: map:: Node :: NodeItem ( & hir:: Item { ref node, .. } ) = node_item {
272279 if let hir:: ItemStatic ( _, m, _) = * node {
273- self . global_item ( def_id, substs, span, if m == hir:: MutMutable { Mutability :: Mutable } else { Mutability :: Immutable } ) ;
280+ self . try ( |this| this . ecx . global_item ( def_id, substs, span, if m == hir:: MutMutable { Mutability :: Mutable } else { Mutability :: Immutable } ) ) ;
274281 return ;
275282 } else {
276283 bug ! ( "static def id doesn't point to static" ) ;
@@ -281,7 +288,7 @@ impl<'a, 'b, 'tcx, M: Machine<'tcx>> Visitor<'tcx> for ConstantExtractor<'a, 'b,
281288 } else {
282289 let def = self . ecx . tcx . describe_def ( def_id) . expect ( "static not found" ) ;
283290 if let hir:: def:: Def :: Static ( _, mutable) = def {
284- self . global_item ( def_id, substs, span, if mutable { Mutability :: Mutable } else { Mutability :: Immutable } ) ;
291+ self . try ( |this| this . ecx . global_item ( def_id, substs, span, if mutable { Mutability :: Mutable } else { Mutability :: Immutable } ) ) ;
285292 } else {
286293 bug ! ( "static found but isn't a static: {:?}" , def) ;
287294 }
0 commit comments