diff --git a/src/Cargo.lock b/src/Cargo.lock index 32304c81182f1..a4246b26c2268 100644 --- a/src/Cargo.lock +++ b/src/Cargo.lock @@ -2246,6 +2246,7 @@ version = "0.0.0" dependencies = [ "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc 0.0.0", + "rustc_data_structures 0.0.0", "rustc_mir 0.0.0", "rustc_target 0.0.0", "syntax 0.0.0", @@ -2400,6 +2401,7 @@ dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", + "rustc_data_structures 0.0.0", "serialize 0.0.0", ] diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 0a5b1e184deec..d2be0e4dcb9b9 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -11,9 +11,10 @@ use hir::def::Def; use hir::def_id::DefId; use ty::{self, Ty, TyCtxt}; -use ty::layout::{LayoutError, Pointer, SizeSkeleton}; +use ty::layout::{LayoutError, Pointer, SizeSkeleton, VariantIdx}; use rustc_target::spec::abi::Abi::RustIntrinsic; +use rustc_data_structures::indexed_vec::Idx; use syntax_pos::Span; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use hir; @@ -48,10 +49,13 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if def.variants.len() == 2 && !def.repr.c() && def.repr.int.is_none() { let data_idx; - if def.variants[0].fields.is_empty() { - data_idx = 1; - } else if def.variants[1].fields.is_empty() { - data_idx = 0; + let one = VariantIdx::new(1); + let zero = VariantIdx::new(0); + + if def.variants[zero].fields.is_empty() { + data_idx = one; + } else if def.variants[one].fields.is_empty() { + data_idx = zero; } else { return ty; } diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 9d3f37bc36a9d..59ef8fa14484b 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -76,6 +76,7 @@ use hir::def::{Def, CtorKind}; use ty::adjustment; use ty::{self, Ty, TyCtxt}; use ty::fold::TypeFoldable; +use ty::layout::VariantIdx; use hir::{MutImmutable, MutMutable, PatKind}; use hir::pat_util::EnumerateAndAdjustIterator; @@ -87,6 +88,7 @@ use std::borrow::Cow; use std::fmt; use std::hash::{Hash, Hasher}; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::indexed_vec::Idx; use std::rc::Rc; use util::nodemap::ItemLocalSet; @@ -227,7 +229,7 @@ impl<'tcx> cmt_<'tcx> { } _ => { assert_eq!(adt_def.variants.len(), 1); - &adt_def.variants[0] + &adt_def.variants[VariantIdx::new(0)] } }; Some((adt_def, &variant_def.fields[field_index])) diff --git a/src/librustc/mir/mod.rs b/src/librustc/mir/mod.rs index 8a32e8f46c290..9a0b1c68ddcd5 100644 --- a/src/librustc/mir/mod.rs +++ b/src/librustc/mir/mod.rs @@ -40,6 +40,7 @@ use syntax_pos::{Span, DUMMY_SP}; use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor}; use ty::subst::{CanonicalUserSubsts, Subst, Substs}; use ty::{self, AdtDef, CanonicalTy, ClosureSubsts, GeneratorSubsts, Region, Ty, TyCtxt}; +use ty::layout::VariantIdx; use util::ppaux; pub use mir::interpret::AssertMessage; @@ -1753,7 +1754,7 @@ pub enum StatementKind<'tcx> { /// Write the discriminant for a variant to the enum Place. SetDiscriminant { place: Place<'tcx>, - variant_index: usize, + variant_index: VariantIdx, }, /// Start a live range for the storage of the local. @@ -1939,7 +1940,7 @@ pub enum ProjectionElem<'tcx, V, T> { /// "Downcast" to a variant of an ADT. Currently, we only introduce /// this for ADTs with more than one variant. It may be better to /// just introduce it always, or always for enums. - Downcast(&'tcx AdtDef, usize), + Downcast(&'tcx AdtDef, VariantIdx), } /// Alias for projections as they appear in places, where the base is a place @@ -1950,6 +1951,11 @@ pub type PlaceProjection<'tcx> = Projection<'tcx, Place<'tcx>, Local, Ty<'tcx>>; /// and the index is a local. pub type PlaceElem<'tcx> = ProjectionElem<'tcx, Local, Ty<'tcx>>; +// at least on 64 bit systems, `PlaceElem` should not be larger than two pointers +static_assert!(PROJECTION_ELEM_IS_2_PTRS_LARGE: + mem::size_of::>() <= 16 +); + /// Alias for projections as they appear in `UserTypeProjection`, where we /// need neither the `V` parameter for `Index` nor the `T` for `Field`. pub type ProjectionKind<'tcx> = ProjectionElem<'tcx, (), ()>; @@ -1969,7 +1975,7 @@ impl<'tcx> Place<'tcx> { self.elem(ProjectionElem::Deref) } - pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: usize) -> Place<'tcx> { + pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Place<'tcx> { self.elem(ProjectionElem::Downcast(adt_def, variant_index)) } @@ -2211,7 +2217,7 @@ pub enum AggregateKind<'tcx> { /// active field index would identity the field `c` Adt( &'tcx AdtDef, - usize, + VariantIdx, &'tcx Substs<'tcx>, Option>, Option, diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index f773f46b6f58c..baa88dba45915 100644 --- a/src/librustc/mir/tcx.rs +++ b/src/librustc/mir/tcx.rs @@ -16,6 +16,7 @@ use mir::*; use ty::subst::{Subst, Substs}; use ty::{self, AdtDef, Ty, TyCtxt}; +use ty::layout::VariantIdx; use hir; use ty::util::IntTypeExt; @@ -27,9 +28,13 @@ pub enum PlaceTy<'tcx> { /// Downcast to a particular variant of an enum. Downcast { adt_def: &'tcx AdtDef, substs: &'tcx Substs<'tcx>, - variant_index: usize }, + variant_index: VariantIdx }, } +static_assert!(PLACE_TY_IS_3_PTRS_LARGE: + mem::size_of::>() <= 24 +); + impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { pub fn from_ty(ty: Ty<'tcx>) -> PlaceTy<'tcx> { PlaceTy::Ty { ty } @@ -54,7 +59,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { pub fn field_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, f: &Field) -> Ty<'tcx> { // Pass `0` here so it can be used as a "default" variant_index in first arm below - let answer = match (self, 0) { + let answer = match (self, VariantIdx::new(0)) { (PlaceTy::Ty { ty: &ty::TyS { sty: ty::TyKind::Adt(adt_def, substs), .. } }, variant_index) | (PlaceTy::Downcast { adt_def, substs, variant_index }, _) => { @@ -134,7 +139,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> { match self.to_ty(tcx).sty { ty::Adt(adt_def, substs) => { assert!(adt_def.is_enum()); - assert!(index < adt_def.variants.len()); + assert!(index.as_usize() < adt_def.variants.len()); assert_eq!(adt_def, adt_def1); PlaceTy::Downcast { adt_def, substs, diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs index 82095a2f5b01d..a86a56a45cd64 100644 --- a/src/librustc/ty/context.rs +++ b/src/librustc/ty/context.rs @@ -45,7 +45,7 @@ use ty::RegionKind; use ty::{TyVar, TyVid, IntVar, IntVid, FloatVar, FloatVid}; use ty::TyKind::*; use ty::GenericParamDefKind; -use ty::layout::{LayoutDetails, TargetDataLayout}; +use ty::layout::{LayoutDetails, TargetDataLayout, VariantIdx}; use ty::query; use ty::steal::Steal; use ty::BindingMode; @@ -1009,7 +1009,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn alloc_adt_def(self, did: DefId, kind: AdtKind, - variants: Vec, + variants: IndexVec, repr: ReprOptions) -> &'gcx ty::AdtDef { let def = ty::AdtDef::new(self, did, kind, variants, repr); diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 5aeba652f3228..877bd5a82e6a0 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -23,6 +23,7 @@ use std::mem; use std::ops::Bound; use ich::StableHashingContext; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use rustc_data_structures::stable_hasher::{HashStable, StableHasher, StableHasherResult}; @@ -229,7 +230,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let b_offset = a.value.size(dl).abi_align(b.value.align(dl)); let size = (b_offset + b.value.size(dl)).abi_align(align); LayoutDetails { - variants: Variants::Single { index: 0 }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Arbitrary { offsets: vec![Size::ZERO, b_offset], memory_index: vec![0, 1] @@ -454,7 +455,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } Ok(LayoutDetails { - variants: Variants::Single { index: 0 }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Arbitrary { offsets, memory_index @@ -499,7 +500,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { // The never type. ty::Never => { tcx.intern_layout(LayoutDetails { - variants: Variants::Single { index: 0 }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Union(0), abi: Abi::Uninhabited, align: dl.i8_align, @@ -555,7 +556,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { .ok_or(LayoutError::SizeOverflow(ty))?; tcx.intern_layout(LayoutDetails { - variants: Variants::Single { index: 0 }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Array { stride: element.size, count @@ -568,7 +569,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { ty::Slice(element) => { let element = self.layout_of(element)?; tcx.intern_layout(LayoutDetails { - variants: Variants::Single { index: 0 }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Array { stride: element.size, count: 0 @@ -580,7 +581,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } ty::Str => { tcx.intern_layout(LayoutDetails { - variants: Variants::Single { index: 0 }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Array { stride: Size::from_bytes(1), count: 0 @@ -650,7 +651,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let size = size.abi_align(align); tcx.intern_layout(LayoutDetails { - variants: Variants::Single { index: 0 }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Array { stride: element.size, count @@ -671,7 +672,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { v.fields.iter().map(|field| { self.layout_of(field.ty(tcx, substs)) }).collect::, _>>() - }).collect::, _>>()?; + }).collect::, _>>()?; if def.is_union() { let packed = def.repr.packed(); @@ -697,7 +698,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } let mut size = Size::ZERO; - for field in &variants[0] { + let index = VariantIdx::new(0); + for field in &variants[index] { assert!(!field.is_unsized()); if packed { @@ -710,8 +712,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } return Ok(tcx.intern_layout(LayoutDetails { - variants: Variants::Single { index: 0 }, - fields: FieldPlacement::Union(variants[0].len()), + variants: Variants::Single { index }, + fields: FieldPlacement::Union(variants[index].len()), abi: Abi::Aggregate { sized: true }, align, size: size.abi_align(align) @@ -729,8 +731,12 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { uninhabited && is_zst }; let (present_first, present_second) = { - let mut present_variants = (0..variants.len()).filter(|&v| { - !absent(&variants[v]) + let mut present_variants = variants.iter_enumerated().filter_map(|(i, v)| { + if absent(v) { + None + } else { + Some(i) + } }); (present_variants.next(), present_variants.next()) }; @@ -792,16 +798,16 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { // The current code for niche-filling relies on variant indices // instead of actual discriminants, so dataful enums with // explicit discriminants (RFC #2363) would misbehave. - let no_explicit_discriminants = def.variants.iter().enumerate() - .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i)); + let no_explicit_discriminants = def.variants.iter_enumerated() + .all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i.as_u32())); // Niche-filling enum optimization. if !def.repr.inhibit_enum_layout_opt() && no_explicit_discriminants { let mut dataful_variant = None; - let mut niche_variants = usize::max_value()..=0; + let mut niche_variants = VariantIdx::MAX..=VariantIdx::new(0); // Find one non-ZST variant. - 'variants: for (v, fields) in variants.iter().enumerate() { + 'variants: for (v, fields) in variants.iter_enumerated() { if absent(fields) { continue 'variants; } @@ -824,7 +830,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } if let Some(i) = dataful_variant { - let count = (niche_variants.end() - niche_variants.start() + 1) as u128; + let count = ( + niche_variants.end().as_u32() - niche_variants.start().as_u32() + 1 + ) as u128; for (field_index, &field) in variants[i].iter().enumerate() { let niche = match self.find_niche(field)? { Some(niche) => niche, @@ -836,7 +844,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { }; let mut align = dl.aggregate_align; - let st = variants.iter().enumerate().map(|(j, v)| { + let st = variants.iter_enumerated().map(|(j, v)| { let mut st = univariant_uninterned(v, &def.repr, StructKind::AlwaysSized)?; st.variants = Variants::Single { index: j }; @@ -844,7 +852,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { align = align.max(st.align); Ok(st) - }).collect::, _>>()?; + }).collect::, _>>()?; let offset = st[i].fields.offset(field_index) + niche.offset; let size = st[i].size; @@ -899,7 +907,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { let (mut min, mut max) = (i128::max_value(), i128::min_value()); let discr_type = def.repr.discr_type(); let bits = Integer::from_attr(self, discr_type).size().bits(); - for (i, discr) in def.discriminants(tcx).enumerate() { + for (i, discr) in def.discriminants(tcx) { if variants[i].iter().any(|f| f.abi.is_uninhabited()) { continue; } @@ -941,7 +949,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { } // Create the set of structs that represent each variant. - let mut layout_variants = variants.iter().enumerate().map(|(i, field_layouts)| { + let mut layout_variants = variants.iter_enumerated().map(|(i, field_layouts)| { let mut st = univariant_uninterned(&field_layouts, &def.repr, StructKind::Prefixed(min_ity.size(), prefix_align))?; st.variants = Variants::Single { index: i }; @@ -956,7 +964,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { size = cmp::max(size, st.size); align = align.max(st.align); Ok(st) - }).collect::, _>>()?; + }).collect::, _>>()?; // Align the maximum variant size to the largest alignment. size = size.abi_align(align); @@ -1259,7 +1267,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> { debug!("print-type-size `{:#?}` adt general variants def {}", layout.ty, adt_def.variants.len()); let variant_infos: Vec<_> = - adt_def.variants.iter().enumerate().map(|(i, variant_def)| { + adt_def.variants.iter_enumerated().map(|(i, variant_def)| { let fields: Vec<_> = variant_def.fields.iter().map(|f| f.ident.name).collect(); build_variant_info(Some(variant_def.name), @@ -1339,7 +1347,8 @@ impl<'a, 'tcx> SizeSkeleton<'tcx> { } // Get a zero-sized variant or a pointer newtype. - let zero_or_ptr_variant = |i: usize| { + let zero_or_ptr_variant = |i| { + let i = VariantIdx::new(i); let fields = def.variants[i].fields.iter().map(|field| { SizeSkeleton::compute(field.ty(tcx, substs), tcx, param_env) }); @@ -1562,7 +1571,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx> where C: LayoutOf> + HasTyCtxt<'tcx>, C::TyLayout: MaybeResult> { - fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: usize) -> TyLayout<'tcx> { + fn for_variant(this: TyLayout<'tcx>, cx: &C, variant_index: VariantIdx) -> TyLayout<'tcx> { let details = match this.variants { Variants::Single { index } if index == variant_index => this.details, @@ -1882,6 +1891,16 @@ impl<'a> HashStable> for FieldPlacement { } } +impl<'a> HashStable> for VariantIdx { + fn hash_stable( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher, + ) { + self.as_u32().hash_stable(hcx, hasher) + } +} + impl<'a> HashStable> for Abi { fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 9a63bb374c66d..83feadd50d77f 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -32,6 +32,7 @@ use mir::GeneratorLayout; use session::CrateDisambiguator; use traits::{self, Reveal}; use ty; +use ty::layout::VariantIdx; use ty::subst::{Subst, Substs}; use ty::util::{IntTypeExt, Discr}; use ty::walk::TypeWalker; @@ -57,7 +58,7 @@ use syntax::symbol::{keywords, Symbol, LocalInternedString, InternedString}; use syntax_pos::{DUMMY_SP, Span}; use smallvec; -use rustc_data_structures::indexed_vec::Idx; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, HashStable}; @@ -1785,7 +1786,7 @@ pub enum VariantDiscr { /// For efficiency reasons, the distance from the /// last `Explicit` discriminant is being stored, /// or `0` for the first variant, if it has none. - Relative(usize), + Relative(u32), } #[derive(Debug)] @@ -1801,7 +1802,7 @@ pub struct FieldDef { /// table. pub struct AdtDef { pub did: DefId, - pub variants: Vec, + pub variants: IndexVec, flags: AdtFlags, pub repr: ReprOptions, } @@ -1999,7 +2000,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { fn new(tcx: TyCtxt<'_, '_, '_>, did: DefId, kind: AdtKind, - variants: Vec, + variants: IndexVec, repr: ReprOptions) -> Self { debug!("AdtDef::new({:?}, {:?}, {:?}, {:?})", did, kind, variants, repr); let mut flags = AdtFlags::NO_ADT_FLAGS; @@ -2121,7 +2122,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { /// Asserts this is a struct or union and returns its unique variant. pub fn non_enum_variant(&self) -> &VariantDef { assert!(self.is_struct() || self.is_union()); - &self.variants[0] + &self.variants[VariantIdx::new(0)] } #[inline] @@ -2148,11 +2149,12 @@ impl<'a, 'gcx, 'tcx> AdtDef { .expect("variant_with_id: unknown variant") } - pub fn variant_index_with_id(&self, vid: DefId) -> usize { + pub fn variant_index_with_id(&self, vid: DefId) -> VariantIdx { self.variants - .iter() - .position(|v| v.did == vid) + .iter_enumerated() + .find(|(_, v)| v.did == vid) .expect("variant_index_with_id: unknown variant") + .0 } pub fn variant_of_def(&self, def: Def) -> &VariantDef { @@ -2216,11 +2218,11 @@ impl<'a, 'gcx, 'tcx> AdtDef { pub fn discriminants( &'a self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - ) -> impl Iterator> + Captures<'gcx> + 'a { + ) -> impl Iterator)> + Captures<'gcx> + 'a { let repr_type = self.repr.discr_type(); let initial = repr_type.initial_discriminant(tcx.global_tcx()); let mut prev_discr = None::>; - self.variants.iter().map(move |v| { + self.variants.iter_enumerated().map(move |(i, v)| { let mut discr = prev_discr.map_or(initial, |d| d.wrap_incr(tcx)); if let VariantDiscr::Explicit(expr_did) = v.discr { if let Some(new_discr) = self.eval_explicit_discr(tcx, expr_did) { @@ -2229,7 +2231,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } prev_discr = Some(discr); - discr + (i, discr) }) } @@ -2240,7 +2242,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { /// assuming there are no constant-evaluation errors there. pub fn discriminant_for_variant(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, - variant_index: usize) + variant_index: VariantIdx) -> Discr<'tcx> { let (val, offset) = self.discriminant_def_for_variant(variant_index); let explicit_value = val @@ -2254,12 +2256,12 @@ impl<'a, 'gcx, 'tcx> AdtDef { /// inferred discriminant directly pub fn discriminant_def_for_variant( &self, - variant_index: usize, - ) -> (Option, usize) { - let mut explicit_index = variant_index; + variant_index: VariantIdx, + ) -> (Option, u32) { + let mut explicit_index = variant_index.as_u32(); let expr_did; loop { - match self.variants[explicit_index].discr { + match self.variants[VariantIdx::from_u32(explicit_index)].discr { ty::VariantDiscr::Relative(0) => { expr_did = None; break; @@ -2273,7 +2275,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { } } } - (expr_did, variant_index - explicit_index) + (expr_did, variant_index.as_u32() - explicit_index) } pub fn destructor(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option { diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 59a66513eef05..e92f92dce63d0 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -33,6 +33,7 @@ CloneTypeFoldableAndLiftImpls! { (), bool, usize, + ::ty::layout::VariantIdx, u64, ::middle::region::Scope, ::syntax::ast::FloatTy, diff --git a/src/librustc_codegen_llvm/base.rs b/src/librustc_codegen_llvm/base.rs index 806025937cb11..821b074cd68c6 100644 --- a/src/librustc_codegen_llvm/base.rs +++ b/src/librustc_codegen_llvm/base.rs @@ -39,7 +39,7 @@ use rustc::middle::weak_lang_items; use rustc::mir::mono::{Linkage, Visibility, Stats, CodegenUnitNameBuilder}; use rustc::middle::cstore::{EncodedMetadata}; use rustc::ty::{self, Ty, TyCtxt}; -use rustc::ty::layout::{self, Align, TyLayout, LayoutOf}; +use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, VariantIdx}; use rustc::ty::query::Providers; use rustc::middle::cstore::{self, LinkagePreference}; use rustc::middle::exported_symbols; @@ -73,6 +73,7 @@ use rustc::util::nodemap::FxHashMap; use CrateInfo; use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::sync::Lrc; +use rustc_data_structures::indexed_vec::Idx; use std::any::Any; use std::cmp; @@ -309,7 +310,7 @@ pub fn coerce_unsized_into( (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { assert_eq!(def_a, def_b); - for i in 0..def_a.variants[0].fields.len() { + for i in 0..def_a.variants[VariantIdx::new(0)].fields.len() { let src_f = src.project_field(bx, i); let dst_f = dst.project_field(bx, i); diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs index 81d615b5ad70a..d6fd069071548 100644 --- a/src/librustc_codegen_llvm/context.rs +++ b/src/librustc_codegen_llvm/context.rs @@ -29,7 +29,7 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc::mir::mono::Stats; use rustc::session::config::{self, DebugInfo}; use rustc::session::Session; -use rustc::ty::layout::{LayoutError, LayoutOf, Size, TyLayout}; +use rustc::ty::layout::{LayoutError, LayoutOf, Size, TyLayout, VariantIdx}; use rustc::ty::{self, Ty, TyCtxt}; use rustc::util::nodemap::FxHashMap; use rustc_target::spec::{HasTargetSpec, Target}; @@ -87,7 +87,7 @@ pub struct CodegenCx<'a, 'tcx: 'a> { /// See http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable for details pub used_statics: RefCell>, - pub lltypes: RefCell, Option), &'a Type>>, + pub lltypes: RefCell, Option), &'a Type>>, pub scalar_lltypes: RefCell, &'a Type>>, pub pointee_infos: RefCell, Size), Option>>, pub isize_ty: &'a Type, diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 38b3a1b9c1ab7..97a3ae9c9faf4 100644 --- a/src/librustc_codegen_llvm/debuginfo/metadata.rs +++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs @@ -1241,7 +1241,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { // This doesn't matter in this case. NoDiscriminant }; - (0..variants.len()).map(|i| { + variants.iter_enumerated().map(|(i, _)| { let variant = self.layout.for_variant(cx, i); let (variant_type_metadata, member_desc_factory) = describe_enum_variant(cx, @@ -1341,7 +1341,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { } ] } else { - (0..variants.len()).map(|i| { + variants.iter_enumerated().map(|(i, _)| { let variant = self.layout.for_variant(cx, i); let (variant_type_metadata, member_desc_factory) = describe_enum_variant(cx, @@ -1361,8 +1361,8 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> { let niche_value = if i == dataful_variant { None } else { - let value = (i as u128) - .wrapping_sub(*niche_variants.start() as u128) + let value = (i.as_u32() as u128) + .wrapping_sub(niche_variants.start().as_u32() as u128) .wrapping_add(niche_start); let value = value & ((1u128 << niche.value.size(cx).bits()) - 1); Some(value as u64) @@ -1530,7 +1530,7 @@ fn prepare_enum_metadata( let def = enum_type.ty_adt_def().unwrap(); let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx) .zip(&def.variants) - .map(|(discr, v)| { + .map(|((_, discr), v)| { let name = SmallCStr::new(&v.name.as_str()); unsafe { Some(llvm::LLVMRustDIBuilderCreateEnumerator( diff --git a/src/librustc_codegen_llvm/mir/place.rs b/src/librustc_codegen_llvm/mir/place.rs index 062f7174680db..75ec5ead243f9 100644 --- a/src/librustc_codegen_llvm/mir/place.rs +++ b/src/librustc_codegen_llvm/mir/place.rs @@ -10,7 +10,7 @@ use llvm::{self, LLVMConstInBoundsGEP}; use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size}; +use rustc::ty::layout::{self, Align, TyLayout, LayoutOf, Size, VariantIdx}; use rustc::mir; use rustc::mir::tcx::PlaceTy; use base; @@ -281,7 +281,7 @@ impl PlaceRef<'ll, 'tcx> { match self.layout.variants { layout::Variants::Single { index } => { let discr_val = self.layout.ty.ty_adt_def().map_or( - index as u128, + index.as_u32() as u128, |def| def.discriminant_for_variant(bx.cx.tcx, index).val); return C_uint_big(cast_to, discr_val); } @@ -320,16 +320,16 @@ impl PlaceRef<'ll, 'tcx> { C_uint_big(niche_llty, niche_start) }; bx.select(bx.icmp(llvm::IntEQ, lldiscr, niche_llval), - C_uint(cast_to, *niche_variants.start() as u64), - C_uint(cast_to, dataful_variant as u64)) + C_uint(cast_to, niche_variants.start().as_u32() as u64), + C_uint(cast_to, dataful_variant.as_u32() as u64)) } else { // Rebase from niche values to discriminant values. - let delta = niche_start.wrapping_sub(*niche_variants.start() as u128); + let delta = niche_start.wrapping_sub(niche_variants.start().as_u32() as u128); let lldiscr = bx.sub(lldiscr, C_uint_big(niche_llty, delta)); - let lldiscr_max = C_uint(niche_llty, *niche_variants.end() as u64); + let lldiscr_max = C_uint(niche_llty, niche_variants.end().as_u32() as u64); bx.select(bx.icmp(llvm::IntULE, lldiscr, lldiscr_max), bx.intcast(lldiscr, cast_to, false), - C_uint(cast_to, dataful_variant as u64)) + C_uint(cast_to, dataful_variant.as_u32() as u64)) } } } @@ -337,7 +337,7 @@ impl PlaceRef<'ll, 'tcx> { /// Set the discriminant for a new value of the given case of the given /// representation. - pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize) { + pub fn codegen_set_discr(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: VariantIdx) { if self.layout.for_variant(bx.cx, variant_index).abi.is_uninhabited() { return; } @@ -376,7 +376,8 @@ impl PlaceRef<'ll, 'tcx> { let niche = self.project_field(bx, 0); let niche_llty = niche.layout.immediate_llvm_type(bx.cx); - let niche_value = ((variant_index - *niche_variants.start()) as u128) + let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); + let niche_value = (niche_value as u128) .wrapping_add(niche_start); // FIXME(eddyb) Check the actual primitive type here. let niche_llval = if niche_value == 0 { @@ -401,7 +402,7 @@ impl PlaceRef<'ll, 'tcx> { } } - pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: usize) + pub fn project_downcast(&self, bx: &Builder<'a, 'll, 'tcx>, variant_index: VariantIdx) -> PlaceRef<'ll, 'tcx> { let mut downcast = *self; downcast.layout = self.layout.for_variant(bx.cx, variant_index); diff --git a/src/librustc_lint/Cargo.toml b/src/librustc_lint/Cargo.toml index f097095abe4e9..fe197e3e2e28c 100644 --- a/src/librustc_lint/Cargo.toml +++ b/src/librustc_lint/Cargo.toml @@ -16,3 +16,4 @@ rustc_mir = { path = "../librustc_mir"} rustc_target = { path = "../librustc_target" } syntax = { path = "../libsyntax" } syntax_pos = { path = "../libsyntax_pos" } +rustc_data_structures = { path = "../librustc_data_structures" } diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs index 8c0e9bd11a173..57cbecb5c67be 100644 --- a/src/librustc_lint/lib.rs +++ b/src/librustc_lint/lib.rs @@ -40,6 +40,7 @@ extern crate log; extern crate rustc_mir; extern crate rustc_target; extern crate syntax_pos; +extern crate rustc_data_structures; use rustc::lint; use rustc::lint::{LateContext, LateLintPass, LintPass, LintArray}; diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 4ce87a9675a80..0e2d041b1ffdb 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -13,7 +13,8 @@ use rustc::hir::Node; use rustc::ty::subst::Substs; use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; -use rustc::ty::layout::{self, IntegerExt, LayoutOf}; +use rustc::ty::layout::{self, IntegerExt, LayoutOf, VariantIdx}; +use rustc_data_structures::indexed_vec::Idx; use util::nodemap::FxHashSet; use lint::{LateContext, LintContext, LintArray}; use lint::{LintPass, LateLintPass}; @@ -452,10 +453,13 @@ fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, if def.variants.len() == 2 { let data_idx; - if def.variants[0].fields.is_empty() { - data_idx = 1; - } else if def.variants[1].fields.is_empty() { - data_idx = 0; + let zero = VariantIdx::new(0); + let one = VariantIdx::new(1); + + if def.variants[zero].fields.is_empty() { + data_idx = one; + } else if def.variants[one].fields.is_empty() { + data_idx = zero; } else { return false; } diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index 0854df5d1269f..1c7e3c95d1470 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -601,7 +601,7 @@ impl<'a, 'tcx> CrateMetadata { }) .collect() } else { - vec![self.get_variant(tcx, &item, item_id, kind)] + std::iter::once(self.get_variant(tcx, &item, item_id, kind)).collect() }; tcx.alloc_adt_def(did, kind, variants, repr) diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index c9df36c5e236a..5421972a4adcb 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -27,6 +27,7 @@ use rustc::mir::{self, interpret}; use rustc::traits::specialization_graph; use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName}; use rustc::ty::codec::{self as ty_codec, TyEncoder}; +use rustc::ty::layout::VariantIdx; use rustc::session::config::{self, CrateType}; use rustc::util::nodemap::FxHashMap; @@ -580,7 +581,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { /// the right to access any information in the adt-def (including, /// e.g., the length of the various vectors). fn encode_enum_variant_info(&mut self, - (enum_did, Untracked(index)): (DefId, Untracked)) + (enum_did, Untracked(index)): (DefId, Untracked)) -> Entry<'tcx> { let tcx = self.tcx; let def = tcx.adt_def(enum_did); @@ -675,7 +676,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> { /// vectors). fn encode_field(&mut self, (adt_def_id, Untracked((variant_index, field_index))): (DefId, - Untracked<(usize, + Untracked<(VariantIdx, usize)>)) -> Entry<'tcx> { let tcx = self.tcx; @@ -1667,7 +1668,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for EncodeVisitor<'a, 'b, 'tcx> { impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { fn encode_fields(&mut self, adt_def_id: DefId) { let def = self.tcx.adt_def(adt_def_id); - for (variant_index, variant) in def.variants.iter().enumerate() { + for (variant_index, variant) in def.variants.iter_enumerated() { for (field_index, field) in variant.fields.iter().enumerate() { self.record(field.did, IsolatedEncoder::encode_field, @@ -1734,7 +1735,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> { self.encode_fields(def_id); let def = self.tcx.adt_def(def_id); - for (i, variant) in def.variants.iter().enumerate() { + for (i, variant) in def.variants.iter_enumerated() { self.record(variant.did, IsolatedEncoder::encode_enum_variant_info, (def_id, Untracked(i))); diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs index a057f2f45c010..c8d2bcd8b9315 100644 --- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs +++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs @@ -47,7 +47,8 @@ use rustc::ty::fold::TypeFoldable; use rustc::ty::subst::{Subst, Substs, UnpackedKind}; use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_data_structures::indexed_vec::IndexVec; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; +use rustc::ty::layout::VariantIdx; use std::rc::Rc; use std::{fmt, iter}; use syntax_pos::{Span, DUMMY_SP}; @@ -574,7 +575,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { }, ProjectionElem::Downcast(adt_def1, index) => match base_ty.sty { ty::Adt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => { - if index >= adt_def.variants.len() { + if index.as_usize() >= adt_def.variants.len() { PlaceTy::Ty { ty: span_mirbug_and_err!( self, @@ -654,7 +655,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> { variant_index, } => (&adt_def.variants[variant_index], substs), PlaceTy::Ty { ty } => match ty.sty { - ty::Adt(adt_def, substs) if !adt_def.is_enum() => (&adt_def.variants[0], substs), + ty::Adt(adt_def, substs) if !adt_def.is_enum() => + (&adt_def.variants[VariantIdx::new(0)], substs), ty::Closure(def_id, substs) => { return match substs.upvar_tys(def_id, tcx).nth(field.index()) { Some(ty) => Ok(ty), @@ -1280,7 +1282,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> { ); } }; - if variant_index >= adt.variants.len() { + if variant_index.as_usize() >= adt.variants.len() { span_bug!( stmt.source_info.span, "bad set discriminant ({:?} = {:?}): value of of range", diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index b92f270255af4..342aaf9039d10 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -22,6 +22,7 @@ use hair::pattern::PatternTypeProjections; use rustc::hir; use rustc::mir::*; use rustc::ty::{self, Ty}; +use rustc::ty::layout::VariantIdx; use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::FxHashMap; use syntax::ast::{Name, NodeId}; @@ -663,7 +664,7 @@ enum TestKind<'tcx> { // test the branches of enum Switch { adt_def: &'tcx ty::AdtDef, - variants: BitSet, + variants: BitSet, }, // test the branches of enum diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 349d877d52474..cfea357334fa8 100644 --- a/src/librustc_mir/build/matches/simplify.rs +++ b/src/librustc_mir/build/matches/simplify.rs @@ -123,7 +123,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { } PatternKind::Variant { adt_def, substs, variant_index, ref subpatterns } => { - let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| { + let irrefutable = adt_def.variants.iter_enumerated().all(|(i, v)| { i == variant_index || { self.hir.tcx().features().never_type && self.hir.tcx().features().exhaustive_patterns && diff --git a/src/librustc_mir/build/matches/test.rs b/src/librustc_mir/build/matches/test.rs index 9e6f32909bdea..177c71b80d1f5 100644 --- a/src/librustc_mir/build/matches/test.rs +++ b/src/librustc_mir/build/matches/test.rs @@ -22,6 +22,7 @@ use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::fx::FxHashMap; use rustc::ty::{self, Ty}; use rustc::ty::util::IntTypeExt; +use rustc::ty::layout::VariantIdx; use rustc::mir::*; use rustc::hir::{RangeEnd, Mutability}; use syntax_pos::Span; @@ -152,7 +153,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn add_variants_to_switch<'pat>(&mut self, test_place: &Place<'tcx>, candidate: &Candidate<'pat, 'tcx>, - variants: &mut BitSet) + variants: &mut BitSet) -> bool { let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) { @@ -196,7 +197,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let mut targets = Vec::with_capacity(used_variants + 1); let mut values = Vec::with_capacity(used_variants); let tcx = self.hir.tcx(); - for (idx, discr) in adt_def.discriminants(tcx).enumerate() { + for (idx, discr) in adt_def.discriminants(tcx) { target_blocks.push(if variants.contains(idx) { values.push(discr.val); targets.push(self.cfg.start_new_block()); @@ -512,7 +513,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { variant_index, subpatterns, candidate); - resulting_candidates[variant_index].push(new_candidate); + resulting_candidates[variant_index.as_usize()].push(new_candidate); true } (&TestKind::Switch { .. }, _) => false, @@ -673,7 +674,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { fn candidate_after_variant_switch<'pat>(&mut self, match_pair_index: usize, adt_def: &'tcx ty::AdtDef, - variant_index: usize, + variant_index: VariantIdx, subpatterns: &'pat [FieldPattern<'tcx>], candidate: &Candidate<'pat, 'tcx>) -> Candidate<'pat, 'tcx> { diff --git a/src/librustc_mir/build/matches/util.rs b/src/librustc_mir/build/matches/util.rs index cfd9100fc6ae7..a87660db2d313 100644 --- a/src/librustc_mir/build/matches/util.rs +++ b/src/librustc_mir/build/matches/util.rs @@ -13,6 +13,7 @@ use build::matches::MatchPair; use hair::*; use rustc::mir::*; use std::u32; +use std::convert::TryInto; impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn field_match_pairs<'pat>(&mut self, @@ -35,8 +36,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { opt_slice: Option<&'pat Pattern<'tcx>>, suffix: &'pat [Pattern<'tcx>]) { let min_length = prefix.len() + suffix.len(); - assert!(min_length < u32::MAX as usize); - let min_length = min_length as u32; + let min_length = min_length.try_into().unwrap(); match_pairs.extend( prefix.iter() diff --git a/src/librustc_mir/const_eval.rs b/src/librustc_mir/const_eval.rs index 011887090eefe..222920f1ad65a 100644 --- a/src/librustc_mir/const_eval.rs +++ b/src/librustc_mir/const_eval.rs @@ -21,7 +21,7 @@ use rustc::hir::def::Def; use rustc::mir::interpret::{ConstEvalErr, ErrorHandled}; use rustc::mir; use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt}; -use rustc::ty::layout::{self, LayoutOf, TyLayout}; +use rustc::ty::layout::{self, LayoutOf, TyLayout, VariantIdx}; use rustc::ty::subst::Subst; use rustc::traits::Reveal; use rustc_data_structures::indexed_vec::IndexVec; @@ -481,7 +481,7 @@ pub fn const_field<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, param_env: ty::ParamEnv<'tcx>, instance: ty::Instance<'tcx>, - variant: Option, + variant: Option, field: mir::Field, value: &'tcx ty::Const<'tcx>, ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { @@ -513,7 +513,7 @@ pub fn const_variant_index<'a, 'tcx>( param_env: ty::ParamEnv<'tcx>, instance: ty::Instance<'tcx>, val: &'tcx ty::Const<'tcx>, -) -> EvalResult<'tcx, usize> { +) -> EvalResult<'tcx, VariantIdx> { trace!("const_variant_index: {:?}, {:?}", instance, val); let ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); let op = ecx.const_to_op(val)?; diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 48fcdd42ff5e0..656a467fb4912 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -284,7 +284,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, Some((adt_def, adt_def.variant_index_with_id(variant_id))) } Def::StructCtor(_, CtorKind::Fn) | - Def::SelfCtor(..) => Some((adt_def, 0)), + Def::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))), _ => None, } }) @@ -468,7 +468,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, AdtKind::Struct | AdtKind::Union => { ExprKind::Adt { adt_def: adt, - variant_index: 0, + variant_index: VariantIdx::new(0), substs, user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt), fields: field_refs(cx, fields), diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs index 3a56d261111ee..733580b3ce2fd 100644 --- a/src/librustc_mir/hair/cx/mod.rs +++ b/src/librustc_mir/hair/cx/mod.rs @@ -25,6 +25,7 @@ use rustc::infer::InferCtxt; use rustc::ty::subst::Subst; use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::subst::{Kind, Substs}; +use rustc::ty::layout::VariantIdx; use syntax::ast::{self, LitKind}; use syntax::attr; use syntax::symbol::Symbol; @@ -228,7 +229,7 @@ impl<'a, 'gcx, 'tcx> Cx<'a, 'gcx, 'tcx> { bug!("found no method `{}` in `{:?}`", method_name, trait_def_id); } - pub fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: usize) -> Vec { + pub fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec { (0..adt_def.variants[variant_index].fields.len()) .map(Field::new) .collect() diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 8a24851de8149..460afba38d674 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -19,6 +19,7 @@ use rustc::hir::def_id::DefId; use rustc::middle::region; use rustc::ty::subst::Substs; use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const}; +use rustc::ty::layout::VariantIdx; use rustc::hir; use syntax::ast; use syntax_pos::Span; @@ -264,7 +265,7 @@ pub enum ExprKind<'tcx> { }, Adt { adt_def: &'tcx AdtDef, - variant_index: usize, + variant_index: VariantIdx, substs: &'tcx Substs<'tcx>, /// Optional user-given substs: for something like `let x = diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs index 69ca21c56242f..08736330acbe7 100644 --- a/src/librustc_mir/hair/pattern/_match.rs +++ b/src/librustc_mir/hair/pattern/_match.rs @@ -179,7 +179,7 @@ use super::{PatternFoldable, PatternFolder, compare_const_vals}; use rustc::hir::def_id::DefId; use rustc::hir::RangeEnd; use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; -use rustc::ty::layout::{Integer, IntegerExt}; +use rustc::ty::layout::{Integer, IntegerExt, VariantIdx}; use rustc::mir::Field; use rustc::mir::interpret::ConstValue; @@ -422,12 +422,12 @@ pub enum Constructor<'tcx> { } impl<'tcx> Constructor<'tcx> { - fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> usize { + fn variant_index_for_adt(&self, adt: &'tcx ty::AdtDef) -> VariantIdx { match self { &Variant(vid) => adt.variant_index_with_id(vid), &Single => { assert!(!adt.is_enum()); - 0 + VariantIdx::new(0) } _ => bug!("bad constructor {:?} for adt {:?}", self, adt) } diff --git a/src/librustc_mir/hair/pattern/mod.rs b/src/librustc_mir/hair/pattern/mod.rs index 0acb4052fd73e..941744c0aab7c 100644 --- a/src/librustc_mir/hair/pattern/mod.rs +++ b/src/librustc_mir/hair/pattern/mod.rs @@ -25,6 +25,7 @@ use rustc::mir::{ProjectionElem, UserTypeAnnotation, UserTypeProjection, UserTyp use rustc::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend}; use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty}; use rustc::ty::subst::{Substs, Kind}; +use rustc::ty::layout::VariantIdx; use rustc::hir::{self, PatKind, RangeEnd}; use rustc::hir::def::{Def, CtorKind}; use rustc::hir::pat_util::EnumerateAndAdjustIterator; @@ -111,7 +112,7 @@ impl<'tcx> PatternTypeProjections<'tcx> { pub(crate) fn variant(&self, adt_def: &'tcx AdtDef, - variant_index: usize, + variant_index: VariantIdx, field: Field) -> Self { self.map_projs(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field)) } @@ -153,7 +154,7 @@ impl<'tcx> PatternTypeProjection<'tcx> { pub(crate) fn variant(&self, adt_def: &'tcx AdtDef, - variant_index: usize, + variant_index: VariantIdx, field: Field) -> Self { let mut new = self.clone(); new.0.projs.push(ProjectionElem::Downcast(adt_def, variant_index)); @@ -200,7 +201,7 @@ pub enum PatternKind<'tcx> { Variant { adt_def: &'tcx AdtDef, substs: &'tcx Substs<'tcx>, - variant_index: usize, + variant_index: VariantIdx, subpatterns: Vec>, }, @@ -273,7 +274,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> { } _ => if let ty::Adt(adt, _) = self.ty.sty { if !adt.is_enum() { - Some(&adt.variants[0]) + Some(&adt.variants[VariantIdx::new(0)]) } else { None } @@ -1160,7 +1161,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> { } => PatternKind::Variant { adt_def: adt_def.fold_with(folder), substs: substs.fold_with(folder), - variant_index: variant_index.fold_with(folder), + variant_index, subpatterns: subpatterns.fold_with(folder) }, PatternKind::Leaf { diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs index d43ec0bd349ab..402632ef46a54 100644 --- a/src/librustc_mir/interpret/operand.rs +++ b/src/librustc_mir/interpret/operand.rs @@ -14,7 +14,7 @@ use std::convert::TryInto; use rustc::{mir, ty}; -use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt}; +use rustc::ty::layout::{self, Size, LayoutOf, TyLayout, HasDataLayout, IntegerExt, VariantIdx}; use rustc::mir::interpret::{ GlobalId, AllocId, @@ -417,7 +417,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> pub fn operand_downcast( &self, op: OpTy<'tcx, M::PointerTag>, - variant: usize, + variant: VariantIdx, ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> { // Downcasts only change the layout Ok(match op.try_as_mplace() { @@ -596,13 +596,13 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> pub fn read_discriminant( &self, rval: OpTy<'tcx, M::PointerTag>, - ) -> EvalResult<'tcx, (u128, usize)> { + ) -> EvalResult<'tcx, (u128, VariantIdx)> { trace!("read_discriminant_value {:#?}", rval.layout); match rval.layout.variants { layout::Variants::Single { index } => { let discr_val = rval.layout.ty.ty_adt_def().map_or( - index as u128, + index.as_u32() as u128, |def| def.discriminant_for_variant(*self.tcx, index).val); return Ok((discr_val, index)); } @@ -645,9 +645,9 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> .ty_adt_def() .expect("tagged layout for non adt") .discriminants(self.tcx.tcx) - .position(|var| var.val == real_discr) + .find(|(_, var)| var.val == real_discr) .ok_or_else(|| EvalErrorKind::InvalidDiscriminant(raw_discr.erase_tag()))?; - (real_discr, index) + (real_discr, index.0) }, layout::Variants::NicheFilling { dataful_variant, @@ -655,33 +655,32 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M> niche_start, .. } => { - let variants_start = *niche_variants.start() as u128; - let variants_end = *niche_variants.end() as u128; - let real_discr = match raw_discr { + let variants_start = niche_variants.start().as_u32() as u128; + let variants_end = niche_variants.end().as_u32() as u128; + match raw_discr { Scalar::Ptr(_) => { // The niche must be just 0 (which a pointer value never is) assert!(niche_start == 0); assert!(variants_start == variants_end); - dataful_variant as u128 + (dataful_variant.as_u32() as u128, dataful_variant) }, Scalar::Bits { bits: raw_discr, size } => { assert_eq!(size as u64, discr_val.layout.size.bytes()); let discr = raw_discr.wrapping_sub(niche_start) .wrapping_add(variants_start); if variants_start <= discr && discr <= variants_end { - discr + let index = discr as usize; + assert_eq!(index as u128, discr); + assert!(index < rval.layout.ty + .ty_adt_def() + .expect("tagged layout for non adt") + .variants.len()); + (discr, VariantIdx::from_usize(index)) } else { - dataful_variant as u128 + (dataful_variant.as_u32() as u128, dataful_variant) } }, - }; - let index = real_discr as usize; - assert_eq!(index as u128, real_discr); - assert!(index < rval.layout.ty - .ty_adt_def() - .expect("tagged layout for non adt") - .variants.len()); - (real_discr, index) + } } }) } diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs index 6f8bbf3c4a97d..c9ec83a7adb27 100644 --- a/src/librustc_mir/interpret/place.rs +++ b/src/librustc_mir/interpret/place.rs @@ -18,7 +18,7 @@ use std::hash::Hash; use rustc::hir; use rustc::mir; use rustc::ty::{self, Ty}; -use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout}; +use rustc::ty::layout::{self, Size, Align, LayoutOf, TyLayout, HasDataLayout, VariantIdx}; use rustc::mir::interpret::{ GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic @@ -431,7 +431,7 @@ where pub fn mplace_downcast( &self, base: MPlaceTy<'tcx, M::PointerTag>, - variant: usize, + variant: VariantIdx, ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { // Downcasts only change the layout assert!(base.meta.is_none()); @@ -498,7 +498,7 @@ where pub fn place_downcast( &self, base: PlaceTy<'tcx, M::PointerTag>, - variant: usize, + variant: VariantIdx, ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { // Downcast just changes the layout Ok(match base.place { @@ -901,7 +901,7 @@ where pub fn write_discriminant_index( &mut self, - variant_index: usize, + variant_index: VariantIdx, dest: PlaceTy<'tcx, M::PointerTag>, ) -> EvalResult<'tcx> { match dest.layout.variants { @@ -910,7 +910,7 @@ where } layout::Variants::Tagged { ref tag, .. } => { let adt_def = dest.layout.ty.ty_adt_def().unwrap(); - assert!(variant_index < adt_def.variants.len()); + assert!(variant_index.as_usize() < adt_def.variants.len()); let discr_val = adt_def .discriminant_for_variant(*self.tcx, variant_index) .val; @@ -931,11 +931,14 @@ where niche_start, .. } => { - assert!(variant_index < dest.layout.ty.ty_adt_def().unwrap().variants.len()); + assert!( + variant_index.as_usize() < dest.layout.ty.ty_adt_def().unwrap().variants.len(), + ); if variant_index != dataful_variant { let niche_dest = self.place_field(dest, 0)?; - let niche_value = ((variant_index - niche_variants.start()) as u128) + let niche_value = variant_index.as_u32() - niche_variants.start().as_u32(); + let niche_value = (niche_value as u128) .wrapping_add(niche_start); self.write_scalar( Scalar::from_uint(niche_value, niche_dest.layout.size), diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs index 84aa5b6756660..3d00dce8b0428 100644 --- a/src/librustc_mir/interpret/validity.rs +++ b/src/librustc_mir/interpret/validity.rs @@ -13,7 +13,7 @@ use std::hash::Hash; use std::ops::RangeInclusive; use syntax_pos::symbol::Symbol; -use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf}; +use rustc::ty::layout::{self, Size, Align, TyLayout, LayoutOf, VariantIdx}; use rustc::ty; use rustc_data_structures::fx::FxHashSet; use rustc::mir::interpret::{ @@ -74,6 +74,7 @@ macro_rules! try_validation { #[derive(Copy, Clone, Debug)] pub enum PathElem { Field(Symbol), + Variant(Symbol), ClosureVar(Symbol), ArrayElem(usize), TupleElem(usize), @@ -107,6 +108,7 @@ fn path_format(path: &Vec) -> String { for elem in path.iter() { match elem { Field(name) => write!(out, ".{}", name), + Variant(name) => write!(out, ".", name), ClosureVar(name) => write!(out, ".", name), TupleElem(idx) => write!(out, ".{}", idx), ArrayElem(idx) => write!(out, "[{}]", idx), @@ -165,12 +167,12 @@ struct ValidityVisitor<'rt, 'a: 'rt, 'mir: 'rt, 'tcx: 'a+'rt+'mir, M: Machine<'a } impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ValidityVisitor<'rt, 'a, 'mir, 'tcx, M> { - fn push_aggregate_field_path_elem( + fn aggregate_field_path_elem( &mut self, layout: TyLayout<'tcx>, field: usize, - ) { - let elem = match layout.ty.sty { + ) -> PathElem { + match layout.ty.sty { // generators and closures. ty::Closure(def_id, _) | ty::Generator(def_id, _, _) => { if let Some(upvar) = self.ecx.tcx.optimized_mir(def_id).upvar_decls.get(field) { @@ -192,9 +194,7 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ValidityVisitor<'rt, 'a, ' layout::Variants::Single { index } => // Inside a variant PathElem::Field(def.variants[index].fields[field].ident.name), - _ => - // To a variant - PathElem::Field(def.variants[field].name) + _ => bug!(), } } @@ -209,8 +209,22 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> ValidityVisitor<'rt, 'a, ' // nothing else has an aggregate layout _ => bug!("aggregate_field_path_elem: got non-aggregate type {:?}", layout.ty), - }; + } + } + + fn visit_elem( + &mut self, + new_op: OpTy<'tcx, M::PointerTag>, + elem: PathElem, + ) -> EvalResult<'tcx> { + // Remember the old state + let path_len = self.path.len(); + // Perform operation self.path.push(elem); + self.visit_value(new_op)?; + // Undo changes + self.path.truncate(path_len); + Ok(()) } } @@ -231,14 +245,19 @@ impl<'rt, 'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> field: usize, new_op: OpTy<'tcx, M::PointerTag> ) -> EvalResult<'tcx> { - // Remember the old state - let path_len = self.path.len(); - // Perform operation - self.push_aggregate_field_path_elem(old_op.layout, field); - self.visit_value(new_op)?; - // Undo changes - self.path.truncate(path_len); - Ok(()) + let elem = self.aggregate_field_path_elem(old_op.layout, field); + self.visit_elem(new_op, elem) + } + + #[inline] + fn visit_variant( + &mut self, + old_op: OpTy<'tcx, M::PointerTag>, + variant_id: VariantIdx, + new_op: OpTy<'tcx, M::PointerTag> + ) -> EvalResult<'tcx> { + let name = old_op.layout.ty.ty_adt_def().unwrap().variants[variant_id].name; + self.visit_elem(new_op, PathElem::Variant(name)) } #[inline] diff --git a/src/librustc_mir/interpret/visitor.rs b/src/librustc_mir/interpret/visitor.rs index 392e27918092f..4a47045643253 100644 --- a/src/librustc_mir/interpret/visitor.rs +++ b/src/librustc_mir/interpret/visitor.rs @@ -1,7 +1,7 @@ //! Visitor for a run-time value with a given layout: Traverse enums, structs and other compound //! types until we arrive at the leaves, with custom handling for primitive types. -use rustc::ty::layout::{self, TyLayout}; +use rustc::ty::layout::{self, TyLayout, VariantIdx}; use rustc::ty; use rustc::mir::interpret::{ EvalResult, @@ -32,7 +32,7 @@ pub trait Value<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>>: Copy fn project_downcast( self, ecx: &EvalContext<'a, 'mir, 'tcx, M>, - variant: usize, + variant: VariantIdx, ) -> EvalResult<'tcx, Self>; /// Project to the n-th field. @@ -70,7 +70,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M> fn project_downcast( self, ecx: &EvalContext<'a, 'mir, 'tcx, M>, - variant: usize, + variant: VariantIdx, ) -> EvalResult<'tcx, Self> { ecx.operand_downcast(self, variant) } @@ -109,7 +109,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> Value<'a, 'mir, 'tcx, M> fn project_downcast( self, ecx: &EvalContext<'a, 'mir, 'tcx, M>, - variant: usize, + variant: VariantIdx, ) -> EvalResult<'tcx, Self> { ecx.mplace_downcast(self, variant) } @@ -171,6 +171,16 @@ macro_rules! make_value_visitor { self.visit_value(new_val) } + #[inline(always)] + fn visit_variant( + &mut self, + _old_val: Self::V, + _variant: VariantIdx, + new_val: Self::V, + ) -> EvalResult<'tcx> { + self.visit_value(new_val) + } + /// Called whenever we reach a value with uninhabited layout. /// Recursing to fields will *always* continue after this! This is not meant to control /// whether and how we descend recursively/ into the scalar's fields if there are any, @@ -221,7 +231,7 @@ macro_rules! make_value_visitor { let inner = v.project_downcast(self.ecx(), idx)?; trace!("walk_value: variant layout: {:#?}", inner.layout()); // recurse with the inner type - return self.visit_field(v, idx, inner); + return self.visit_variant(v, idx, inner); } layout::Variants::Single { .. } => {} } diff --git a/src/librustc_mir/shim.rs b/src/librustc_mir/shim.rs index 54983b8f4e026..e99af56c22c00 100644 --- a/src/librustc_mir/shim.rs +++ b/src/librustc_mir/shim.rs @@ -13,6 +13,7 @@ use rustc::hir::def_id::DefId; use rustc::infer; use rustc::mir::*; use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind}; +use rustc::ty::layout::VariantIdx; use rustc::ty::subst::{Subst, Substs}; use rustc::ty::query::Providers; @@ -291,7 +292,7 @@ impl<'a, 'tcx> DropElaborator<'a, 'tcx> for DropShimElaborator<'a, 'tcx> { fn deref_subpath(&self, _path: Self::Path) -> Option { None } - fn downcast_subpath(&self, _path: Self::Path, _variant: usize) -> Option { + fn downcast_subpath(&self, _path: Self::Path, _variant: VariantIdx) -> Option { Some(()) } fn array_subpath(&self, _path: Self::Path, _index: u32, _size: u32) -> Option { @@ -867,7 +868,7 @@ pub fn build_adt_ctor<'a, 'gcx, 'tcx>(infcx: &infer::InferCtxt<'a, 'gcx, 'tcx>, let variant_no = if adt_def.is_enum() { adt_def.variant_index_with_id(def_id) } else { - 0 + VariantIdx::new(0) }; // return = ADT(arg0, arg1, ...); return diff --git a/src/librustc_mir/transform/elaborate_drops.rs b/src/librustc_mir/transform/elaborate_drops.rs index 5de289068b255..2b3fd552e0faa 100644 --- a/src/librustc_mir/transform/elaborate_drops.rs +++ b/src/librustc_mir/transform/elaborate_drops.rs @@ -16,6 +16,7 @@ use dataflow::{drop_flag_effects_for_location, on_lookup_result_bits}; use dataflow::MoveDataParamEnv; use dataflow::{self, do_dataflow, DebugFormatted}; use rustc::ty::{self, TyCtxt}; +use rustc::ty::layout::VariantIdx; use rustc::mir::*; use rustc::util::nodemap::FxHashMap; use rustc_data_structures::bit_set::BitSet; @@ -282,7 +283,7 @@ impl<'a, 'b, 'tcx> DropElaborator<'a, 'tcx> for Elaborator<'a, 'b, 'tcx> { }) } - fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option { + fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option { dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| { match p { &Projection { diff --git a/src/librustc_mir/transform/generator.rs b/src/librustc_mir/transform/generator.rs index 5889fabee9d6e..9d633fa2b0b7c 100644 --- a/src/librustc_mir/transform/generator.rs +++ b/src/librustc_mir/transform/generator.rs @@ -64,6 +64,7 @@ use rustc::hir::def_id::DefId; use rustc::mir::*; use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor}; use rustc::ty::{self, TyCtxt, AdtDef, Ty}; +use rustc::ty::layout::VariantIdx; use rustc::ty::subst::Substs; use util::dump_mir; use util::liveness::{self, IdentityMap}; @@ -158,7 +159,7 @@ struct TransformVisitor<'a, 'tcx: 'a> { impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { // Make a GeneratorState rvalue - fn make_state(&self, idx: usize, val: Operand<'tcx>) -> Rvalue<'tcx> { + fn make_state(&self, idx: VariantIdx, val: Operand<'tcx>) -> Rvalue<'tcx> { let adt = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None, None); Rvalue::Aggregate(box adt, vec![val]) } @@ -229,11 +230,11 @@ impl<'a, 'tcx> MutVisitor<'tcx> for TransformVisitor<'a, 'tcx> { }); let ret_val = match data.terminator().kind { - TerminatorKind::Return => Some((1, + TerminatorKind::Return => Some((VariantIdx::new(1), None, Operand::Move(Place::Local(self.new_ret_local)), None)), - TerminatorKind::Yield { ref value, resume, drop } => Some((0, + TerminatorKind::Yield { ref value, resume, drop } => Some((VariantIdx::new(0), Some(resume), value.clone(), drop)), diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index d9a1e4a0fd639..2c7f337b3b1c0 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -14,6 +14,7 @@ use rustc::mir::*; use rustc::middle::lang_items; use rustc::traits::Reveal; use rustc::ty::{self, Ty, TyCtxt}; +use rustc::ty::layout::VariantIdx; use rustc::ty::subst::Substs; use rustc::ty::util::IntTypeExt; use rustc_data_structures::indexed_vec::Idx; @@ -94,7 +95,7 @@ pub trait DropElaborator<'a, 'tcx: 'a> : fmt::Debug { fn field_subpath(&self, path: Self::Path, field: Field) -> Option; fn deref_subpath(&self, path: Self::Path) -> Option; - fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option; + fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option; fn array_subpath(&self, path: Self::Path, index: u32, size: u32) -> Option; } @@ -392,7 +393,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let fields = self.move_paths_for_fields( self.place, self.path, - &adt.variants[0], + &adt.variants[VariantIdx::new(0)], substs ); self.drop_ladder(fields, succ, unwind) @@ -416,7 +417,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let mut have_otherwise = false; - for (variant_index, discr) in adt.discriminants(self.tcx()).enumerate() { + for (variant_index, discr) in adt.discriminants(self.tcx()) { let subpath = self.elaborator.downcast_subpath( self.path, variant_index); if let Some(variant_path) = subpath { @@ -894,7 +895,7 @@ impl<'l, 'b, 'tcx, D> DropCtxt<'l, 'b, 'tcx, D> let tcx = self.tcx(); let unit_temp = Place::Local(self.new_temp(tcx.mk_unit())); let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem); - let args = adt.variants[0].fields.iter().enumerate().map(|(i, f)| { + let args = adt.variants[VariantIdx::new(0)].fields.iter().enumerate().map(|(i, f)| { let field = Field::new(i); let field_ty = f.ty(self.tcx(), substs); Operand::Move(self.place.clone().field(field, field_ty)) diff --git a/src/librustc_target/Cargo.toml b/src/librustc_target/Cargo.toml index 684ea4c78978c..dfdd7f0ae58e5 100644 --- a/src/librustc_target/Cargo.toml +++ b/src/librustc_target/Cargo.toml @@ -12,4 +12,5 @@ crate-type = ["dylib"] bitflags = "1.0" log = "0.4" rustc_cratesio_shim = { path = "../librustc_cratesio_shim" } +rustc_data_structures = { path = "../librustc_data_structures" } serialize = { path = "../libserialize" } diff --git a/src/librustc_target/abi/mod.rs b/src/librustc_target/abi/mod.rs index 15f61a033447f..88f22912fa6fc 100644 --- a/src/librustc_target/abi/mod.rs +++ b/src/librustc_target/abi/mod.rs @@ -16,6 +16,8 @@ use spec::Target; use std::{cmp, fmt}; use std::ops::{Add, Deref, Sub, Mul, AddAssign, Range, RangeInclusive}; +use rustc_data_structures::indexed_vec::{Idx, IndexVec}; + pub mod call; /// Parsed [Data layout](http://llvm.org/docs/LangRef.html#data-layout) @@ -825,11 +827,15 @@ impl Abi { } } +newtype_index! { + pub struct VariantIdx { .. } +} + #[derive(PartialEq, Eq, Hash, Debug)] pub enum Variants { /// Single enum variants, structs/tuples, unions, and all non-ADTs. Single { - index: usize + index: VariantIdx, }, /// General-case enums: for each case there is a struct, and they all have @@ -837,7 +843,7 @@ pub enum Variants { /// at a non-0 offset, after where the tag would go. Tagged { tag: Scalar, - variants: Vec, + variants: IndexVec, }, /// Multiple cases distinguished by a niche (values invalid for a type): @@ -849,11 +855,11 @@ pub enum Variants { /// `None` has a null pointer for the second tuple field, and /// `Some` is the identity function (with a non-null reference). NicheFilling { - dataful_variant: usize, - niche_variants: RangeInclusive, + dataful_variant: VariantIdx, + niche_variants: RangeInclusive, niche: Scalar, niche_start: u128, - variants: Vec, + variants: IndexVec, } } @@ -871,7 +877,7 @@ impl LayoutDetails { let size = scalar.value.size(cx); let align = scalar.value.align(cx); LayoutDetails { - variants: Variants::Single { index: 0 }, + variants: Variants::Single { index: VariantIdx::new(0) }, fields: FieldPlacement::Union(0), abi: Abi::Scalar(scalar), size, @@ -908,12 +914,16 @@ pub trait LayoutOf { } pub trait TyLayoutMethods<'a, C: LayoutOf>: Sized { - fn for_variant(this: TyLayout<'a, Self>, cx: &C, variant_index: usize) -> TyLayout<'a, Self>; + fn for_variant( + this: TyLayout<'a, Self>, + cx: &C, + variant_index: VariantIdx, + ) -> TyLayout<'a, Self>; fn field(this: TyLayout<'a, Self>, cx: &C, i: usize) -> C::TyLayout; } impl<'a, Ty> TyLayout<'a, Ty> { - pub fn for_variant(self, cx: &C, variant_index: usize) -> Self + pub fn for_variant(self, cx: &C, variant_index: VariantIdx) -> Self where Ty: TyLayoutMethods<'a, C>, C: LayoutOf { Ty::for_variant(self, cx, variant_index) } diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index e60c9922d467a..813b39de06413 100644 --- a/src/librustc_target/lib.rs +++ b/src/librustc_target/lib.rs @@ -23,7 +23,9 @@ #![feature(box_syntax)] #![feature(nll)] +#![feature(rustc_attrs)] #![feature(slice_patterns)] +#![feature(step_trait)] #[macro_use] extern crate bitflags; @@ -36,5 +38,8 @@ extern crate serialize as rustc_serialize; // used by deriving #[allow(unused_extern_crates)] extern crate rustc_cratesio_shim; +#[macro_use] +extern crate rustc_data_structures; + pub mod abi; pub mod spec; diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 7dfdb926c60ef..2e6797ef23ad2 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -103,6 +103,8 @@ use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoB use rustc::ty::fold::TypeFoldable; use rustc::ty::query::Providers; use rustc::ty::util::{Representability, IntTypeExt, Discr}; +use rustc::ty::layout::VariantIdx; +use rustc_data_structures::indexed_vec::Idx; use errors::{Applicability, DiagnosticBuilder, DiagnosticId}; use require_c_abi_if_variadic; @@ -1837,10 +1839,11 @@ pub fn check_enum<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } let mut disr_vals: Vec> = Vec::with_capacity(vs.len()); - for (discr, v) in def.discriminants(tcx).zip(vs) { + for ((_, discr), v) in def.discriminants(tcx).zip(vs) { // Check for duplicate discriminant values if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) { - let variant_i_node_id = tcx.hir.as_local_node_id(def.variants[i].did).unwrap(); + let variant_did = def.variants[VariantIdx::new(i)].did; + let variant_i_node_id = tcx.hir.as_local_node_id(variant_did).unwrap(); let variant_i = tcx.hir.expect_variant(variant_i_node_id); let i_span = match variant_i.node.disr_expr { Some(ref expr) => tcx.hir.span(expr.id), diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d5f5cbb562e78..70af837076f1a 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -651,7 +651,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad }; ( AdtKind::Struct, - vec![convert_variant( + std::iter::once(convert_variant( tcx, ctor_id.unwrap_or(def_id), item.name, @@ -659,12 +659,12 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad def, AdtKind::Struct, def_id - )], + )).collect(), ) } ItemKind::Union(ref def, _) => ( AdtKind::Union, - vec![convert_variant( + std::iter::once(convert_variant( tcx, def_id, item.name, @@ -672,7 +672,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad def, AdtKind::Union, def_id - )], + )).collect(), ), _ => bug!(), }; diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index c39b71e33ca0c..f514cb83a1fed 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -38,10 +38,12 @@ use rustc::hir::def::{self, Def, CtorKind}; use rustc::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc::ty::subst::Substs; use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind}; +use rustc::ty::layout::VariantIdx; use rustc::middle::stability; use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc_typeck::hir_ty_to_ty; use rustc::infer::region_constraints::{RegionConstraintData, Constraint}; +use rustc_data_structures::indexed_vec::{IndexVec, Idx}; use std::collections::hash_map::Entry; use std::fmt; @@ -98,6 +100,12 @@ impl, U> Clean> for [T] { } } +impl, U, V: Idx> Clean> for IndexVec { + fn clean(&self, cx: &DocContext) -> IndexVec { + self.iter().map(|x| x.clean(cx)).collect() + } +} + impl, U> Clean for P { fn clean(&self, cx: &DocContext) -> U { (**self).clean(cx) @@ -2886,7 +2894,7 @@ impl Clean for ::rustc::hir::VariantData { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Enum { - pub variants: Vec, + pub variants: IndexVec, pub generics: Generics, pub variants_stripped: bool, } @@ -2902,7 +2910,7 @@ impl Clean for doctree::Enum { stability: self.stab.clean(cx), deprecation: self.depr.clean(cx), inner: EnumItem(Enum { - variants: self.variants.clean(cx), + variants: self.variants.iter().map(|v| v.clean(cx)).collect(), generics: self.generics.clean(cx), variants_stripped: false, }), diff --git a/src/test/ui/consts/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr index 804c9643d8ae3..d36e96b08174a 100644 --- a/src/test/ui/consts/const-eval/ub-enum.stderr +++ b/src/test/ui/consts/const-eval/ub-enum.stderr @@ -42,7 +42,7 @@ error[E0080]: it is undefined behavior to use this value --> $DIR/ub-enum.rs:61:1 | LL | const BAD_ENUM_CHAR: Option<(char, char)> = Some(('x', unsafe { TransmuteChar { a: !0 }.b })); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at .Some.0.1, but expected something less or equal to 1114111 + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 4294967295 at ..0.1, but expected something less or equal to 1114111 | = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rust compiler repository if you believe it should not be considered undefined behavior