Auto merge of #55589 - oli-obk:min_length_💣, r=pnkfelix

Add `VariantIdx` type and use instead of `usize`
This commit is contained in:
bors 2018-11-13 07:04:14 +00:00
commit 485397e49a
44 changed files with 308 additions and 189 deletions

View File

@ -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",
]

View File

@ -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;
}

View File

@ -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]))

View File

@ -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>,

View File

@ -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,

View File

@ -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);

View File

@ -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>,

View File

@ -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> {

View File

@ -33,6 +33,7 @@ CloneTypeFoldableAndLiftImpls! {
(),
bool,
usize,
::ty::layout::VariantIdx,
u64,
::middle::region::Scope,
::syntax::ast::FloatTy,

View File

@ -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);

View File

@ -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,

View File

@ -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(

View File

@ -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);

View File

@ -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" }

View File

@ -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};

View File

@ -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;
}

View File

@ -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)

View File

@ -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)));

View File

@ -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",

View File

@ -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

View File

@ -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 &&

View File

@ -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> {

View File

@ -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()

View File

@ -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)?;

View File

@ -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),

View File

@ -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()

View File

@ -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 =

View File

@ -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)
}

View File

@ -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 {

View File

@ -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)
}
}
})
}

View File

@ -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),

View File

@ -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]

View File

@ -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 { .. } => {}
}

View File

@ -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

View File

@ -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 {

View File

@ -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)),

View File

@ -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))

View File

@ -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" }

View File

@ -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)
}

View File

@ -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;

View File

@ -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),

View File

@ -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!(),
};

View File

@ -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,
}),

View File

@ -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