@@ -222,15 +222,24 @@ struct MirConstContext<'a, 'tcx: 'a> {
222222 substs : & ' tcx Substs < ' tcx > ,
223223
224224 /// Values of locals in a constant or const fn.
225- locals : IndexVec < mir:: Local , Option < Const < ' tcx > > >
225+ locals : IndexVec < mir:: Local , Option < Result < Const < ' tcx > , ConstEvalErr < ' tcx > > > >
226226}
227227
228+ fn add_err < ' tcx , U , V > ( failure : & mut Result < U , ConstEvalErr < ' tcx > > ,
229+ value : & Result < V , ConstEvalErr < ' tcx > > )
230+ {
231+ if let & Err ( ref err) = value {
232+ if failure. is_ok ( ) {
233+ * failure = Err ( err. clone ( ) ) ;
234+ }
235+ }
236+ }
228237
229238impl < ' a , ' tcx > MirConstContext < ' a , ' tcx > {
230239 fn new ( ccx : & ' a CrateContext < ' a , ' tcx > ,
231240 mir : & ' a mir:: Mir < ' tcx > ,
232241 substs : & ' tcx Substs < ' tcx > ,
233- args : IndexVec < mir:: Local , Const < ' tcx > > )
242+ args : IndexVec < mir:: Local , Result < Const < ' tcx > , ConstEvalErr < ' tcx > > > )
234243 -> MirConstContext < ' a , ' tcx > {
235244 let mut context = MirConstContext {
236245 ccx : ccx,
@@ -249,7 +258,7 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
249258 fn trans_def ( ccx : & ' a CrateContext < ' a , ' tcx > ,
250259 def_id : DefId ,
251260 substs : & ' tcx Substs < ' tcx > ,
252- args : IndexVec < mir:: Local , Const < ' tcx > > )
261+ args : IndexVec < mir:: Local , Result < Const < ' tcx > , ConstEvalErr < ' tcx > > > )
253262 -> Result < Const < ' tcx > , ConstEvalErr < ' tcx > > {
254263 let instance = monomorphize:: resolve ( ccx. shared ( ) , def_id, substs) ;
255264 let mir = ccx. tcx ( ) . instance_mir ( instance. def ) ;
@@ -278,10 +287,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
278287 mir:: StatementKind :: Assign ( ref dest, ref rvalue) => {
279288 let ty = dest. ty ( self . mir , tcx) ;
280289 let ty = self . monomorphize ( & ty) . to_ty ( tcx) ;
281- match self . const_rvalue ( rvalue, ty, span) {
282- Ok ( value) => self . store ( dest, value, span) ,
283- Err ( err) => if failure. is_ok ( ) { failure = Err ( err) ; }
284- }
290+ let value = self . const_rvalue ( rvalue, ty, span) ;
291+ add_err ( & mut failure, & value) ;
292+ self . store ( dest, value, span) ;
285293 }
286294 mir:: StatementKind :: StorageLive ( _) |
287295 mir:: StatementKind :: StorageDead ( _) |
@@ -301,9 +309,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
301309 mir:: TerminatorKind :: Goto { target } => target,
302310 mir:: TerminatorKind :: Return => {
303311 failure?;
304- return Ok ( self . locals [ mir:: RETURN_POINTER ] . unwrap_or_else ( || {
312+ return self . locals [ mir:: RETURN_POINTER ] . clone ( ) . unwrap_or_else ( || {
305313 span_bug ! ( span, "no returned value in constant" ) ;
306- } ) ) ;
314+ } ) ;
307315 }
308316
309317 mir:: TerminatorKind :: Assert { ref cond, expected, ref msg, target, .. } => {
@@ -342,33 +350,30 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
342350
343351 let mut arg_vals = IndexVec :: with_capacity ( args. len ( ) ) ;
344352 for arg in args {
345- match self . const_operand ( arg, span) {
346- Ok ( arg) => { arg_vals. push ( arg) ; } ,
347- Err ( err) => if failure. is_ok ( ) { failure = Err ( err) ; }
348- }
353+ let arg_val = self . const_operand ( arg, span) ;
354+ add_err ( & mut failure, & arg_val) ;
355+ arg_vals. push ( arg_val) ;
349356 }
350357 if let Some ( ( ref dest, target) ) = * destination {
351- if fn_ty. fn_sig ( tcx) . abi ( ) == Abi :: RustIntrinsic {
352- let value = match & tcx. item_name ( def_id) . as_str ( ) [ ..] {
358+ let result = if fn_ty. fn_sig ( tcx) . abi ( ) == Abi :: RustIntrinsic {
359+ match & tcx. item_name ( def_id) . as_str ( ) [ ..] {
353360 "size_of" => {
354361 let llval = C_uint ( self . ccx ,
355362 self . ccx . size_of ( substs. type_at ( 0 ) ) ) ;
356- Const :: new ( llval, tcx. types . usize )
363+ Ok ( Const :: new ( llval, tcx. types . usize ) )
357364 }
358365 "min_align_of" => {
359366 let llval = C_uint ( self . ccx ,
360367 self . ccx . align_of ( substs. type_at ( 0 ) ) ) ;
361- Const :: new ( llval, tcx. types . usize )
368+ Ok ( Const :: new ( llval, tcx. types . usize ) )
362369 }
363370 _ => span_bug ! ( span, "{:?} in constant" , terminator. kind)
364- } ;
365- self . store ( dest, value, span) ;
366- } else {
367- match MirConstContext :: trans_def ( self . ccx , def_id, substs, arg_vals) {
368- Ok ( value) => self . store ( dest, value, span) ,
369- Err ( err) => if failure. is_ok ( ) { failure = Err ( err) ; }
370371 }
371- }
372+ } else {
373+ MirConstContext :: trans_def ( self . ccx , def_id, substs, arg_vals)
374+ } ;
375+ add_err ( & mut failure, & result) ;
376+ self . store ( dest, result, span) ;
372377 target
373378 } else {
374379 span_bug ! ( span, "diverging {:?} in constant" , terminator. kind) ;
@@ -379,7 +384,10 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
379384 }
380385 }
381386
382- fn store ( & mut self , dest : & mir:: Lvalue < ' tcx > , value : Const < ' tcx > , span : Span ) {
387+ fn store ( & mut self ,
388+ dest : & mir:: Lvalue < ' tcx > ,
389+ value : Result < Const < ' tcx > , ConstEvalErr < ' tcx > > ,
390+ span : Span ) {
383391 if let mir:: Lvalue :: Local ( index) = * dest {
384392 self . locals [ index] = Some ( value) ;
385393 } else {
@@ -392,9 +400,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
392400 let tcx = self . ccx . tcx ( ) ;
393401
394402 if let mir:: Lvalue :: Local ( index) = * lvalue {
395- return Ok ( self . locals [ index] . unwrap_or_else ( || {
403+ return self . locals [ index] . clone ( ) . unwrap_or_else ( || {
396404 span_bug ! ( span, "{:?} not initialized" , lvalue)
397- } ) . as_lvalue ( ) ) ;
405+ } ) . map ( |v| v . as_lvalue ( ) ) ;
398406 }
399407
400408 let lvalue = match * lvalue {
0 commit comments