Use type safe `VariantIdx` instead of `usize` everywhere

This commit is contained in:
Oliver Scherer 2018-11-01 19:03:38 +01:00
parent 740fb0cbaa
commit 4a9ed3f25a
33 changed files with 144 additions and 104 deletions

View File

@ -2246,6 +2246,7 @@ version = "0.0.0"
dependencies = [ dependencies = [
"log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.5 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc 0.0.0", "rustc 0.0.0",
"rustc_data_structures 0.0.0",
"rustc_mir 0.0.0", "rustc_mir 0.0.0",
"rustc_target 0.0.0", "rustc_target 0.0.0",
"syntax 0.0.0", "syntax 0.0.0",

View File

@ -1754,7 +1754,7 @@ pub enum StatementKind<'tcx> {
/// Write the discriminant for a variant to the enum Place. /// Write the discriminant for a variant to the enum Place.
SetDiscriminant { SetDiscriminant {
place: Place<'tcx>, place: Place<'tcx>,
variant_index: usize, variant_index: VariantIdx,
}, },
/// Start a live range for the storage of the local. /// Start a live range for the storage of the local.

View File

@ -2149,11 +2149,12 @@ impl<'a, 'gcx, 'tcx> AdtDef {
.expect("variant_with_id: unknown variant") .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 self.variants
.iter() .iter_enumerated()
.position(|v| v.did == vid) .find(|(_, v)| v.did == vid)
.expect("variant_index_with_id: unknown variant") .expect("variant_index_with_id: unknown variant")
.0
} }
pub fn variant_of_def(&self, def: Def) -> &VariantDef { pub fn variant_of_def(&self, def: Def) -> &VariantDef {

View File

@ -39,7 +39,7 @@ use rustc::middle::weak_lang_items;
use rustc::mir::mono::{Linkage, Visibility, Stats, CodegenUnitNameBuilder}; use rustc::mir::mono::{Linkage, Visibility, Stats, CodegenUnitNameBuilder};
use rustc::middle::cstore::{EncodedMetadata}; use rustc::middle::cstore::{EncodedMetadata};
use rustc::ty::{self, Ty, TyCtxt}; 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::ty::query::Providers;
use rustc::middle::cstore::{self, LinkagePreference}; use rustc::middle::cstore::{self, LinkagePreference};
use rustc::middle::exported_symbols; use rustc::middle::exported_symbols;
@ -73,6 +73,7 @@ use rustc::util::nodemap::FxHashMap;
use CrateInfo; use CrateInfo;
use rustc_data_structures::small_c_str::SmallCStr; use rustc_data_structures::small_c_str::SmallCStr;
use rustc_data_structures::sync::Lrc; use rustc_data_structures::sync::Lrc;
use rustc_data_structures::indexed_vec::Idx;
use std::any::Any; use std::any::Any;
use std::cmp; use std::cmp;
@ -309,7 +310,7 @@ pub fn coerce_unsized_into(
(&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => { (&ty::Adt(def_a, _), &ty::Adt(def_b, _)) => {
assert_eq!(def_a, 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 src_f = src.project_field(bx, i);
let dst_f = dst.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::mir::mono::Stats;
use rustc::session::config::{self, DebugInfo}; use rustc::session::config::{self, DebugInfo};
use rustc::session::Session; 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::ty::{self, Ty, TyCtxt};
use rustc::util::nodemap::FxHashMap; use rustc::util::nodemap::FxHashMap;
use rustc_target::spec::{HasTargetSpec, Target}; 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 /// See http://llvm.org/docs/LangRef.html#the-llvm-used-global-variable for details
pub used_statics: RefCell<Vec<&'a Value>>, 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 scalar_lltypes: RefCell<FxHashMap<Ty<'tcx>, &'a Type>>,
pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>, pub pointee_infos: RefCell<FxHashMap<(Ty<'tcx>, Size), Option<PointeeInfo>>>,
pub isize_ty: &'a Type, pub isize_ty: &'a Type,

View File

@ -1241,7 +1241,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
// This doesn't matter in this case. // This doesn't matter in this case.
NoDiscriminant NoDiscriminant
}; };
(0..variants.len()).map(|i| { variants.iter_enumerated().map(|(i, _)| {
let variant = self.layout.for_variant(cx, i); let variant = self.layout.for_variant(cx, i);
let (variant_type_metadata, member_desc_factory) = let (variant_type_metadata, member_desc_factory) =
describe_enum_variant(cx, describe_enum_variant(cx,
@ -1341,7 +1341,7 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
} }
] ]
} else { } else {
(0..variants.len()).map(|i| { variants.iter_enumerated().map(|(i, _)| {
let variant = self.layout.for_variant(cx, i); let variant = self.layout.for_variant(cx, i);
let (variant_type_metadata, member_desc_factory) = let (variant_type_metadata, member_desc_factory) =
describe_enum_variant(cx, describe_enum_variant(cx,
@ -1361,8 +1361,8 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
let niche_value = if i == dataful_variant { let niche_value = if i == dataful_variant {
None None
} else { } else {
let value = (i as u128) let value = (i.as_u32() as u128)
.wrapping_sub(*niche_variants.start() as u128) .wrapping_sub(niche_variants.start().as_u32() as u128)
.wrapping_add(niche_start); .wrapping_add(niche_start);
let value = value & ((1u128 << niche.value.size(cx).bits()) - 1); let value = value & ((1u128 << niche.value.size(cx).bits()) - 1);
Some(value as u64) Some(value as u64)
@ -1530,7 +1530,7 @@ fn prepare_enum_metadata(
let def = enum_type.ty_adt_def().unwrap(); let def = enum_type.ty_adt_def().unwrap();
let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx) let enumerators_metadata: Vec<_> = def.discriminants(cx.tcx)
.zip(&def.variants) .zip(&def.variants)
.map(|(discr, v)| { .map(|((_, discr), v)| {
let name = SmallCStr::new(&v.name.as_str()); let name = SmallCStr::new(&v.name.as_str());
unsafe { unsafe {
Some(llvm::LLVMRustDIBuilderCreateEnumerator( Some(llvm::LLVMRustDIBuilderCreateEnumerator(

View File

@ -10,7 +10,7 @@
use llvm::{self, LLVMConstInBoundsGEP}; use llvm::{self, LLVMConstInBoundsGEP};
use rustc::ty::{self, Ty}; 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;
use rustc::mir::tcx::PlaceTy; use rustc::mir::tcx::PlaceTy;
use base; use base;
@ -281,7 +281,7 @@ impl PlaceRef<'ll, 'tcx> {
match self.layout.variants { match self.layout.variants {
layout::Variants::Single { index } => { layout::Variants::Single { index } => {
let discr_val = self.layout.ty.ty_adt_def().map_or( 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); |def| def.discriminant_for_variant(bx.cx.tcx, index).val);
return C_uint_big(cast_to, discr_val); return C_uint_big(cast_to, discr_val);
} }
@ -320,16 +320,16 @@ impl PlaceRef<'ll, 'tcx> {
C_uint_big(niche_llty, niche_start) C_uint_big(niche_llty, niche_start)
}; };
bx.select(bx.icmp(llvm::IntEQ, lldiscr, niche_llval), bx.select(bx.icmp(llvm::IntEQ, lldiscr, niche_llval),
C_uint(cast_to, *niche_variants.start() as u64), C_uint(cast_to, niche_variants.start().as_u32() as u64),
C_uint(cast_to, dataful_variant as u64)) C_uint(cast_to, dataful_variant.as_u32() as u64))
} else { } else {
// Rebase from niche values to discriminant values. // 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 = 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.select(bx.icmp(llvm::IntULE, lldiscr, lldiscr_max),
bx.intcast(lldiscr, cast_to, false), 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 /// Set the discriminant for a new value of the given case of the given
/// representation. /// 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() { if self.layout.for_variant(bx.cx, variant_index).abi.is_uninhabited() {
return; return;
} }
@ -376,7 +376,8 @@ impl PlaceRef<'ll, 'tcx> {
let niche = self.project_field(bx, 0); let niche = self.project_field(bx, 0);
let niche_llty = niche.layout.immediate_llvm_type(bx.cx); 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); .wrapping_add(niche_start);
// FIXME(eddyb) Check the actual primitive type here. // FIXME(eddyb) Check the actual primitive type here.
let niche_llval = if niche_value == 0 { 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> { -> PlaceRef<'ll, 'tcx> {
let mut downcast = *self; let mut downcast = *self;
downcast.layout = self.layout.for_variant(bx.cx, variant_index); 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" } rustc_target = { path = "../librustc_target" }
syntax = { path = "../libsyntax" } syntax = { path = "../libsyntax" }
syntax_pos = { path = "../libsyntax_pos" } 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_mir;
extern crate rustc_target; extern crate rustc_target;
extern crate syntax_pos; extern crate syntax_pos;
extern crate rustc_data_structures;
use rustc::lint; use rustc::lint;
use rustc::lint::{LateContext, LateLintPass, LintPass, LintArray}; use rustc::lint::{LateContext, LateLintPass, LintPass, LintArray};

View File

@ -13,7 +13,8 @@
use rustc::hir::Node; use rustc::hir::Node;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::ty::{self, AdtKind, ParamEnv, Ty, TyCtxt}; 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 util::nodemap::FxHashSet;
use lint::{LateContext, LintContext, LintArray}; use lint::{LateContext, LintContext, LintArray};
use lint::{LintPass, LateLintPass}; 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 { if def.variants.len() == 2 {
let data_idx; let data_idx;
if def.variants[0].fields.is_empty() { let zero = VariantIdx::new(0);
data_idx = 1; let one = VariantIdx::new(1);
} else if def.variants[1].fields.is_empty() {
data_idx = 0; if def.variants[zero].fields.is_empty() {
data_idx = one;
} else if def.variants[one].fields.is_empty() {
data_idx = zero;
} else { } else {
return false; return false;
} }

View File

@ -601,7 +601,7 @@ impl<'a, 'tcx> CrateMetadata {
}) })
.collect() .collect()
} else { } 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) 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::traits::specialization_graph;
use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName}; use rustc::ty::{self, Ty, TyCtxt, ReprOptions, SymbolName};
use rustc::ty::codec::{self as ty_codec, TyEncoder}; use rustc::ty::codec::{self as ty_codec, TyEncoder};
use rustc::ty::layout::VariantIdx;
use rustc::session::config::{self, CrateType}; use rustc::session::config::{self, CrateType};
use rustc::util::nodemap::FxHashMap; 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, /// the right to access any information in the adt-def (including,
/// e.g., the length of the various vectors). /// e.g., the length of the various vectors).
fn encode_enum_variant_info(&mut self, fn encode_enum_variant_info(&mut self,
(enum_did, Untracked(index)): (DefId, Untracked<usize>)) (enum_did, Untracked(index)): (DefId, Untracked<VariantIdx>))
-> Entry<'tcx> { -> Entry<'tcx> {
let tcx = self.tcx; let tcx = self.tcx;
let def = tcx.adt_def(enum_did); let def = tcx.adt_def(enum_did);
@ -675,7 +676,7 @@ impl<'a, 'b: 'a, 'tcx: 'b> IsolatedEncoder<'a, 'b, 'tcx> {
/// vectors). /// vectors).
fn encode_field(&mut self, fn encode_field(&mut self,
(adt_def_id, Untracked((variant_index, field_index))): (DefId, (adt_def_id, Untracked((variant_index, field_index))): (DefId,
Untracked<(usize, Untracked<(VariantIdx,
usize)>)) usize)>))
-> Entry<'tcx> { -> Entry<'tcx> {
let tcx = self.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> { impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
fn encode_fields(&mut self, adt_def_id: DefId) { fn encode_fields(&mut self, adt_def_id: DefId) {
let def = self.tcx.adt_def(adt_def_id); 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() { for (field_index, field) in variant.fields.iter().enumerate() {
self.record(field.did, self.record(field.did,
IsolatedEncoder::encode_field, IsolatedEncoder::encode_field,
@ -1734,7 +1735,7 @@ impl<'a, 'b, 'tcx> IndexBuilder<'a, 'b, 'tcx> {
self.encode_fields(def_id); self.encode_fields(def_id);
let def = self.tcx.adt_def(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, self.record(variant.did,
IsolatedEncoder::encode_enum_variant_info, IsolatedEncoder::encode_enum_variant_info,
(def_id, Untracked(i))); (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::subst::{Subst, Substs, UnpackedKind};
use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind}; use rustc::ty::{self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind};
use rustc_data_structures::fx::{FxHashMap, FxHashSet}; 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::rc::Rc;
use std::{fmt, iter}; use std::{fmt, iter};
use syntax_pos::{Span, DUMMY_SP}; 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 { ProjectionElem::Downcast(adt_def1, index) => match base_ty.sty {
ty::Adt(adt_def, substs) if adt_def.is_enum() && adt_def == adt_def1 => { 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 { PlaceTy::Ty {
ty: span_mirbug_and_err!( ty: span_mirbug_and_err!(
self, self,
@ -654,7 +655,8 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
variant_index, variant_index,
} => (&adt_def.variants[variant_index], substs), } => (&adt_def.variants[variant_index], substs),
PlaceTy::Ty { ty } => match ty.sty { 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) => { ty::Closure(def_id, substs) => {
return match substs.upvar_tys(def_id, tcx).nth(field.index()) { return match substs.upvar_tys(def_id, tcx).nth(field.index()) {
Some(ty) => Ok(ty), 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!( span_bug!(
stmt.source_info.span, stmt.source_info.span,
"bad set discriminant ({:?} = {:?}): value of of range", "bad set discriminant ({:?} = {:?}): value of of range",

View File

@ -22,6 +22,7 @@ use hair::pattern::PatternTypeProjections;
use rustc::hir; use rustc::hir;
use rustc::mir::*; use rustc::mir::*;
use rustc::ty::{self, Ty}; use rustc::ty::{self, Ty};
use rustc::ty::layout::VariantIdx;
use rustc_data_structures::bit_set::BitSet; use rustc_data_structures::bit_set::BitSet;
use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::fx::FxHashMap;
use syntax::ast::{Name, NodeId}; use syntax::ast::{Name, NodeId};
@ -663,7 +664,7 @@ enum TestKind<'tcx> {
// test the branches of enum // test the branches of enum
Switch { Switch {
adt_def: &'tcx ty::AdtDef, adt_def: &'tcx ty::AdtDef,
variants: BitSet<usize>, variants: BitSet<VariantIdx>,
}, },
// test the branches of enum // 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 } => { 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 || { i == variant_index || {
self.hir.tcx().features().never_type && self.hir.tcx().features().never_type &&
self.hir.tcx().features().exhaustive_patterns && 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_data_structures::fx::FxHashMap;
use rustc::ty::{self, Ty}; use rustc::ty::{self, Ty};
use rustc::ty::util::IntTypeExt; use rustc::ty::util::IntTypeExt;
use rustc::ty::layout::VariantIdx;
use rustc::mir::*; use rustc::mir::*;
use rustc::hir::{RangeEnd, Mutability}; use rustc::hir::{RangeEnd, Mutability};
use syntax_pos::Span; 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, pub fn add_variants_to_switch<'pat>(&mut self,
test_place: &Place<'tcx>, test_place: &Place<'tcx>,
candidate: &Candidate<'pat, 'tcx>, candidate: &Candidate<'pat, 'tcx>,
variants: &mut BitSet<usize>) variants: &mut BitSet<VariantIdx>)
-> bool -> bool
{ {
let match_pair = match candidate.match_pairs.iter().find(|mp| mp.place == *test_place) { 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 targets = Vec::with_capacity(used_variants + 1);
let mut values = Vec::with_capacity(used_variants); let mut values = Vec::with_capacity(used_variants);
let tcx = self.hir.tcx(); 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) { target_blocks.push(if variants.contains(idx) {
values.push(discr.val); values.push(discr.val);
targets.push(self.cfg.start_new_block()); targets.push(self.cfg.start_new_block());
@ -512,7 +513,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
variant_index, variant_index,
subpatterns, subpatterns,
candidate); candidate);
resulting_candidates[variant_index].push(new_candidate); resulting_candidates[variant_index.as_usize()].push(new_candidate);
true true
} }
(&TestKind::Switch { .. }, _) => false, (&TestKind::Switch { .. }, _) => false,
@ -673,7 +674,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
fn candidate_after_variant_switch<'pat>(&mut self, fn candidate_after_variant_switch<'pat>(&mut self,
match_pair_index: usize, match_pair_index: usize,
adt_def: &'tcx ty::AdtDef, adt_def: &'tcx ty::AdtDef,
variant_index: usize, variant_index: VariantIdx,
subpatterns: &'pat [FieldPattern<'tcx>], subpatterns: &'pat [FieldPattern<'tcx>],
candidate: &Candidate<'pat, 'tcx>) candidate: &Candidate<'pat, 'tcx>)
-> Candidate<'pat, 'tcx> { -> Candidate<'pat, 'tcx> {

View File

@ -13,6 +13,7 @@ use build::matches::MatchPair;
use hair::*; use hair::*;
use rustc::mir::*; use rustc::mir::*;
use std::u32; use std::u32;
use std::convert::TryInto;
impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
pub fn field_match_pairs<'pat>(&mut self, pub fn field_match_pairs<'pat>(&mut self,

View File

@ -21,7 +21,7 @@ use rustc::hir::def::Def;
use rustc::mir::interpret::{ConstEvalErr, ErrorHandled}; use rustc::mir::interpret::{ConstEvalErr, ErrorHandled};
use rustc::mir; use rustc::mir;
use rustc::ty::{self, TyCtxt, Instance, query::TyCtxtAt}; 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::ty::subst::Subst;
use rustc::traits::Reveal; use rustc::traits::Reveal;
use rustc_data_structures::indexed_vec::IndexVec; use rustc_data_structures::indexed_vec::IndexVec;
@ -481,7 +481,7 @@ pub fn const_field<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
instance: ty::Instance<'tcx>, instance: ty::Instance<'tcx>,
variant: Option<u32>, variant: Option<VariantIdx>,
field: mir::Field, field: mir::Field,
value: &'tcx ty::Const<'tcx>, value: &'tcx ty::Const<'tcx>,
) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> { ) -> ::rustc::mir::interpret::ConstEvalResult<'tcx> {
@ -513,7 +513,7 @@ pub fn const_variant_index<'a, 'tcx>(
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
instance: ty::Instance<'tcx>, instance: ty::Instance<'tcx>,
val: &'tcx ty::Const<'tcx>, val: &'tcx ty::Const<'tcx>,
) -> EvalResult<'tcx, usize> { ) -> EvalResult<'tcx, VariantIdx> {
trace!("const_variant_index: {:?}, {:?}", instance, val); trace!("const_variant_index: {:?}, {:?}", instance, val);
let ecx = mk_eval_cx(tcx, instance, param_env).unwrap(); let ecx = mk_eval_cx(tcx, instance, param_env).unwrap();
let op = ecx.const_to_op(val)?; 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))) Some((adt_def, adt_def.variant_index_with_id(variant_id)))
} }
Def::StructCtor(_, CtorKind::Fn) | Def::StructCtor(_, CtorKind::Fn) |
Def::SelfCtor(..) => Some((adt_def, 0)), Def::SelfCtor(..) => Some((adt_def, VariantIdx::new(0))),
_ => None, _ => None,
} }
}) })
@ -468,7 +468,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>,
AdtKind::Struct | AdtKind::Union => { AdtKind::Struct | AdtKind::Union => {
ExprKind::Adt { ExprKind::Adt {
adt_def: adt, adt_def: adt,
variant_index: 0, variant_index: VariantIdx::new(0),
substs, substs,
user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt), user_ty: cx.user_substs_applied_to_adt(expr.hir_id, adt),
fields: field_refs(cx, fields), fields: field_refs(cx, fields),

View File

@ -25,6 +25,7 @@ use rustc::infer::InferCtxt;
use rustc::ty::subst::Subst; use rustc::ty::subst::Subst;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::subst::{Kind, Substs}; use rustc::ty::subst::{Kind, Substs};
use rustc::ty::layout::VariantIdx;
use syntax::ast::{self, LitKind}; use syntax::ast::{self, LitKind};
use syntax::attr; use syntax::attr;
use syntax::symbol::Symbol; 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); 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()) (0..adt_def.variants[variant_index].fields.len())
.map(Field::new) .map(Field::new)
.collect() .collect()

View File

@ -19,6 +19,7 @@ use rustc::hir::def_id::DefId;
use rustc::middle::region; use rustc::middle::region;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const}; use rustc::ty::{AdtDef, UpvarSubsts, Region, Ty, Const};
use rustc::ty::layout::VariantIdx;
use rustc::hir; use rustc::hir;
use syntax::ast; use syntax::ast;
use syntax_pos::Span; use syntax_pos::Span;
@ -264,7 +265,7 @@ pub enum ExprKind<'tcx> {
}, },
Adt { Adt {
adt_def: &'tcx AdtDef, adt_def: &'tcx AdtDef,
variant_index: usize, variant_index: VariantIdx,
substs: &'tcx Substs<'tcx>, substs: &'tcx Substs<'tcx>,
/// Optional user-given substs: for something like `let x = /// 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::def_id::DefId;
use rustc::hir::RangeEnd; use rustc::hir::RangeEnd;
use rustc::ty::{self, Ty, TyCtxt, TypeFoldable}; 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::Field;
use rustc::mir::interpret::ConstValue; use rustc::mir::interpret::ConstValue;
@ -422,12 +422,12 @@ pub enum Constructor<'tcx> {
} }
impl<'tcx> 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 { match self {
&Variant(vid) => adt.variant_index_with_id(vid), &Variant(vid) => adt.variant_index_with_id(vid),
&Single => { &Single => {
assert!(!adt.is_enum()); assert!(!adt.is_enum());
0 VariantIdx::new(0)
} }
_ => bug!("bad constructor {:?} for adt {:?}", self, adt) _ => 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::mir::interpret::{Scalar, GlobalId, ConstValue, sign_extend};
use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty}; use rustc::ty::{self, Region, TyCtxt, AdtDef, Ty};
use rustc::ty::subst::{Substs, Kind}; use rustc::ty::subst::{Substs, Kind};
use rustc::ty::layout::VariantIdx;
use rustc::hir::{self, PatKind, RangeEnd}; use rustc::hir::{self, PatKind, RangeEnd};
use rustc::hir::def::{Def, CtorKind}; use rustc::hir::def::{Def, CtorKind};
use rustc::hir::pat_util::EnumerateAndAdjustIterator; use rustc::hir::pat_util::EnumerateAndAdjustIterator;
@ -111,7 +112,7 @@ impl<'tcx> PatternTypeProjections<'tcx> {
pub(crate) fn variant(&self, pub(crate) fn variant(&self,
adt_def: &'tcx AdtDef, adt_def: &'tcx AdtDef,
variant_index: usize, variant_index: VariantIdx,
field: Field) -> Self { field: Field) -> Self {
self.map_projs(|pat_ty_proj| pat_ty_proj.variant(adt_def, variant_index, field)) 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, pub(crate) fn variant(&self,
adt_def: &'tcx AdtDef, adt_def: &'tcx AdtDef,
variant_index: usize, variant_index: VariantIdx,
field: Field) -> Self { field: Field) -> Self {
let mut new = self.clone(); let mut new = self.clone();
new.0.projs.push(ProjectionElem::Downcast(adt_def, variant_index)); new.0.projs.push(ProjectionElem::Downcast(adt_def, variant_index));
@ -200,7 +201,7 @@ pub enum PatternKind<'tcx> {
Variant { Variant {
adt_def: &'tcx AdtDef, adt_def: &'tcx AdtDef,
substs: &'tcx Substs<'tcx>, substs: &'tcx Substs<'tcx>,
variant_index: usize, variant_index: VariantIdx,
subpatterns: Vec<FieldPattern<'tcx>>, subpatterns: Vec<FieldPattern<'tcx>>,
}, },
@ -273,7 +274,7 @@ impl<'tcx> fmt::Display for Pattern<'tcx> {
} }
_ => if let ty::Adt(adt, _) = self.ty.sty { _ => if let ty::Adt(adt, _) = self.ty.sty {
if !adt.is_enum() { if !adt.is_enum() {
Some(&adt.variants[0]) Some(&adt.variants[VariantIdx::new(0)])
} else { } else {
None None
} }
@ -1160,7 +1161,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatternKind<'tcx> {
} => PatternKind::Variant { } => PatternKind::Variant {
adt_def: adt_def.fold_with(folder), adt_def: adt_def.fold_with(folder),
substs: substs.fold_with(folder), substs: substs.fold_with(folder),
variant_index: variant_index.fold_with(folder), variant_index,
subpatterns: subpatterns.fold_with(folder) subpatterns: subpatterns.fold_with(folder)
}, },
PatternKind::Leaf { PatternKind::Leaf {

View File

@ -14,7 +14,7 @@
use std::convert::TryInto; use std::convert::TryInto;
use rustc::{mir, ty}; 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::{ use rustc::mir::interpret::{
GlobalId, AllocId, GlobalId, AllocId,
@ -417,7 +417,7 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
pub fn operand_downcast( pub fn operand_downcast(
&self, &self,
op: OpTy<'tcx, M::PointerTag>, op: OpTy<'tcx, M::PointerTag>,
variant: usize, variant: VariantIdx,
) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> { ) -> EvalResult<'tcx, OpTy<'tcx, M::PointerTag>> {
// Downcasts only change the layout // Downcasts only change the layout
Ok(match op.try_as_mplace() { 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( pub fn read_discriminant(
&self, &self,
rval: OpTy<'tcx, M::PointerTag>, rval: OpTy<'tcx, M::PointerTag>,
) -> EvalResult<'tcx, (u128, usize)> { ) -> EvalResult<'tcx, (u128, VariantIdx)> {
trace!("read_discriminant_value {:#?}", rval.layout); trace!("read_discriminant_value {:#?}", rval.layout);
match rval.layout.variants { match rval.layout.variants {
layout::Variants::Single { index } => { layout::Variants::Single { index } => {
let discr_val = rval.layout.ty.ty_adt_def().map_or( 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); |def| def.discriminant_for_variant(*self.tcx, index).val);
return Ok((discr_val, index)); 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() .ty_adt_def()
.expect("tagged layout for non adt") .expect("tagged layout for non adt")
.discriminants(self.tcx.tcx) .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()))?; .ok_or_else(|| EvalErrorKind::InvalidDiscriminant(raw_discr.erase_tag()))?;
(real_discr, index) (real_discr, index.0)
}, },
layout::Variants::NicheFilling { layout::Variants::NicheFilling {
dataful_variant, dataful_variant,
@ -655,33 +655,32 @@ impl<'a, 'mir, 'tcx, M: Machine<'a, 'mir, 'tcx>> EvalContext<'a, 'mir, 'tcx, M>
niche_start, niche_start,
.. ..
} => { } => {
let variants_start = *niche_variants.start() as u128; let variants_start = niche_variants.start().as_u32() as u128;
let variants_end = *niche_variants.end() as u128; let variants_end = niche_variants.end().as_u32() as u128;
let real_discr = match raw_discr { match raw_discr {
Scalar::Ptr(_) => { Scalar::Ptr(_) => {
// The niche must be just 0 (which a pointer value never is) // The niche must be just 0 (which a pointer value never is)
assert!(niche_start == 0); assert!(niche_start == 0);
assert!(variants_start == variants_end); assert!(variants_start == variants_end);
dataful_variant as u128 (dataful_variant.as_u32() as u128, dataful_variant)
}, },
Scalar::Bits { bits: raw_discr, size } => { Scalar::Bits { bits: raw_discr, size } => {
assert_eq!(size as u64, discr_val.layout.size.bytes()); assert_eq!(size as u64, discr_val.layout.size.bytes());
let discr = raw_discr.wrapping_sub(niche_start) let discr = raw_discr.wrapping_sub(niche_start)
.wrapping_add(variants_start); .wrapping_add(variants_start);
if variants_start <= discr && discr <= variants_end { 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 { } 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::hir;
use rustc::mir; use rustc::mir;
use rustc::ty::{self, Ty}; 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::{ use rustc::mir::interpret::{
GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic GlobalId, AllocId, Allocation, Scalar, EvalResult, Pointer, PointerArithmetic
@ -431,7 +431,7 @@ where
pub fn mplace_downcast( pub fn mplace_downcast(
&self, &self,
base: MPlaceTy<'tcx, M::PointerTag>, base: MPlaceTy<'tcx, M::PointerTag>,
variant: usize, variant: VariantIdx,
) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> { ) -> EvalResult<'tcx, MPlaceTy<'tcx, M::PointerTag>> {
// Downcasts only change the layout // Downcasts only change the layout
assert!(base.meta.is_none()); assert!(base.meta.is_none());
@ -498,7 +498,7 @@ where
pub fn place_downcast( pub fn place_downcast(
&self, &self,
base: PlaceTy<'tcx, M::PointerTag>, base: PlaceTy<'tcx, M::PointerTag>,
variant: usize, variant: VariantIdx,
) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> { ) -> EvalResult<'tcx, PlaceTy<'tcx, M::PointerTag>> {
// Downcast just changes the layout // Downcast just changes the layout
Ok(match base.place { Ok(match base.place {
@ -901,7 +901,7 @@ where
pub fn write_discriminant_index( pub fn write_discriminant_index(
&mut self, &mut self,
variant_index: usize, variant_index: VariantIdx,
dest: PlaceTy<'tcx, M::PointerTag>, dest: PlaceTy<'tcx, M::PointerTag>,
) -> EvalResult<'tcx> { ) -> EvalResult<'tcx> {
match dest.layout.variants { match dest.layout.variants {
@ -910,7 +910,7 @@ where
} }
layout::Variants::Tagged { ref tag, .. } => { layout::Variants::Tagged { ref tag, .. } => {
let adt_def = dest.layout.ty.ty_adt_def().unwrap(); 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 let discr_val = adt_def
.discriminant_for_variant(*self.tcx, variant_index) .discriminant_for_variant(*self.tcx, variant_index)
.val; .val;
@ -931,11 +931,14 @@ where
niche_start, 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 { if variant_index != dataful_variant {
let niche_dest = let niche_dest =
self.place_field(dest, 0)?; 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); .wrapping_add(niche_start);
self.write_scalar( self.write_scalar(
Scalar::from_uint(niche_value, niche_dest.layout.size), Scalar::from_uint(niche_value, niche_dest.layout.size),

View File

@ -13,6 +13,7 @@ use rustc::hir::def_id::DefId;
use rustc::infer; use rustc::infer;
use rustc::mir::*; use rustc::mir::*;
use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind}; use rustc::ty::{self, Ty, TyCtxt, GenericParamDefKind};
use rustc::ty::layout::VariantIdx;
use rustc::ty::subst::{Subst, Substs}; use rustc::ty::subst::{Subst, Substs};
use rustc::ty::query::Providers; 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> { fn deref_subpath(&self, _path: Self::Path) -> Option<Self::Path> {
None 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(()) Some(())
} }
fn array_subpath(&self, _path: Self::Path, _index: u32, _size: u32) -> Option<Self::Path> { 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() { let variant_no = if adt_def.is_enum() {
adt_def.variant_index_with_id(def_id) adt_def.variant_index_with_id(def_id)
} else { } else {
0 VariantIdx::new(0)
}; };
// return = ADT(arg0, arg1, ...); return // 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::MoveDataParamEnv;
use dataflow::{self, do_dataflow, DebugFormatted}; use dataflow::{self, do_dataflow, DebugFormatted};
use rustc::ty::{self, TyCtxt}; use rustc::ty::{self, TyCtxt};
use rustc::ty::layout::VariantIdx;
use rustc::mir::*; use rustc::mir::*;
use rustc::util::nodemap::FxHashMap; use rustc::util::nodemap::FxHashMap;
use rustc_data_structures::bit_set::BitSet; 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| { dataflow::move_path_children_matching(self.ctxt.move_data(), path, |p| {
match p { match p {
&Projection { &Projection {

View File

@ -64,6 +64,7 @@ use rustc::hir::def_id::DefId;
use rustc::mir::*; use rustc::mir::*;
use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor}; use rustc::mir::visit::{PlaceContext, Visitor, MutVisitor};
use rustc::ty::{self, TyCtxt, AdtDef, Ty}; use rustc::ty::{self, TyCtxt, AdtDef, Ty};
use rustc::ty::layout::VariantIdx;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use util::dump_mir; use util::dump_mir;
use util::liveness::{self, IdentityMap}; use util::liveness::{self, IdentityMap};
@ -158,7 +159,7 @@ struct TransformVisitor<'a, 'tcx: 'a> {
impl<'a, 'tcx> TransformVisitor<'a, 'tcx> { impl<'a, 'tcx> TransformVisitor<'a, 'tcx> {
// Make a GeneratorState rvalue // 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); let adt = AggregateKind::Adt(self.state_adt_ref, idx, self.state_substs, None, None);
Rvalue::Aggregate(box adt, vec![val]) 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 { let ret_val = match data.terminator().kind {
TerminatorKind::Return => Some((1, TerminatorKind::Return => Some((VariantIdx::new(1),
None, None,
Operand::Move(Place::Local(self.new_ret_local)), Operand::Move(Place::Local(self.new_ret_local)),
None)), None)),
TerminatorKind::Yield { ref value, resume, drop } => Some((0, TerminatorKind::Yield { ref value, resume, drop } => Some((VariantIdx::new(0),
Some(resume), Some(resume),
value.clone(), value.clone(),
drop)), drop)),

View File

@ -14,6 +14,7 @@ use rustc::mir::*;
use rustc::middle::lang_items; use rustc::middle::lang_items;
use rustc::traits::Reveal; use rustc::traits::Reveal;
use rustc::ty::{self, Ty, TyCtxt}; use rustc::ty::{self, Ty, TyCtxt};
use rustc::ty::layout::VariantIdx;
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::ty::util::IntTypeExt; use rustc::ty::util::IntTypeExt;
use rustc_data_structures::indexed_vec::Idx; 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 field_subpath(&self, path: Self::Path, field: Field) -> Option<Self::Path>;
fn deref_subpath(&self, path: Self::Path) -> 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>; 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( let fields = self.move_paths_for_fields(
self.place, self.place,
self.path, self.path,
&adt.variants[0], &adt.variants[VariantIdx::new(0)],
substs substs
); );
self.drop_ladder(fields, succ, unwind) 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; 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( let subpath = self.elaborator.downcast_subpath(
self.path, variant_index); self.path, variant_index);
if let Some(variant_path) = subpath { 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 tcx = self.tcx();
let unit_temp = Place::Local(self.new_temp(tcx.mk_unit())); let unit_temp = Place::Local(self.new_temp(tcx.mk_unit()));
let free_func = tcx.require_lang_item(lang_items::BoxFreeFnLangItem); 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 = Field::new(i);
let field_ty = f.ty(self.tcx(), substs); let field_ty = f.ty(self.tcx(), substs);
Operand::Move(self.place.clone().field(field, field_ty)) Operand::Move(self.place.clone().field(field, field_ty))

View File

@ -914,7 +914,11 @@ pub trait LayoutOf {
} }
pub trait TyLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized { pub trait TyLayoutMethods<'a, C: LayoutOf<Ty = Self>>: Sized {
fn for_variant(this: TyLayout<'a, Self>, cx: &C, variant_index: VariantIdx) -> 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; fn field(this: TyLayout<'a, Self>, cx: &C, i: usize) -> C::TyLayout;
} }

View File

@ -103,6 +103,8 @@ use rustc::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase, AutoBorrow, AutoB
use rustc::ty::fold::TypeFoldable; use rustc::ty::fold::TypeFoldable;
use rustc::ty::query::Providers; use rustc::ty::query::Providers;
use rustc::ty::util::{Representability, IntTypeExt, Discr}; 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 errors::{Applicability, DiagnosticBuilder, DiagnosticId};
use require_c_abi_if_variadic; 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()); 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 // Check for duplicate discriminant values
if let Some(i) = disr_vals.iter().position(|&x| x.val == discr.val) { 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 variant_i = tcx.hir.expect_variant(variant_i_node_id);
let i_span = match variant_i.node.disr_expr { let i_span = match variant_i.node.disr_expr {
Some(ref expr) => tcx.hir.span(expr.id), 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, AdtKind::Struct,
vec![convert_variant( std::iter::once(convert_variant(
tcx, tcx,
ctor_id.unwrap_or(def_id), ctor_id.unwrap_or(def_id),
item.name, item.name,
@ -659,12 +659,12 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad
def, def,
AdtKind::Struct, AdtKind::Struct,
def_id def_id
)], )).collect(),
) )
} }
ItemKind::Union(ref def, _) => ( ItemKind::Union(ref def, _) => (
AdtKind::Union, AdtKind::Union,
vec![convert_variant( std::iter::once(convert_variant(
tcx, tcx,
def_id, def_id,
item.name, item.name,
@ -672,7 +672,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad
def, def,
AdtKind::Union, AdtKind::Union,
def_id def_id
)], )).collect(),
), ),
_ => bug!(), _ => 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::hir::def_id::{CrateNum, DefId, CRATE_DEF_INDEX, LOCAL_CRATE};
use rustc::ty::subst::Substs; use rustc::ty::subst::Substs;
use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind}; use rustc::ty::{self, TyCtxt, Region, RegionVid, Ty, AdtKind};
use rustc::ty::layout::VariantIdx;
use rustc::middle::stability; use rustc::middle::stability;
use rustc::util::nodemap::{FxHashMap, FxHashSet}; use rustc::util::nodemap::{FxHashMap, FxHashSet};
use rustc_typeck::hir_ty_to_ty; use rustc_typeck::hir_ty_to_ty;
use rustc::infer::region_constraints::{RegionConstraintData, Constraint}; use rustc::infer::region_constraints::{RegionConstraintData, Constraint};
use rustc_data_structures::indexed_vec::{IndexVec, Idx};
use std::collections::hash_map::Entry; use std::collections::hash_map::Entry;
use std::fmt; 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> { impl<T: Clean<U>, U> Clean<U> for P<T> {
fn clean(&self, cx: &DocContext) -> U { fn clean(&self, cx: &DocContext) -> U {
(**self).clean(cx) (**self).clean(cx)
@ -2886,7 +2894,7 @@ impl Clean<VariantStruct> for ::rustc::hir::VariantData {
#[derive(Clone, RustcEncodable, RustcDecodable, Debug)] #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
pub struct Enum { pub struct Enum {
pub variants: Vec<Item>, pub variants: IndexVec<VariantIdx, Item>,
pub generics: Generics, pub generics: Generics,
pub variants_stripped: bool, pub variants_stripped: bool,
} }
@ -2902,7 +2910,7 @@ impl Clean<Item> for doctree::Enum {
stability: self.stab.clean(cx), stability: self.stab.clean(cx),
deprecation: self.depr.clean(cx), deprecation: self.depr.clean(cx),
inner: EnumItem(Enum { inner: EnumItem(Enum {
variants: self.variants.clean(cx), variants: self.variants.iter().map(|v| v.clean(cx)).collect(),
generics: self.generics.clean(cx), generics: self.generics.clean(cx),
variants_stripped: false, variants_stripped: false,
}), }),