diff options
| author | Michael Woerister <michaelwoerister@gmail> | 2013-07-10 17:28:28 +0200 |
|---|---|---|
| committer | Michael Woerister <michaelwoerister@gmail> | 2013-07-19 07:57:38 +0200 |
| commit | 12d87d39c1baebcce28ebff095bc811cd3d7402f (patch) | |
| tree | b26500e4a0040af990d324d362601e3217cad9fd | |
| parent | 77a00cca0307ad4d7de084b45168387e8d82d92e (diff) | |
| download | rust-12d87d39c1baebcce28ebff095bc811cd3d7402f.tar.gz rust-12d87d39c1baebcce28ebff095bc811cd3d7402f.zip | |
Cleanup of ty::VariantInfo and related functions.
| -rw-r--r-- | src/librustc/metadata/csearch.rs | 2 | ||||
| -rw-r--r-- | src/librustc/metadata/decoder.rs | 6 | ||||
| -rw-r--r-- | src/librustc/middle/trans/base.rs | 4 | ||||
| -rw-r--r-- | src/librustc/middle/ty.rs | 144 | ||||
| -rw-r--r-- | src/librustc/middle/typeck/check/mod.rs | 119 |
5 files changed, 131 insertions, 144 deletions
diff --git a/src/librustc/metadata/csearch.rs b/src/librustc/metadata/csearch.rs index f336b0f4e4c..2934751eeaf 100644 --- a/src/librustc/metadata/csearch.rs +++ b/src/librustc/metadata/csearch.rs @@ -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) diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index e748ae89a9d..cf75bf45eaf 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -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, diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index 588b0b5c75f..a68a8437e1b 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -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; diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 9438d60a480..59d33fc086d 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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); - - 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 - } + let mut discriminant = match last_discriminant { + Some(val) => val + 1, + None => INITIAL_DISCRIMINANT_VALUE + }; + + 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) => { - - let fields : &[@struct_field] = struct_def.fields; - - 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 - } - } - } + None => {} + }; + + let variant_info = @VariantInfo::from_ast_variant(cx, variant, discriminant); + last_discriminant = Some(discriminant); + variant_info + }).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() { diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 0e1f8e617ff..319d94bae70 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -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); - 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))); + let mut variants : ~[@ty::VariantInfo] = ~[]; + let mut disr_vals: ~[int] = ~[]; + let mut prev_disr_val : Option<int> = None; - } - } - } - 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); + for vs.iter().advance |v| { - let this_disr_val = *disr_val; - *disr_val += 1; + // 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 + }; - 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)) - } + 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 => () }; - 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 - }); + // 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); |
