Skip to content

Commit 12d87d3

Browse files
Cleanup of ty::VariantInfo and related functions.
1 parent 77a00cc commit 12d87d3

File tree

5 files changed

+131
-144
lines changed

5 files changed

+131
-144
lines changed

src/librustc/metadata/csearch.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ pub fn maybe_get_item_ast(tcx: ty::ctxt, def: ast::def_id,
9090
}
9191

9292
pub fn get_enum_variants(tcx: ty::ctxt, def: ast::def_id)
93-
-> ~[ty::VariantInfo] {
93+
-> ~[@ty::VariantInfo] {
9494
let cstore = tcx.cstore;
9595
let cdata = cstore::get_crate_data(cstore, def.crate);
9696
return decoder::get_enum_variants(cstore.intr, cdata, def.node, tcx)

src/librustc/metadata/decoder.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -733,11 +733,11 @@ pub fn maybe_get_item_ast(cdata: cmd, tcx: ty::ctxt,
733733
}
734734

735735
pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
736-
tcx: ty::ctxt) -> ~[ty::VariantInfo] {
736+
tcx: ty::ctxt) -> ~[@ty::VariantInfo] {
737737
let data = cdata.data;
738738
let items = reader::get_doc(reader::Doc(data), tag_items);
739739
let item = find_item(id, items);
740-
let mut infos: ~[ty::VariantInfo] = ~[];
740+
let mut infos: ~[@ty::VariantInfo] = ~[];
741741
let variant_ids = enum_variant_ids(item, cdata);
742742
let mut disr_val = 0;
743743
for variant_ids.iter().advance |did| {
@@ -753,7 +753,7 @@ pub fn get_enum_variants(intr: @ident_interner, cdata: cmd, id: ast::node_id,
753753
Some(val) => { disr_val = val; }
754754
_ => { /* empty */ }
755755
}
756-
infos.push(@ty::VariantInfo_{
756+
infos.push(@ty::VariantInfo{
757757
args: arg_tys,
758758
arg_names: None,
759759
ctor_ty: ctor_ty,

src/librustc/middle/trans/base.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -671,7 +671,7 @@ pub fn iter_structural_ty(cx: block, av: ValueRef, t: ty::t,
671671
let _icx = push_ctxt("iter_structural_ty");
672672

673673
fn iter_variant(cx: block, repr: &adt::Repr, av: ValueRef,
674-
variant: ty::VariantInfo,
674+
variant: @ty::VariantInfo,
675675
tps: &[ty::t], f: val_and_ty_fn) -> block {
676676
let _icx = push_ctxt("iter_variant");
677677
let tcx = cx.tcx();
@@ -2110,7 +2110,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
21102110
}
21112111

21122112
pub fn trans_enum_def(ccx: @mut CrateContext, enum_definition: &ast::enum_def,
2113-
id: ast::node_id, vi: @~[ty::VariantInfo],
2113+
id: ast::node_id, vi: @~[@ty::VariantInfo],
21142114
i: &mut uint) {
21152115
for enum_definition.variants.iter().advance |variant| {
21162116
let disr_val = vi[*i].disr_val;

src/librustc/middle/ty.rs

Lines changed: 76 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ use syntax::opt_vec;
5050
use syntax::abi::AbiSet;
5151
use syntax;
5252

53+
pub static INITIAL_DISCRIMINANT_VALUE: int = 0;
54+
5355
// Data types
5456

5557
#[deriving(Eq, IterBytes)]
@@ -282,7 +284,7 @@ struct ctxt_ {
282284
needs_unwind_cleanup_cache: @mut HashMap<t, bool>,
283285
tc_cache: @mut HashMap<uint, TypeContents>,
284286
ast_ty_to_ty_cache: @mut HashMap<node_id, ast_ty_to_ty_cache_entry>,
285-
enum_var_cache: @mut HashMap<def_id, @~[VariantInfo]>,
287+
enum_var_cache: @mut HashMap<def_id, @~[@VariantInfo]>,
286288
ty_param_defs: @mut HashMap<ast::node_id, TypeParameterDef>,
287289
adjustments: @mut HashMap<ast::node_id, @AutoAdjustment>,
288290
normalized_cache: @mut HashMap<t, t>,
@@ -3702,19 +3704,70 @@ pub struct VariantInfo_ {
37023704
vis: visibility
37033705
}
37043706

3705-
pub type VariantInfo = @VariantInfo_;
3707+
impl VariantInfo {
3708+
3709+
/// Creates a new VariantInfo from the corresponding ast representation.
3710+
///
3711+
/// Does not do any caching of the value in the type context.
3712+
pub fn from_ast_variant(cx: ctxt,
3713+
ast_variant: &ast::variant,
3714+
discriminant: int) -> VariantInfo {
3715+
3716+
let ctor_ty = node_id_to_type(cx, ast_variant.node.id);
3717+
3718+
match ast_variant.node.kind {
3719+
ast::tuple_variant_kind(ref args) => {
3720+
let arg_tys = if args.len() > 0 { ty_fn_args(ctor_ty).map(|a| *a) } else { ~[] };
3721+
3722+
return VariantInfo {
3723+
args: arg_tys,
3724+
arg_names: None,
3725+
ctor_ty: ctor_ty,
3726+
name: ast_variant.node.name,
3727+
id: ast_util::local_def(ast_variant.node.id),
3728+
disr_val: discriminant,
3729+
vis: ast_variant.node.vis
3730+
};
3731+
},
3732+
ast::struct_variant_kind(ref struct_def) => {
3733+
3734+
let fields : &[@struct_field] = struct_def.fields;
3735+
3736+
assert!(fields.len() > 0);
3737+
3738+
let arg_tys = ty_fn_args(ctor_ty).map(|a| *a);
3739+
let arg_names = do fields.map |field| {
3740+
match field.node.kind {
3741+
named_field(ident, _visibility) => ident,
3742+
unnamed_field => cx.sess.bug(
3743+
"enum_variants: all fields in struct must have a name")
3744+
}};
3745+
3746+
return VariantInfo {
3747+
args: arg_tys,
3748+
arg_names: Some(arg_names),
3749+
ctor_ty: ctor_ty,
3750+
name: ast_variant.node.name,
3751+
id: ast_util::local_def(ast_variant.node.id),
3752+
disr_val: discriminant,
3753+
vis: ast_variant.node.vis
3754+
};
3755+
}
3756+
}
3757+
}
3758+
}
37063759

37073760
pub fn substd_enum_variants(cx: ctxt,
37083761
id: ast::def_id,
37093762
substs: &substs)
3710-
-> ~[VariantInfo] {
3763+
-> ~[@VariantInfo] {
37113764
do enum_variants(cx, id).iter().transform |variant_info| {
37123765
let substd_args = variant_info.args.iter()
37133766
.transform(|aty| subst(cx, substs, *aty)).collect();
37143767

37153768
let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
37163769

3717-
@VariantInfo_ {
3770+
@VariantInfo {
37183771
args: substd_args,
37193772
ctor_ty: substd_ctor_ty,
37203773
..(**variant_info).clone()
@@ -3832,7 +3885,7 @@ pub fn type_is_empty(cx: ctxt, t: t) -> bool {
38323885
}
38333886
}
38343887

3835-
pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
3888+
pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[@VariantInfo] {
38363889
match cx.enum_var_cache.find(&id) {
38373890
Some(&variants) => return variants,
38383891
_ => { /* fallthrough */ }
@@ -3851,71 +3904,26 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
38513904
node: ast::item_enum(ref enum_definition, _),
38523905
_
38533906
}, _) => {
3854-
let mut disr_val = -1;
3907+
let mut last_discriminant : Option<int> = None;
38553908
@enum_definition.variants.iter().transform(|variant| {
38563909

3857-
let ctor_ty = node_id_to_type(cx, variant.node.id);
3858-
3859-
match variant.node.kind {
3860-
ast::tuple_variant_kind(ref args) => {
3861-
let arg_tys = if args.len() > 0u {
3862-
ty_fn_args(ctor_ty).map(|a| *a) }
3863-
else {
3864-
~[]
3865-
};
3866-
3867-
match variant.node.disr_expr {
3868-
Some (ex) => {
3869-
disr_val = match const_eval::eval_const_expr(cx,
3870-
ex) {
3871-
const_eval::const_int(val) => val as int,
3872-
_ => cx.sess.bug("enum_variants: bad disr expr")
3873-
}
3874-
}
3875-
_ => disr_val += 1
3876-
}
3877-
@VariantInfo_{
3878-
args: arg_tys,
3879-
arg_names: None,
3880-
ctor_ty: ctor_ty,
3881-
name: variant.node.name,
3882-
id: ast_util::local_def(variant.node.id),
3883-
disr_val: disr_val,
3884-
vis: variant.node.vis
3885-
}
3910+
let mut discriminant = match last_discriminant {
3911+
Some(val) => val + 1,
3912+
None => INITIAL_DISCRIMINANT_VALUE
3913+
};
3914+
3915+
match variant.node.disr_expr {
3916+
Some(e) => match const_eval::eval_const_expr_partial(cx, e) {
3917+
Ok(const_eval::const_int(val)) => { discriminant = val as int; }
3918+
_ => {}
38863919
},
3887-
ast::struct_variant_kind(struct_def) => {
3888-
3889-
let fields : &[@struct_field] = struct_def.fields;
3890-
3891-
let (arg_tys, arg_names) =
3892-
if fields.len() > 0 {
3893-
let arg_tys = ty_fn_args(ctor_ty).map(|a| *a);
3894-
let arg_names = do fields.map |field| { match field.node.kind {
3895-
named_field(ident, _visibility) => ident,
3896-
unnamed_field => cx.sess.bug(
3897-
"enum_variants: all fields in struct must have a name")
3898-
}};
3899-
3900-
(arg_tys, Some(arg_names))
3901-
} else {
3902-
(~[], None)
3903-
};
3904-
3905-
assert!(variant.node.disr_expr.is_none());
3906-
disr_val += 1;
3907-
3908-
@VariantInfo_{
3909-
args: arg_tys,
3910-
arg_names: arg_names,
3911-
ctor_ty: ctor_ty,
3912-
name: variant.node.name,
3913-
id: ast_util::local_def(variant.node.id),
3914-
disr_val: disr_val,
3915-
vis: variant.node.vis
3916-
}
3917-
}
3918-
}
3920+
None => {}
3921+
};
3922+
3923+
let variant_info = @VariantInfo::from_ast_variant(cx, variant, discriminant);
3924+
last_discriminant = Some(discriminant);
3925+
variant_info
3926+
39193927
}).collect()
39203928
}
39213929
_ => 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] {
39303938
pub fn enum_variant_with_id(cx: ctxt,
39313939
enum_id: ast::def_id,
39323940
variant_id: ast::def_id)
3933-
-> VariantInfo {
3941+
-> @VariantInfo {
39343942
let variants = enum_variants(cx, enum_id);
39353943
let mut i = 0;
39363944
while i < variants.len() {

src/librustc/middle/typeck/check/mod.rs

Lines changed: 49 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ use middle::const_eval;
8181
use middle::pat_util::pat_id_map;
8282
use middle::pat_util;
8383
use middle::lint::unreachable_code;
84-
use middle::ty::{FnSig, VariantInfo_};
84+
use middle::ty::{FnSig, VariantInfo};
8585
use middle::ty::{ty_param_bounds_and_ty, ty_param_substs_and_ty};
8686
use middle::ty::{substs, param_ty, ExprTyProvider};
8787
use middle::ty;
@@ -3133,87 +3133,66 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt,
31333133
vs: &[ast::variant],
31343134
id: ast::node_id) {
31353135
fn do_check(ccx: @mut CrateCtxt,
3136-
_sp: span,
31373136
vs: &[ast::variant],
3138-
id: ast::node_id,
3139-
disr_vals: &mut ~[int],
3140-
disr_val: &mut int,
3141-
variants: &mut ~[ty::VariantInfo]) {
3137+
id: ast::node_id)
3138+
-> ~[@ty::VariantInfo] {
3139+
31423140
let rty = ty::node_id_to_type(ccx.tcx, id);
3143-
for vs.iter().advance |v| {
3144-
for v.node.disr_expr.iter().advance |e_ref| {
3145-
let e = *e_ref;
3146-
debug!("disr expr, checking %s",
3147-
pprust::expr_to_str(e, ccx.tcx.sess.intr()));
3148-
let declty = ty::mk_int();
3149-
let fcx = blank_fn_ctxt(ccx, rty, e.id);
3150-
check_const_with_ty(fcx, e.span, e, declty);
3151-
// check_expr (from check_const pass) doesn't guarantee
3152-
// that the expression is in an form that eval_const_expr can
3153-
// handle, so we may still get an internal compiler error
3154-
3155-
match const_eval::eval_const_expr_partial(&ccx.tcx, e) {
3156-
Ok(const_eval::const_int(val)) => {
3157-
*disr_val = val as int;
3158-
}
3159-
Ok(_) => {
3160-
ccx.tcx.sess.span_err(e.span, "expected signed integer \
3161-
constant");
3162-
}
3163-
Err(ref err) => {
3164-
ccx.tcx.sess.span_err(e.span,
3165-
fmt!("expected constant: %s", (*err)));
3141+
let mut variants : ~[@ty::VariantInfo] = ~[];
3142+
let mut disr_vals: ~[int] = ~[];
3143+
let mut prev_disr_val : Option<int> = None;
31663144

3167-
}
3168-
}
3169-
}
3170-
if disr_vals.contains(&*disr_val) {
3171-
ccx.tcx.sess.span_err(v.span,
3172-
"discriminator value already exists");
3173-
}
3174-
disr_vals.push(*disr_val);
3175-
let ctor_ty = ty::node_id_to_type(ccx.tcx, v.node.id);
3145+
for vs.iter().advance |v| {
31763146

3177-
let this_disr_val = *disr_val;
3178-
*disr_val += 1;
3147+
// If the discriminant value is specified explicitly in the enum check whether the
3148+
// initialization expression is valid, otherwise use the last value plus one.
3149+
let mut current_disr_val = match prev_disr_val {
3150+
Some(prev_disr_val) => prev_disr_val + 1,
3151+
None => ty::INITIAL_DISCRIMINANT_VALUE
3152+
};
31793153

3180-
let (arg_tys, arg_names) = match v.node.kind {
3181-
ast::tuple_variant_kind(ref args) if args.len() > 0u => {
3182-
(ty::ty_fn_args(ctor_ty).map(|a| *a), None)
3183-
}
3184-
ast::tuple_variant_kind(_) => {
3185-
(~[], None)
3186-
}
3187-
ast::struct_variant_kind(struct_def) => {
3188-
let tys = ty::ty_fn_args(ctor_ty).map(|a| *a);
3189-
let names = do struct_def.fields.map |field| { match field.node.kind {
3190-
ast::named_field(ident, _visibility) => ident,
3191-
ast::unnamed_field => ccx.tcx.sess.bug(
3192-
"enum_variants: all fields in struct must have a name")
3193-
}};
3194-
3195-
(tys, Some(names))
3196-
}
3154+
match v.node.disr_expr {
3155+
Some(e) => {
3156+
debug!("disr expr, checking %s", pprust::expr_to_str(e, ccx.tcx.sess.intr()));
3157+
3158+
let declty = ty::mk_int();
3159+
let fcx = blank_fn_ctxt(ccx, rty, e.id);
3160+
check_const_with_ty(fcx, e.span, e, declty);
3161+
// check_expr (from check_const pass) doesn't guarantee
3162+
// that the expression is in an form that eval_const_expr can
3163+
// handle, so we may still get an internal compiler error
3164+
3165+
match const_eval::eval_const_expr_partial(&ccx.tcx, e) {
3166+
Ok(const_eval::const_int(val)) => { current_disr_val = val as int; }
3167+
Ok(_) => {
3168+
ccx.tcx.sess.span_err(e.span, "expected signed integer constant");
3169+
}
3170+
Err(ref err) => {
3171+
ccx.tcx.sess.span_err(e.span, fmt!("expected constant: %s", (*err)));
3172+
}
3173+
}
3174+
},
3175+
None => ()
31973176
};
31983177

3199-
variants.push(@VariantInfo_{
3200-
args: arg_tys,
3201-
arg_names: arg_names,
3202-
ctor_ty: ctor_ty,
3203-
name: v.node.name,
3204-
id: local_def(v.node.id),
3205-
disr_val: this_disr_val,
3206-
vis: v.node.vis
3207-
});
3178+
// Check for duplicate discriminator values
3179+
if disr_vals.contains(&current_disr_val) {
3180+
ccx.tcx.sess.span_err(v.span, "discriminator value already exists");
3181+
}
3182+
disr_vals.push(current_disr_val);
3183+
3184+
let variant_info = @VariantInfo::from_ast_variant(ccx.tcx, v, current_disr_val);
3185+
prev_disr_val = Some(current_disr_val);
3186+
3187+
variants.push(variant_info);
32083188
}
3189+
3190+
return variants;
32093191
}
32103192

32113193
let rty = ty::node_id_to_type(ccx.tcx, id);
3212-
let mut disr_vals: ~[int] = ~[];
3213-
let mut disr_val = 0;
3214-
let mut variants = ~[];
32153194

3216-
do_check(ccx, sp, vs, id, &mut disr_vals, &mut disr_val, &mut variants);
3195+
let variants = do_check(ccx, vs, id);
32173196

32183197
// cache so that ty::enum_variants won't repeat this work
32193198
ccx.tcx.enum_var_cache.insert(local_def(id), @variants);

0 commit comments

Comments
 (0)