diff options
| author | bors <bors@rust-lang.org> | 2018-11-13 07:04:14 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-11-13 07:04:14 +0000 |
| commit | 485397e49a02a3b7ff77c17e4a3f16c653925cb3 (patch) | |
| tree | a8386662a025a2d9eb81c4a9e797bcf589b3894c | |
| parent | c4371c854f5c7f734563f61a666e0ae230024c17 (diff) | |
| parent | d46a2078b4e450e163a44502c42fc4a326943d03 (diff) | |
Auto merge of #55589 - oli-obk:min_length_💣, r=pnkfelix
Add `VariantIdx` type and use instead of `usize`
44 files changed, 308 insertions, 189 deletions
diff --git a/src/Cargo.lock b/src/Cargo.lock index 32304c81182..a4246b26c22 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 0a5b1e184de..d2be0e4dcb9 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 9d3f37bc36a..59ef8fa1448 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 8a32e8f46c2..9a0b1c68ddc 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::<PlaceElem<'_>>() <= 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<UserTypeAnnotation<'tcx>>, Option<usize>, diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs index f773f46b6f5..baa88dba459 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::<PlaceTy<'_>>() <= 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 82095a2f5b0..a86a56a45cd 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<ty::VariantDef>, + variants: IndexVec<VariantIdx, ty::VariantDef>, 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 5aeba652f32..877bd5a82e6 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::<Result<Vec<_>, _>>() - }).collect::<Result<Vec<_>, _>>()?; + }).collect::<Result<IndexVec<VariantIdx, _>, _>>()?; 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::<Result<Vec<_>, _>>()?; + }).collect::<Result<IndexVec<VariantIdx, _>, _>>()?; 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::<Result<Vec<_>, _>>()?; + }).collect::<Result<IndexVec<VariantIdx, _>, _>>()?; // 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<Ty = Ty<'tcx>> + HasTyCtxt<'tcx>, C::TyLayout: MaybeResult<TyLayout<'tcx>> { - 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<StableHashingContext<'a>> for FieldPlacement { } } +impl<'a> HashStable<StableHashingContext<'a>> for VariantIdx { + fn hash_stable<W: StableHasherResult>( + &self, + hcx: &mut StableHashingContext<'a>, + hasher: &mut StableHasher<W>, + ) { + self.as_u32().hash_stable(hcx, hasher) + } +} + impl<'a> HashStable<StableHashingContext<'a>> for Abi { fn hash_stable<W: StableHasherResult>(&self, hcx: &mut StableHashingContext<'a>, diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 9a63bb374c6..83feadd50d7 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<VariantDef>, + pub variants: IndexVec<self::layout::VariantIdx, VariantDef>, flags: AdtFlags, pub repr: ReprOptions, } @@ -1999,7 +2000,7 @@ impl<'a, 'gcx, 'tcx> AdtDef { fn new(tcx: TyCtxt<'_, '_, '_>, did: DefId, kind: AdtKind, - variants: Vec<VariantDef>, + variants: IndexVec<VariantIdx, VariantDef>, 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<Item=Discr<'tcx>> + Captures<'gcx> + 'a { + ) -> impl Iterator<Item=(VariantIdx, Discr<'tcx>)> + Captures<'gcx> + 'a { let repr_type = self.repr.discr_type(); let initial = repr_type.initial_discriminant(tcx.global_tcx()); let mut prev_discr = None::<Discr<'tcx>>; - 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<DefId>, usize) { - let mut explicit_index = variant_index; + variant_index: VariantIdx, + ) -> (Option<DefId>, 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<Destructor> { diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 59a66513eef..e92f92dce63 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 806025937cb..821b074cd68 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 81d615b5ad7..d6fd0690715 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<Vec<&'a Value>>, - pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<usize>), &'a Type>>, + pub lltypes: RefCell<FxHashMap<(Ty<'tcx>, Option<VariantIdx>), &'a Type>>, pub scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'a Type>>, pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>, pub isize_ty: &'a Type, diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs index 38b3a1b9c1a..97a3ae9c9fa 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 062f7174680..75ec5ead243 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 f097095abe4..fe197e3e2e2 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 8c0e9bd11a1..57cbecb5c67 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 4ce87a9675a..0e2d041b1ff 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 0854df5d126..1c7e3c95d14 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 c9df36c5e23..5421972a4ad 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<usize>)) + (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>)) -> 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 a057f2f45c0..c8d2bcd8b93 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 b92f270255a..342aaf9039d 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<usize>, + variants: BitSet<VariantIdx>, }, // test the branches of enum diff --git a/src/librustc_mir/build/matches/simplify.rs b/src/librustc_mir/build/matches/simplify.rs index 349d877d524..cfea357334f 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 9e6f32909bd..177c71b80d1 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<usize>) + variants: &mut BitSet<VariantIdx>) -> 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 cfd9100fc6a..a87660db2d3 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 011887090ee..222920f1ad6 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<usize>, + variant: Option<VariantIdx>, 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 48fcdd42ff5..656a467fb49 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 3a56d261111..733580b3ce2 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<Field> { + pub fn all_fields(&mut self, adt_def: &ty::AdtDef, variant_index: VariantIdx) -> Vec<Field> { (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 8a24851de81..460afba38d6 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 69ca21c5624..08736330acb 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 0acb4052fd7..941744c0aab 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<FieldPattern<'tcx>>, }, @@ -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 d43ec0bd349..402632ef46a 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 6f8bbf3c4a9..c9ec83a7adb 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 84aa5b67566..3d00dce8b04 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<PathElem>) -> String { for elem in path.iter() { match elem { Field(name) => write!(out, ".{}", name), + Variant(name) => write!(out, ".<downcast-variant({})>", name), ClosureVar(name) => write!(out, ".<closure-var({})>", 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 392e2791809..4a470456432 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 54983b8f4e0..e99af56c22c 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<Self::Path> { None } - fn downcast_subpath(&self, _path: Self::Path, _variant: usize) -> Option<Self::Path> { + fn downcast_subpath(&self, _path: Self::Path, _variant: VariantIdx) -> Option<Self::Path> { Some(()) } fn array_subpath(&self, _path: Self::Path, _index: u32, _size: u32) -> Option<Self::Path> { @@ -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 5de289068b2..2b3fd552e0f 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<Self::Path> { + fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option<Self::Path> { 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 5889fabee9d..9d633fa2b0b 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 d9a1e4a0fd6..2c7f337b3b1 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<Self::Path>; fn deref_subpath(&self, path: Self::Path) -> Option<Self::Path>; - fn downcast_subpath(&self, path: Self::Path, variant: usize) -> Option<Self::Path>; + fn downcast_subpath(&self, path: Self::Path, variant: VariantIdx) -> Option<Self::Path>; fn array_subpath(&self, path: Self::Path, index: u32, size: u32) -> Option<Self::Path>; } @@ -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 684ea4c7897..dfdd7f0ae58 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 15f61a03344..88f22912fa6 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<LayoutDetails>, + variants: IndexVec<VariantIdx, LayoutDetails>, }, /// 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<usize>, + dataful_variant: VariantIdx, + niche_variants: RangeInclusive<VariantIdx>, niche: Scalar, niche_start: u128, - variants: Vec<LayoutDetails>, + variants: IndexVec<VariantIdx, LayoutDetails>, } } @@ -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<Ty = Self>>: 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<C>(self, cx: &C, variant_index: usize) -> Self + pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self where Ty: TyLayoutMethods<'a, C>, C: LayoutOf<Ty = Ty> { Ty::for_variant(self, cx, variant_index) } diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs index e60c9922d46..813b39de064 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 7dfdb926c60..2e6797ef23a 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<Discr<'tcx>> = 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 d5f5cbb562e..70af837076f 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 c39b71e33ca..f514cb83a1f 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<T: Clean<U>, U> Clean<Vec<U>> for [T] { } } +impl<T: Clean<U>, U, V: Idx> Clean<IndexVec<V, U>> for IndexVec<V, T> { + fn clean(&self, cx: &DocContext) -> IndexVec<V, U> { + self.iter().map(|x| x.clean(cx)).collect() + } +} + impl<T: Clean<U>, U> Clean<U> for P<T> { fn clean(&self, cx: &DocContext) -> U { (**self).clean(cx) @@ -2886,7 +2894,7 @@ impl Clean<VariantStruct> for ::rustc::hir::VariantData { #[derive(Clone, RustcEncodable, RustcDecodable, Debug)] pub struct Enum { - pub variants: Vec<Item>, + pub variants: IndexVec<VariantIdx, Item>, pub generics: Generics, pub variants_stripped: bool, } @@ -2902,7 +2910,7 @@ impl Clean<Item> 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 804c9643d8a..d36e96b0817 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 .<downcast-variant(Some)>.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 |
