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 = [
"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",

View File

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

View File

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

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,

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

@ -914,7 +914,11 @@ pub trait LayoutOf {
}
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;
}

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