@@ -17,8 +17,7 @@ use syntax_pos::{Span, DUMMY_SP};
1717use rustc:: ty:: subst:: InternalSubsts ;
1818use rustc_data_structures:: indexed_vec:: IndexVec ;
1919use rustc:: ty:: layout:: {
20- LayoutOf , TyLayout , LayoutError ,
21- HasTyCtxt , TargetDataLayout , HasDataLayout ,
20+ LayoutOf , TyLayout , LayoutError , HasTyCtxt , TargetDataLayout , HasDataLayout , Size ,
2221} ;
2322
2423use crate :: interpret:: {
@@ -333,6 +332,12 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
333332 this. ecx . operand_field ( eval, field. index ( ) as u64 )
334333 } ) ?;
335334 } ,
335+ ProjectionElem :: Deref => {
336+ trace ! ( "processing deref" ) ;
337+ eval = self . use_ecx ( source_info, |this| {
338+ this. ecx . deref_operand ( eval)
339+ } ) ?. into ( ) ;
340+ }
336341 // We could get more projections by using e.g., `operand_projection`,
337342 // but we do not even have the stack frame set up properly so
338343 // an `Index` projection would throw us off-track.
@@ -363,8 +368,12 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
363368 Rvalue :: Use ( ref op) => {
364369 self . eval_operand ( op, source_info)
365370 } ,
371+ Rvalue :: Ref ( _, _, ref place) => {
372+ let src = self . eval_place ( place, source_info) ?;
373+ let mplace = src. try_as_mplace ( ) . ok ( ) ?;
374+ Some ( ImmTy :: from_scalar ( mplace. ptr . into ( ) , place_layout) . into ( ) )
375+ } ,
366376 Rvalue :: Repeat ( ..) |
367- Rvalue :: Ref ( ..) |
368377 Rvalue :: Aggregate ( ..) |
369378 Rvalue :: NullaryOp ( NullOp :: Box , _) |
370379 Rvalue :: Discriminant ( ..) => None ,
@@ -376,10 +385,30 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
376385 this. ecx . cast ( op, kind, dest. into ( ) ) ?;
377386 Ok ( dest. into ( ) )
378387 } )
379- }
388+ } ,
389+ Rvalue :: Len ( ref place) => {
390+ let place = self . eval_place ( & place, source_info) ?;
391+ let mplace = place. try_as_mplace ( ) . ok ( ) ?;
392+
393+ if let ty:: Slice ( _) = mplace. layout . ty . sty {
394+ let len = mplace. meta . unwrap ( ) . to_usize ( & self . ecx ) . unwrap ( ) ;
380395
381- // FIXME(oli-obk): evaluate static/constant slice lengths
382- Rvalue :: Len ( _) => None ,
396+ Some ( ImmTy {
397+ imm : Immediate :: Scalar (
398+ Scalar :: from_uint (
399+ len,
400+ Size :: from_bits (
401+ self . tcx . sess . target . usize_ty . bit_width ( ) . unwrap ( ) as u64
402+ )
403+ ) . into ( ) ,
404+ ) ,
405+ layout : self . tcx . layout_of ( self . param_env . and ( self . tcx . types . usize ) ) . ok ( ) ?,
406+ } . into ( ) )
407+ } else {
408+ trace ! ( "not slice: {:?}" , mplace. layout. ty. sty) ;
409+ None
410+ }
411+ } ,
383412 Rvalue :: NullaryOp ( NullOp :: SizeOf , ty) => {
384413 type_size_of ( self . tcx , self . param_env , ty) . and_then ( |n| Some (
385414 ImmTy {
@@ -525,12 +554,10 @@ impl<'a, 'mir, 'tcx> ConstPropagator<'a, 'mir, 'tcx> {
525554 source_info : SourceInfo ,
526555 ) {
527556 trace ! ( "attepting to replace {:?} with {:?}" , rval, value) ;
528- self . ecx . validate_operand (
529- value,
530- vec ! [ ] ,
531- None ,
532- true ,
533- ) . expect ( "value should already be a valid const" ) ;
557+ if let Err ( e) = self . ecx . validate_operand ( value, vec ! [ ] , None , true ) {
558+ trace ! ( "validation error, attempt failed: {:?}" , e) ;
559+ return ;
560+ }
534561
535562 // FIXME> figure out what tho do when try_read_immediate fails
536563 let imm = self . use_ecx ( source_info, |this| {
0 commit comments