Cleanup of ty::VariantInfo and related functions.
This commit is contained in:
parent
77a00cca03
commit
12d87d39c1
@ -90,7 +90,7 @@ pub fn maybe_get_item_ast(tcx: ty::ctxt, def: ast::def_id,
|
||||
}
|
||||
|
||||
pub fn get_enum_variants(tcx: ty::ctxt, def: ast::def_id)
|
||||
-> ~[ty::VariantInfo] {
|
||||
-> ~[@ty::VariantInfo] {
|
||||
let cstore = tcx.cstore;
|
||||
let cdata = cstore::get_crate_data(cstore, def.crate);
|
||||
return decoder::get_enum_variants(cstore.intr, cdata, def.node, tcx)
|
||||
|
@ -733,11 +733,11 @@ pub fn maybe_get_item_ast(cdata: cmd, tcx: ty::ctxt,
|
||||
}
|
||||
|
||||
pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
|
||||
tcx: ty::ctxt) -> ~[ty::VariantInfo] {
|
||||
tcx: ty::ctxt) -> ~[@ty::VariantInfo] {
|
||||
let data = cdata.data;
|
||||
let items = reader::get_doc(reader::Doc(data), tag_items);
|
||||
let item = find_item(id, items);
|
||||
let mut infos: ~[ty::VariantInfo] = ~[];
|
||||
let mut infos: ~[@ty::VariantInfo] = ~[];
|
||||
let variant_ids = enum_variant_ids(item, cdata);
|
||||
let mut disr_val = 0;
|
||||
for variant_ids.iter().advance |did| {
|
||||
@ -753,7 +753,7 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
|
||||
Some(val) => { disr_val = val; }
|
||||
_ => { /* empty */ }
|
||||
}
|
||||
infos.push(@ty::VariantInfo_{
|
||||
infos.push(@ty::VariantInfo{
|
||||
args: arg_tys,
|
||||
arg_names: None,
|
||||
ctor_ty: ctor_ty,
|
||||
|
@ -671,7 +671,7 @@ pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
|
||||
let _icx = push_ctxt("iter_structural_ty");
|
||||
|
||||
fn iter_variant(cx: block, repr: &adt::Repr, av: ValueRef,
|
||||
variant: ty::VariantInfo,
|
||||
variant: @ty::VariantInfo,
|
||||
tps: &[ty::t], f: val_and_ty_fn) -> block {
|
||||
let _icx = push_ctxt("iter_variant");
|
||||
let tcx = cx.tcx();
|
||||
@ -2110,7 +2110,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
|
||||
}
|
||||
|
||||
pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def,
|
||||
id: ast::node_id, vi: @~[ty::VariantInfo],
|
||||
id: ast::node_id, vi: @~[@ty::VariantInfo],
|
||||
i: &mut uint) {
|
||||
for enum_definition.variants.iter().advance |variant| {
|
||||
let disr_val = vi[*i].disr_val;
|
||||
|
@ -50,6 +50,8 @@ use syntax::opt_vec;
|
||||
use syntax::abi::AbiSet;
|
||||
use syntax;
|
||||
|
||||
pub static INITIAL_DISCRIMINANT_VALUE: int = 0;
|
||||
|
||||
// Data types
|
||||
|
||||
#[deriving(Eq, IterBytes)]
|
||||
@ -282,7 +284,7 @@ struct ctxt_ {
|
||||
needs_unwind_cleanup_cache: @mut HashMap<t, bool>,
|
||||
tc_cache: @mut HashMap<uint, TypeContents>,
|
||||
ast_ty_to_ty_cache: @mut HashMap<node_id, ast_ty_to_ty_cache_entry>,
|
||||
enum_var_cache: @mut HashMap<def_id, @~[VariantInfo]>,
|
||||
enum_var_cache: @mut HashMap<def_id, @~[@VariantInfo]>,
|
||||
ty_param_defs: @mut HashMap<ast::node_id, TypeParameterDef>,
|
||||
adjustments: @mut HashMap<ast::node_id, @AutoAdjustment>,
|
||||
normalized_cache: @mut HashMap<t, t>,
|
||||
@ -3702,19 +3704,70 @@ pub struct VariantInfo_ {
|
||||
vis: visibility
|
||||
}
|
||||
|
||||
pub type VariantInfo = @VariantInfo_;
|
||||
impl VariantInfo {
|
||||
|
||||
/// Creates a new VariantInfo from the corresponding ast representation.
|
||||
///
|
||||
/// Does not do any caching of the value in the type context.
|
||||
pub fn from_ast_variant(cx: ctxt,
|
||||
ast_variant: &ast::variant,
|
||||
discriminant: int) -> VariantInfo {
|
||||
|
||||
let ctor_ty = node_id_to_type(cx, ast_variant.node.id);
|
||||
|
||||
match ast_variant.node.kind {
|
||||
ast::tuple_variant_kind(ref args) => {
|
||||
let arg_tys = if args.len() > 0 { ty_fn_args(ctor_ty).map(|a| *a) } else { ~[] };
|
||||
|
||||
return VariantInfo {
|
||||
args: arg_tys,
|
||||
arg_names: None,
|
||||
ctor_ty: ctor_ty,
|
||||
name: ast_variant.node.name,
|
||||
id: ast_util::local_def(ast_variant.node.id),
|
||||
disr_val: discriminant,
|
||||
vis: ast_variant.node.vis
|
||||
};
|
||||
},
|
||||
ast::struct_variant_kind(ref struct_def) => {
|
||||
|
||||
let fields : &[@struct_field] = struct_def.fields;
|
||||
|
||||
assert!(fields.len() > 0);
|
||||
|
||||
let arg_tys = ty_fn_args(ctor_ty).map(|a| *a);
|
||||
let arg_names = do fields.map |field| {
|
||||
match field.node.kind {
|
||||
named_field(ident, _visibility) => ident,
|
||||
unnamed_field => cx.sess.bug(
|
||||
"enum_variants: all fields in struct must have a name")
|
||||
}};
|
||||
|
||||
return VariantInfo {
|
||||
args: arg_tys,
|
||||
arg_names: Some(arg_names),
|
||||
ctor_ty: ctor_ty,
|
||||
name: ast_variant.node.name,
|
||||
id: ast_util::local_def(ast_variant.node.id),
|
||||
disr_val: discriminant,
|
||||
vis: ast_variant.node.vis
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn substd_enum_variants(cx: ctxt,
|
||||
id: ast::def_id,
|
||||
substs: &substs)
|
||||
-> ~[VariantInfo] {
|
||||
-> ~[@VariantInfo] {
|
||||
do enum_variants(cx, id).iter().transform |variant_info| {
|
||||
let substd_args = variant_info.args.iter()
|
||||
.transform(|aty| subst(cx, substs, *aty)).collect();
|
||||
|
||||
let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
|
||||
|
||||
@VariantInfo_ {
|
||||
@VariantInfo {
|
||||
args: substd_args,
|
||||
ctor_ty: substd_ctor_ty,
|
||||
..(**variant_info).clone()
|
||||
@ -3832,7 +3885,7 @@ pub fn type_is_empty(cx: ctxt, t: t) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
|
||||
pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[@VariantInfo] {
|
||||
match cx.enum_var_cache.find(&id) {
|
||||
Some(&variants) => return variants,
|
||||
_ => { /* fallthrough */ }
|
||||
@ -3851,71 +3904,26 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
|
||||
node: ast::item_enum(ref enum_definition, _),
|
||||
_
|
||||
}, _) => {
|
||||
let mut disr_val = -1;
|
||||
let mut last_discriminant : Option<int> = None;
|
||||
@enum_definition.variants.iter().transform(|variant| {
|
||||
|
||||
let ctor_ty = node_id_to_type(cx, variant.node.id);
|
||||
let mut discriminant = match last_discriminant {
|
||||
Some(val) => val + 1,
|
||||
None => INITIAL_DISCRIMINANT_VALUE
|
||||
};
|
||||
|
||||
match variant.node.kind {
|
||||
ast::tuple_variant_kind(ref args) => {
|
||||
let arg_tys = if args.len() > 0u {
|
||||
ty_fn_args(ctor_ty).map(|a| *a) }
|
||||
else {
|
||||
~[]
|
||||
};
|
||||
|
||||
match variant.node.disr_expr {
|
||||
Some (ex) => {
|
||||
disr_val = match const_eval::eval_const_expr(cx,
|
||||
ex) {
|
||||
const_eval::const_int(val) => val as int,
|
||||
_ => cx.sess.bug("enum_variants: bad disr expr")
|
||||
}
|
||||
}
|
||||
_ => disr_val += 1
|
||||
}
|
||||
@VariantInfo_{
|
||||
args: arg_tys,
|
||||
arg_names: None,
|
||||
ctor_ty: ctor_ty,
|
||||
name: variant.node.name,
|
||||
id: ast_util::local_def(variant.node.id),
|
||||
disr_val: disr_val,
|
||||
vis: variant.node.vis
|
||||
}
|
||||
match variant.node.disr_expr {
|
||||
Some(e) => match const_eval::eval_const_expr_partial(cx, e) {
|
||||
Ok(const_eval::const_int(val)) => { discriminant = val as int; }
|
||||
_ => {}
|
||||
},
|
||||
ast::struct_variant_kind(struct_def) => {
|
||||
None => {}
|
||||
};
|
||||
|
||||
let fields : &[@struct_field] = struct_def.fields;
|
||||
let variant_info = @VariantInfo::from_ast_variant(cx, variant, discriminant);
|
||||
last_discriminant = Some(discriminant);
|
||||
variant_info
|
||||
|
||||
let (arg_tys, arg_names) =
|
||||
if fields.len() > 0 {
|
||||
let arg_tys = ty_fn_args(ctor_ty).map(|a| *a);
|
||||
let arg_names = do fields.map |field| { match field.node.kind {
|
||||
named_field(ident, _visibility) => ident,
|
||||
unnamed_field => cx.sess.bug(
|
||||
"enum_variants: all fields in struct must have a name")
|
||||
}};
|
||||
|
||||
(arg_tys, Some(arg_names))
|
||||
} else {
|
||||
(~[], None)
|
||||
};
|
||||
|
||||
assert!(variant.node.disr_expr.is_none());
|
||||
disr_val += 1;
|
||||
|
||||
@VariantInfo_{
|
||||
args: arg_tys,
|
||||
arg_names: arg_names,
|
||||
ctor_ty: ctor_ty,
|
||||
name: variant.node.name,
|
||||
id: ast_util::local_def(variant.node.id),
|
||||
disr_val: disr_val,
|
||||
vis: variant.node.vis
|
||||
}
|
||||
}
|
||||
}
|
||||
}).collect()
|
||||
}
|
||||
_ => cx.sess.bug("enum_variants: id not bound to an enum")
|
||||
@ -3930,7 +3938,7 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
|
||||
pub fn enum_variant_with_id(cx: ctxt,
|
||||
enum_id: ast::def_id,
|
||||
variant_id: ast::def_id)
|
||||
-> VariantInfo {
|
||||
-> @VariantInfo {
|
||||
let variants = enum_variants(cx, enum_id);
|
||||
let mut i = 0;
|
||||
while i < variants.len() {
|
||||
|
@ -81,7 +81,7 @@ use middle::const_eval;
|
||||
use middle::pat_util::pat_id_map;
|
||||
use middle::pat_util;
|
||||
use middle::lint::unreachable_code;
|
||||
use middle::ty::{FnSig, VariantInfo_};
|
||||
use middle::ty::{FnSig, VariantInfo};
|
||||
use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty};
|
||||
use middle::ty::{substs, param_ty, ExprTyProvider};
|
||||
use middle::ty;
|
||||
@ -3133,87 +3133,66 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt,
|
||||
vs: &[ast::variant],
|
||||
id: ast::node_id) {
|
||||
fn do_check(ccx: @mut CrateCtxt,
|
||||
_sp: span,
|
||||
vs: &[ast::variant],
|
||||
id: ast::node_id,
|
||||
disr_vals: &mut ~[int],
|
||||
disr_val: &mut int,
|
||||
variants: &mut ~[ty::VariantInfo]) {
|
||||
id: ast::node_id)
|
||||
-> ~[@ty::VariantInfo] {
|
||||
|
||||
let rty = ty::node_id_to_type(ccx.tcx, id);
|
||||
let mut variants : ~[@ty::VariantInfo] = ~[];
|
||||
let mut disr_vals: ~[int] = ~[];
|
||||
let mut prev_disr_val : Option<int> = None;
|
||||
|
||||
for vs.iter().advance |v| {
|
||||
for v.node.disr_expr.iter().advance |e_ref| {
|
||||
let e = *e_ref;
|
||||
debug!("disr expr, checking %s",
|
||||
pprust::expr_to_str(e, ccx.tcx.sess.intr()));
|
||||
let declty = ty::mk_int();
|
||||
let fcx = blank_fn_ctxt(ccx, rty, e.id);
|
||||
check_const_with_ty(fcx, e.span, e, declty);
|
||||
// check_expr (from check_const pass) doesn't guarantee
|
||||
// that the expression is in an form that eval_const_expr can
|
||||
// handle, so we may still get an internal compiler error
|
||||
|
||||
match const_eval::eval_const_expr_partial(&ccx.tcx, e) {
|
||||
Ok(const_eval::const_int(val)) => {
|
||||
*disr_val = val as int;
|
||||
}
|
||||
Ok(_) => {
|
||||
ccx.tcx.sess.span_err(e.span, "expected signed integer \
|
||||
constant");
|
||||
}
|
||||
Err(ref err) => {
|
||||
ccx.tcx.sess.span_err(e.span,
|
||||
fmt!("expected constant: %s", (*err)));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if disr_vals.contains(&*disr_val) {
|
||||
ccx.tcx.sess.span_err(v.span,
|
||||
"discriminator value already exists");
|
||||
}
|
||||
disr_vals.push(*disr_val);
|
||||
let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
|
||||
|
||||
let this_disr_val = *disr_val;
|
||||
*disr_val += 1;
|
||||
|
||||
let (arg_tys, arg_names) = match v.node.kind {
|
||||
ast::tuple_variant_kind(ref args) if args.len() > 0u => {
|
||||
(ty::ty_fn_args(ctor_ty).map(|a| *a), None)
|
||||
}
|
||||
ast::tuple_variant_kind(_) => {
|
||||
(~[], None)
|
||||
}
|
||||
ast::struct_variant_kind(struct_def) => {
|
||||
let tys = ty::ty_fn_args(ctor_ty).map(|a| *a);
|
||||
let names = do struct_def.fields.map |field| { match field.node.kind {
|
||||
ast::named_field(ident, _visibility) => ident,
|
||||
ast::unnamed_field => ccx.tcx.sess.bug(
|
||||
"enum_variants: all fields in struct must have a name")
|
||||
}};
|
||||
|
||||
(tys, Some(names))
|
||||
}
|
||||
// If the discriminant value is specified explicitly in the enum check whether the
|
||||
// initialization expression is valid, otherwise use the last value plus one.
|
||||
let mut current_disr_val = match prev_disr_val {
|
||||
Some(prev_disr_val) => prev_disr_val + 1,
|
||||
None => ty::INITIAL_DISCRIMINANT_VALUE
|
||||
};
|
||||
|
||||
variants.push(@VariantInfo_{
|
||||
args: arg_tys,
|
||||
arg_names: arg_names,
|
||||
ctor_ty: ctor_ty,
|
||||
name: v.node.name,
|
||||
id: local_def(v.node.id),
|
||||
disr_val: this_disr_val,
|
||||
vis: v.node.vis
|
||||
});
|
||||
match v.node.disr_expr {
|
||||
Some(e) => {
|
||||
debug!("disr expr, checking %s", pprust::expr_to_str(e, ccx.tcx.sess.intr()));
|
||||
|
||||
let declty = ty::mk_int();
|
||||
let fcx = blank_fn_ctxt(ccx, rty, e.id);
|
||||
check_const_with_ty(fcx, e.span, e, declty);
|
||||
// check_expr (from check_const pass) doesn't guarantee
|
||||
// that the expression is in an form that eval_const_expr can
|
||||
// handle, so we may still get an internal compiler error
|
||||
|
||||
match const_eval::eval_const_expr_partial(&ccx.tcx, e) {
|
||||
Ok(const_eval::const_int(val)) => { current_disr_val = val as int; }
|
||||
Ok(_) => {
|
||||
ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
|
||||
}
|
||||
Err(ref err) => {
|
||||
ccx.tcx.sess.span_err(e.span, fmt!("expected constant: %s", (*err)));
|
||||
}
|
||||
}
|
||||
},
|
||||
None => ()
|
||||
};
|
||||
|
||||
// Check for duplicate discriminator values
|
||||
if disr_vals.contains(¤t_disr_val) {
|
||||
ccx.tcx.sess.span_err(v.span, "discriminator value already exists");
|
||||
}
|
||||
disr_vals.push(current_disr_val);
|
||||
|
||||
let variant_info = @VariantInfo::from_ast_variant(ccx.tcx, v, current_disr_val);
|
||||
prev_disr_val = Some(current_disr_val);
|
||||
|
||||
variants.push(variant_info);
|
||||
}
|
||||
|
||||
return variants;
|
||||
}
|
||||
|
||||
let rty = ty::node_id_to_type(ccx.tcx, id);
|
||||
let mut disr_vals: ~[int] = ~[];
|
||||
let mut disr_val = 0;
|
||||
let mut variants = ~[];
|
||||
|
||||
do_check(ccx, sp, vs, id, &mut disr_vals, &mut disr_val, &mut variants);
|
||||
let variants = do_check(ccx, vs, id);
|
||||
|
||||
// cache so that ty::enum_variants won't repeat this work
|
||||
ccx.tcx.enum_var_cache.insert(local_def(id), @variants);
|
||||
|
Loading…
x
Reference in New Issue
Block a user