diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs index 57363441493..aa189744701 100644 --- a/src/librustc/middle/ty/mod.rs +++ b/src/librustc/middle/ty/mod.rs @@ -1731,6 +1731,13 @@ impl<'tcx, 'container> VariantDefData<'tcx, 'container> { self.fields.iter().find(|f| f.name == name) } + #[inline] + pub fn index_of_field_named(&self, + name: ast::Name) + -> Option { + self.fields.iter().position(|f| f.name == name) + } + #[inline] pub fn field_named(&self, name: ast::Name) -> &FieldDefData<'tcx, 'container> { self.find_field_named(name).unwrap() diff --git a/src/librustc_mir/build/expr/as_rvalue.rs b/src/librustc_mir/build/expr/as_rvalue.rs index c5831b881ab..23ca22129fd 100644 --- a/src/librustc_mir/build/expr/as_rvalue.rs +++ b/src/librustc_mir/build/expr/as_rvalue.rs @@ -149,16 +149,19 @@ impl<'a,'tcx> Builder<'a,'tcx> { block.and(Rvalue::Aggregate(AggregateKind::Closure(closure_id, substs), upvars)) } ExprKind::Adt { adt_def, variant_index, substs, fields, base } => { // see (*) above - // first process the set of fields + // first process the set of fields that were provided + // (evaluating them in order given by user) let fields_map: FnvHashMap<_, _> = fields.into_iter() .map(|f| (f.name, unpack!(block = this.as_operand(block, f.expr)))) .collect(); - let field_names = this.hir.fields(adt_def, variant_index); - + // if base expression is given, evaluate it now let base = base.map(|base| unpack!(block = this.as_lvalue(block, base))); + // get list of all fields that we will need + let field_names = this.hir.all_fields(adt_def, variant_index); + // for the actual values we use, take either the // expr the user specified or, if they didn't // specify something for this field name, create a diff --git a/src/librustc_mir/repr.rs b/src/librustc_mir/repr.rs index 54e00dc0a68..5bf326ba5a5 100644 --- a/src/librustc_mir/repr.rs +++ b/src/librustc_mir/repr.rs @@ -443,10 +443,19 @@ pub type LvalueProjection<'tcx> = pub type LvalueElem<'tcx> = ProjectionElem<'tcx,Operand<'tcx>>; +/// Index into the list of fields found in a `VariantDef` #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] -pub enum Field { - Named(Name), - Indexed(usize), +pub struct Field(u32); + +impl Field { + pub fn new(value: usize) -> Field { + assert!(value < (u32::MAX) as usize); + Field(value as u32) + } + + pub fn index(self) -> usize { + self.0 as usize + } } impl<'tcx> Lvalue<'tcx> { @@ -491,10 +500,8 @@ impl<'tcx> Debug for Lvalue<'tcx> { write!(fmt,"({:?} as {:?})", data.base, variant_index), ProjectionElem::Deref => write!(fmt,"(*{:?})", data.base), - ProjectionElem::Field(Field::Named(name)) => - write!(fmt,"{:?}.{:?}", data.base, name), - ProjectionElem::Field(Field::Indexed(index)) => - write!(fmt,"{:?}.{:?}", data.base, index), + ProjectionElem::Field(field) => + write!(fmt,"{:?}.{:?}", data.base, field.index()), ProjectionElem::Index(ref index) => write!(fmt,"{:?}[{:?}]", data.base, index), ProjectionElem::ConstantIndex { offset, min_length, from_end: false } =>