@@ -290,7 +290,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
290290 Ok ( val) => val,
291291 Err ( err) => match err. kind {
292292 EvalErrorKind :: PointerOutOfBounds { .. } |
293- EvalErrorKind :: ReadUndefBytes =>
293+ EvalErrorKind :: ReadUndefBytes ( _ ) =>
294294 return validation_failure ! (
295295 "uninitialized or out-of-bounds memory" , path
296296 ) ,
@@ -333,16 +333,16 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
333333 // The fields don't need to correspond to any bit pattern of the union's fields.
334334 // See https://github.com/rust-lang/rust/issues/32836#issuecomment-406875389
335335 } ,
336- layout:: FieldPlacement :: Array { .. } if !dest. layout . is_zst ( ) => {
336+ layout:: FieldPlacement :: Array { stride , .. } if !dest. layout . is_zst ( ) => {
337337 let dest = dest. to_mem_place ( ) ; // non-ZST array/slice/str cannot be immediate
338- // Special handling for strings to verify UTF-8
339338 match dest. layout . ty . sty {
339+ // Special handling for strings to verify UTF-8
340340 ty:: Str => {
341341 match self . read_str ( dest) {
342342 Ok ( _) => { } ,
343343 Err ( err) => match err. kind {
344344 EvalErrorKind :: PointerOutOfBounds { .. } |
345- EvalErrorKind :: ReadUndefBytes =>
345+ EvalErrorKind :: ReadUndefBytes ( _ ) =>
346346 // The error here looks slightly different than it does
347347 // for slices, because we do not report the index into the
348348 // str at which we are OOB.
@@ -356,6 +356,55 @@ impl<'a, 'mir, 'tcx, M: Machine<'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> {
356356 }
357357 }
358358 }
359+ // Special handling for arrays/slices of builtin integer types
360+ ty:: Array ( tys, ..) | ty:: Slice ( tys) if {
361+ // This optimization applies only for integer types
362+ match tys. sty {
363+ ty:: Int ( ..) | ty:: Uint ( ..) => true ,
364+ _ => false ,
365+ }
366+ } => {
367+ // This is the length of the array/slice.
368+ let len = dest. len ( self ) ?;
369+ // Since primitive types are naturally aligned and tightly packed in arrays,
370+ // we can use the stride to get the size of the integral type.
371+ let ty_size = stride. bytes ( ) ;
372+ // This is the size in bytes of the whole array.
373+ let size = Size :: from_bytes ( ty_size * len) ;
374+
375+ match self . memory . read_bytes ( dest. ptr , size) {
376+ // In the happy case, we needn't check anything else.
377+ Ok ( _) => { } ,
378+ // Some error happened, try to provide a more detailed description.
379+ Err ( err) => {
380+ // For some errors we might be able to provide extra information
381+ match err. kind {
382+ EvalErrorKind :: ReadUndefBytes ( offset) => {
383+ // Some byte was undefined, determine which
384+ // element that byte belongs to so we can
385+ // provide an index.
386+ let i = ( offset. bytes ( ) / ty_size) as usize ;
387+ path. push ( PathElem :: ArrayElem ( i) ) ;
388+
389+ return validation_failure ! (
390+ "undefined bytes" , path
391+ )
392+ } ,
393+ EvalErrorKind :: PointerOutOfBounds { allocation_size, .. } => {
394+ // If the array access is out-of-bounds, the first
395+ // undefined access is the after the end of the array.
396+ let i = ( allocation_size. bytes ( ) * ty_size) as usize ;
397+ path. push ( PathElem :: ArrayElem ( i) ) ;
398+ } ,
399+ _ => ( ) ,
400+ }
401+
402+ return validation_failure ! (
403+ "uninitialized or out-of-bounds memory" , path
404+ )
405+ }
406+ }
407+ } ,
359408 _ => {
360409 // This handles the unsized case correctly as well, as well as
361410 // SIMD an all sorts of other array-like types.
0 commit comments