@@ -50,6 +50,8 @@ use syntax::opt_vec;
50
50
use syntax:: abi:: AbiSet ;
51
51
use syntax;
52
52
53
+ pub static INITIAL_DISCRIMINANT_VALUE : int = 0 ;
54
+
53
55
// Data types
54
56
55
57
#[ deriving( Eq , IterBytes ) ]
@@ -282,7 +284,7 @@ struct ctxt_ {
282
284
needs_unwind_cleanup_cache : @mut HashMap < t , bool > ,
283
285
tc_cache : @mut HashMap < uint , TypeContents > ,
284
286
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 ] > ,
286
288
ty_param_defs : @mut HashMap < ast:: node_id , TypeParameterDef > ,
287
289
adjustments : @mut HashMap < ast:: node_id , @AutoAdjustment > ,
288
290
normalized_cache : @mut HashMap < t , t > ,
@@ -3702,19 +3704,70 @@ pub struct VariantInfo_ {
3702
3704
vis : visibility
3703
3705
}
3704
3706
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
+ }
3706
3759
3707
3760
pub fn substd_enum_variants ( cx : ctxt ,
3708
3761
id : ast:: def_id ,
3709
3762
substs : & substs )
3710
- -> ~[ VariantInfo ] {
3763
+ -> ~[ @ VariantInfo ] {
3711
3764
do enum_variants ( cx, id) . iter ( ) . transform |variant_info| {
3712
3765
let substd_args = variant_info. args . iter ( )
3713
3766
. transform ( |aty| subst ( cx, substs, * aty) ) . collect ( ) ;
3714
3767
3715
3768
let substd_ctor_ty = subst ( cx, substs, variant_info. ctor_ty ) ;
3716
3769
3717
- @VariantInfo_ {
3770
+ @VariantInfo {
3718
3771
args : substd_args,
3719
3772
ctor_ty : substd_ctor_ty,
3720
3773
..( * * variant_info) . clone ( )
@@ -3832,7 +3885,7 @@ pub fn type_is_empty(cx: ctxt, t: t) -> bool {
3832
3885
}
3833
3886
}
3834
3887
3835
- pub fn enum_variants ( cx : ctxt , id : ast:: def_id ) -> @~[ VariantInfo ] {
3888
+ pub fn enum_variants ( cx : ctxt , id : ast:: def_id ) -> @~[ @ VariantInfo ] {
3836
3889
match cx. enum_var_cache . find ( & id) {
3837
3890
Some ( & variants) => return variants,
3838
3891
_ => { /* fallthrough */ }
@@ -3851,71 +3904,26 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
3851
3904
node : ast:: item_enum( ref enum_definition, _) ,
3852
3905
_
3853
3906
} , _) => {
3854
- let mut disr_val = - 1 ;
3907
+ let mut last_discriminant : Option < int > = None ;
3855
3908
@enum_definition. variants . iter ( ) . transform ( |variant| {
3856
3909
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 ( ) > 0 u {
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
+ _ => { }
3886
3919
} ,
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
+
3919
3927
} ) . collect ( )
3920
3928
}
3921
3929
_ => 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] {
3930
3938
pub fn enum_variant_with_id ( cx : ctxt ,
3931
3939
enum_id : ast:: def_id ,
3932
3940
variant_id : ast:: def_id )
3933
- -> VariantInfo {
3941
+ -> @ VariantInfo {
3934
3942
let variants = enum_variants ( cx, enum_id) ;
3935
3943
let mut i = 0 ;
3936
3944
while i < variants. len ( ) {
0 commit comments