Change:
I saw that was closed when was merged so I thought it would fix the same error on my own code as well however as of nightly: it still happens. Code: Playground: From what I can tell its an alignment issue because changing id from a to a fixes the issue.

Discussion:
variant: Option<usize>, field: mir::Field, base_ty: Ty<'tcx>, <del> ) -> EvalResult<'tcx, Option<(Value, Ty<'tcx>)>> { </del> <ins> ) -> EvalResult<'tcx, ValTy<'tcx>> { </ins> let mut base_layout = self.layout_of(base_ty)?; if let Some(variant_index) = variant { base_layout = base_layout.for_variant(self, variant_index);

let field_index = field.index(); let field = base_layout.field(self, field_index)?; if field.size.bytes() == 0 { <del> return Ok(Some((Value::Scalar(Scalar::undef()), field.ty))) </del> <ins> return Ok(ValTy { value: Value::Scalar(Scalar::undef()), ty: field.ty, }); </ins> } let offset = base_layout.fields.offset(field_index); <del> match base { </del> <ins> let value = match base { </ins> // the field covers the entire type Value::ScalarPair(..) | <del> Value::Scalar(_) if offset.bytes() == 0 && field.size == base_layout.size => Ok(Some((base, field.ty))), // split fat pointers, 2 element tuples, ... Value::ScalarPair(a, b) if base_layout.fields.count() == 2 => { let val = [a, b][field_index]; Ok(Some((Value::Scalar(val), field.ty))) </del> <ins> Value::Scalar(_) if offset.bytes() == 0 && field.size == base_layout.size => base, // extract fields from types with `ScalarPair` ABI Value::ScalarPair(a, b) => { let val = if offset.bytes() == 0 { a } else { b }; Value::Scalar(val) </ins> }, <del> // FIXME(oli-obk): figure out whether we should be calling `try_read_value` here _ => Ok(None), } </del> <ins> Value::ByRef(base_ptr, align) => { let offset = base_layout.fields.offset(field_index); let ptr = base_ptr.ptr_offset(offset, self)?; let align = align.min(base_layout.align).min(field.align); assert!(!field.is_unsized()); Value::ByRef(ptr, align) }, Value::Scalar(val) => bug!("field access on non aggregate {:?}, {:?}", val, base_ty), }; Ok(ValTy { value, ty: field.ty, }) </ins> } fn try_read_place_projection(

}; let base_ty = self.place_ty(&proj.base); match proj.elem { <del> Field(field, _) => Ok(self.read_field(base, None, field, base_ty)?.map(|(f, _)| f)), </del> <ins> Field(field, _) => Ok(Some(self.read_field(base, None, field, base_ty)?.value)), </ins> // The NullablePointer cases should work fine, need to take care for normal enums Downcast(..) | Subslice { .. } |

use syntax::codemap::Span; use rustc_target::spec::abi::Abi; <del> use rustc::mir::interpret::{EvalResult, Scalar, Value}; </del> <ins> use rustc::mir::interpret::EvalResult; </ins> use super::{EvalContext, Place, Machine, ValTy}; use rustc_data_structures::indexed_vec::Idx;

// unpack and write all other args let layout = self.layout_of(args[1].ty)?; <del> if let ty::TyTuple(..) = args[1].ty.sty { </del> <ins> if let ty::TyTuple(_) = args[1].ty.sty { if layout.is_zst() { // Nothing to do, no need to unpack zsts return Ok(()); } </ins> if self.frame().mir.args_iter().count() == layout.fields.count() + 1 { <del> match args[1].value { Value::ByRef(ptr, align) => { for (i, arg_local) in arg_locals.enumerate() { let field = layout.field(&self, i)?; let offset = layout.fields.offset(i); let arg = Value::ByRef(ptr.ptr_offset(offset, &self)?, align.min(field.align)); let dest = self.eval_place(&mir::Place::Local(arg_local))?; trace!( "writing arg {:?} to {:?} (type: {})", arg, dest, field.ty ); let valty = ValTy { value: arg, ty: field.ty, }; self.write_value(valty, dest)?; } } Value::Scalar(Scalar::Bits { defined: 0, .. }) => {} other => { trace!("{:#?}, {:#?}", other, layout); let mut layout = layout; 'outer: loop { for i in 0..layout.fields.count() { let field = layout.field(&self, i)?; if layout.fields.offset(i).bytes() == 0 && layout.size == field.size { layout = field; continue 'outer; } } break; } { let mut write_next = |value| { let dest = self.eval_place(&mir::Place::Local( arg_locals.next().unwrap(), ))?; let valty = ValTy { value: Value::Scalar(value), ty: layout.ty, }; self.write_value(valty, dest) }; match other { Value::Scalar(value) | Value::ScalarPair(value, _) => write_next(value)?, _ => unreachable!(), } if let Value::ScalarPair(_, value) = other { write_next(value)?; } } assert!(arg_locals.next().is_none()); } </del> <ins> for (i, arg_local) in arg_locals.enumerate() { let field = mir::Field::new(i); let valty = self.read_field(args[1].value, None, field, args[1].ty)?; let dest = self.eval_place(&mir::Place::Local(arg_local))?; self.write_value(valty, dest)?; </ins> } } else { trace!("manual impl of rust-call ABI");

use rustc_data_structures::indexed_vec::IndexVec; use rustc::ty::ParamEnv; use rustc::ty::layout::{ <del> LayoutOf, TyLayout, LayoutError, LayoutCx, </del> <ins> LayoutOf, TyLayout, LayoutError, </ins> HasTyCtxt, TargetDataLayout, HasDataLayout, };

ProjectionElem::Field(field, _) => { trace!("field proj on {:?}", proj.base); let (base, ty, span) = self.eval_place(&proj.base)?; <del> match base { Value::ScalarPair(a, b) => { trace!("by val pair: {:?}, {:?}", a, b); let base_layout = self.tcx.layout_of(self.param_env.and(ty)).ok()?; trace!("layout computed"); use rustc_data_structures::indexed_vec::Idx; let field_index = field.index(); let val = [a, b][field_index]; let cx = LayoutCx { tcx: self.tcx, param_env: self.param_env, }; let field = base_layout.field(cx, field_index).ok()?; trace!("projection resulted in: {:?}", val); Some((Value::Scalar(val), field.ty, span)) }, _ => None, } </del> <ins> let valty = self.use_ecx(span, |this| { this.ecx.read_field(base, None, field, ty) })?; Some((valty.value, valty.ty, span)) </ins> }, _ => None, },

<ins> // Copyright 2018 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your // option. This file may not be copied, modified, or distributed // except according to those terms. // compile-pass // https://github.com/rust-lang/rust/issues/51300 #[derive(PartialEq, Eq, Clone, Copy)] pub struct Stat { pub id: u8, pub index: usize, } impl Stat { pub const STUDENT_HAPPINESS: Stat = Stat{ id: 0, index: 0, }; pub const STUDENT_HUNGER: Stat = Stat{ id: 0, index: Self::STUDENT_HAPPINESS.index + 1, }; } pub fn from_index(id: u8, index: usize) -> Option<Stat> { let stat = Stat{id, index}; match stat { Stat::STUDENT_HAPPINESS => Some(Stat::STUDENT_HAPPINESS), Stat::STUDENT_HUNGER => Some(Stat::STUDENT_HUNGER), _ => None, } } fn main() { } </ins>