Skip to content

Commit 1c3dc29

Browse files
committed
Allow uint discriminants and store them as such
Infers type of constants used as discriminants and ensures they are integral, instead of forcing them to be a signed integer. Also, stores discriminant values as uint instead of int interally and deals with related fallout. Fixes issue rust-lang#7994
1 parent 4a726f0 commit 1c3dc29

File tree

10 files changed

+59
-55
lines changed

10 files changed

+59
-55
lines changed

src/librustc/metadata/decoder.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ use metadata::tydecode::{parse_ty_data, parse_def_id,
2323
use middle::ty;
2424

2525
use std::hash::HashUtil;
26-
use std::int;
26+
use std::uint;
2727
use std::io::WriterUtil;
2828
use std::io;
2929
use std::option;
@@ -200,9 +200,9 @@ fn each_reexport(d: ebml::Doc, f: &fn(ebml::Doc) -> bool) -> bool {
200200
return true;
201201
}
202202

203-
fn variant_disr_val(d: ebml::Doc) -> Option<int> {
203+
fn variant_disr_val(d: ebml::Doc) -> Option<uint> {
204204
do reader::maybe_get_doc(d, tag_disr_val).chain |val_doc| {
205-
do reader::with_doc_data(val_doc) |data| { int::parse_bytes(data, 10u) }
205+
do reader::with_doc_data(val_doc) |data| { uint::parse_bytes(data, 10u) }
206206
}
207207
}
208208

src/librustc/metadata/encoder.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use middle;
2121

2222
use std::hash::HashUtil;
2323
use std::hashmap::{HashMap, HashSet};
24-
use std::int;
2524
use std::io;
2625
use std::str;
2726
use std::uint;
@@ -290,9 +289,9 @@ fn encode_discriminant(ecx: &EncodeContext,
290289

291290
fn encode_disr_val(_: &EncodeContext,
292291
ebml_w: &mut writer::Encoder,
293-
disr_val: int) {
292+
disr_val: uint) {
294293
ebml_w.start_tag(tag_disr_val);
295-
let s = int::to_str(disr_val);
294+
let s = uint::to_str(disr_val);
296295
ebml_w.writer.write(s.as_bytes());
297296
ebml_w.end_tag();
298297
}

src/librustc/middle/trans/_match.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ pub enum Lit {
193193
// range)
194194
pub enum Opt {
195195
lit(Lit),
196-
var(/* disr val */int, @adt::Repr),
196+
var(/* disr val */ uint, @adt::Repr),
197197
range(@ast::expr, @ast::expr),
198198
vec_len_eq(uint),
199199
vec_len_ge(uint, /* slice */uint)
@@ -874,7 +874,7 @@ pub struct ExtractedBlock {
874874

875875
pub fn extract_variant_args(bcx: @mut Block,
876876
repr: &adt::Repr,
877-
disr_val: int,
877+
disr_val: uint,
878878
val: ValueRef)
879879
-> ExtractedBlock {
880880
let _icx = push_ctxt("match::extract_variant_args");

src/librustc/middle/trans/adt.rs

Lines changed: 33 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ use middle::trans::type_::Type;
6464
/// Representations.
6565
pub enum Repr {
6666
/// C-like enums; basically an int.
67-
CEnum(int, int), // discriminant range
67+
CEnum(uint, uint), // discriminant range
6868
/**
6969
* Single-case variants, and structs/tuples/records.
7070
*
@@ -89,7 +89,7 @@ pub enum Repr {
8989
* is represented such that `None` is a null pointer and `Some` is the
9090
* identity function.
9191
*/
92-
NullablePointer{ nonnull: Struct, nndiscr: int, ptrfield: uint,
92+
NullablePointer{ nonnull: Struct, nndiscr: uint, ptrfield: uint,
9393
nullfields: ~[ty::t] }
9494
}
9595

@@ -140,7 +140,7 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
140140
return Univariant(mk_struct(cx, ftys, packed), dtor)
141141
}
142142
ty::ty_enum(def_id, ref substs) => {
143-
struct Case { discr: int, tys: ~[ty::t] };
143+
struct Case { discr: uint, tys: ~[ty::t] };
144144
impl Case {
145145
fn is_zerolen(&self, cx: &mut CrateContext) -> bool {
146146
mk_struct(cx, self.tys, false).size == 0
@@ -177,7 +177,7 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
177177
// Since there's at least one
178178
// non-empty body, explicit discriminants should have
179179
// been rejected by a checker before this point.
180-
if !cases.iter().enumerate().all(|(i,c)| c.discr == (i as int)) {
180+
if !cases.iter().enumerate().all(|(i,c)| c.discr == i) {
181181
cx.sess.bug(fmt!("non-C-like enum %s with specified \
182182
discriminants",
183183
ty::item_path_str(cx.tcx, def_id)))
@@ -206,7 +206,7 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
206206
}
207207

208208
// The general case.
209-
let discr = ~[ty::mk_int()];
209+
let discr = ~[ty::mk_uint()];
210210
return General(cases.map(|c| mk_struct(cx, discr + c.tys, false)))
211211
}
212212
_ => cx.sess.bug("adt::represent_type called on non-ADT type")
@@ -305,17 +305,16 @@ pub fn trans_get_discr(bcx: @mut Block, r: &Repr, scrutinee: ValueRef)
305305
-> ValueRef {
306306
match *r {
307307
CEnum(min, max) => load_discr(bcx, scrutinee, min, max),
308-
Univariant(*) => C_int(bcx.ccx(), 0),
309-
General(ref cases) => load_discr(bcx, scrutinee, 0,
310-
(cases.len() - 1) as int),
308+
Univariant(*) => C_uint(bcx.ccx(), 0),
309+
General(ref cases) => load_discr(bcx, scrutinee, 0, cases.len() - 1),
311310
NullablePointer{ nonnull: ref nonnull, nndiscr, ptrfield, _ } => {
312311
ZExt(bcx, nullable_bitdiscr(bcx, nonnull, nndiscr, ptrfield, scrutinee),
313312
Type::enum_discrim(bcx.ccx()))
314313
}
315314
}
316315
}
317316

318-
fn nullable_bitdiscr(bcx: @mut Block, nonnull: &Struct, nndiscr: int, ptrfield: uint,
317+
fn nullable_bitdiscr(bcx: @mut Block, nonnull: &Struct, nndiscr: uint, ptrfield: uint,
319318
scrutinee: ValueRef) -> ValueRef {
320319
let cmp = if nndiscr == 0 { IntEQ } else { IntNE };
321320
let llptr = Load(bcx, GEPi(bcx, scrutinee, [0, ptrfield]));
@@ -324,7 +323,7 @@ fn nullable_bitdiscr(bcx: @mut Block, nonnull: &Struct, nndiscr: int, ptrfield:
324323
}
325324

326325
/// Helper for cases where the discriminant is simply loaded.
327-
fn load_discr(bcx: @mut Block, scrutinee: ValueRef, min: int, max: int)
326+
fn load_discr(bcx: @mut Block, scrutinee: ValueRef, min: uint, max: uint)
328327
-> ValueRef {
329328
let ptr = GEPi(bcx, scrutinee, [0, 0]);
330329
if max + 1 == min {
@@ -348,16 +347,16 @@ fn load_discr(bcx: @mut Block, scrutinee: ValueRef, min: int, max: int)
348347
*
349348
* This should ideally be less tightly tied to `_match`.
350349
*/
351-
pub fn trans_case(bcx: @mut Block, r: &Repr, discr: int) -> _match::opt_result {
350+
pub fn trans_case(bcx: @mut Block, r: &Repr, discr: uint) -> _match::opt_result {
352351
match *r {
353352
CEnum(*) => {
354-
_match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
353+
_match::single_result(rslt(bcx, C_uint(bcx.ccx(), discr)))
355354
}
356355
Univariant(*) => {
357356
bcx.ccx().sess.bug("no cases for univariants or structs")
358357
}
359358
General(*) => {
360-
_match::single_result(rslt(bcx, C_int(bcx.ccx(), discr)))
359+
_match::single_result(rslt(bcx, C_uint(bcx.ccx(), discr)))
361360
}
362361
NullablePointer{ _ } => {
363362
assert!(discr == 0 || discr == 1);
@@ -371,11 +370,11 @@ pub fn trans_case(bcx: @mut Block, r: &Repr, discr: int) -> _match::opt_result {
371370
* representation. The fields, if any, should then be initialized via
372371
* `trans_field_ptr`.
373372
*/
374-
pub fn trans_start_init(bcx: @mut Block, r: &Repr, val: ValueRef, discr: int) {
373+
pub fn trans_start_init(bcx: @mut Block, r: &Repr, val: ValueRef, discr: uint) {
375374
match *r {
376375
CEnum(min, max) => {
377376
assert!(min <= discr && discr <= max);
378-
Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
377+
Store(bcx, C_uint(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
379378
}
380379
Univariant(ref st, true) => {
381380
assert_eq!(discr, 0);
@@ -386,7 +385,7 @@ pub fn trans_start_init(bcx: @mut Block, r: &Repr, val: ValueRef, discr: int) {
386385
assert_eq!(discr, 0);
387386
}
388387
General(*) => {
389-
Store(bcx, C_int(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
388+
Store(bcx, C_uint(bcx.ccx(), discr), GEPi(bcx, val, [0, 0]))
390389
}
391390
NullablePointer{ nonnull: ref nonnull, nndiscr, ptrfield, _ } => {
392391
if discr != nndiscr {
@@ -402,22 +401,22 @@ pub fn trans_start_init(bcx: @mut Block, r: &Repr, val: ValueRef, discr: int) {
402401
* The number of fields in a given case; for use when obtaining this
403402
* information from the type or definition is less convenient.
404403
*/
405-
pub fn num_args(r: &Repr, discr: int) -> uint {
404+
pub fn num_args(r: &Repr, discr: uint) -> uint {
406405
match *r {
407406
CEnum(*) => 0,
408407
Univariant(ref st, dtor) => {
409408
assert_eq!(discr, 0);
410409
st.fields.len() - (if dtor { 1 } else { 0 })
411410
}
412-
General(ref cases) => cases[discr as uint].fields.len() - 1,
411+
General(ref cases) => cases[discr].fields.len() - 1,
413412
NullablePointer{ nonnull: ref nonnull, nndiscr, nullfields: ref nullfields, _ } => {
414413
if discr == nndiscr { nonnull.fields.len() } else { nullfields.len() }
415414
}
416415
}
417416
}
418417

419418
/// Access a field, at a point when the value's case is known.
420-
pub fn trans_field_ptr(bcx: @mut Block, r: &Repr, val: ValueRef, discr: int,
419+
pub fn trans_field_ptr(bcx: @mut Block, r: &Repr, val: ValueRef, discr: uint,
421420
ix: uint) -> ValueRef {
422421
// Note: if this ever needs to generate conditionals (e.g., if we
423422
// decide to do some kind of cdr-coding-like non-unique repr
@@ -431,7 +430,7 @@ pub fn trans_field_ptr(bcx: @mut Block, r: &Repr, val: ValueRef, discr: int,
431430
struct_field_ptr(bcx, st, val, ix, false)
432431
}
433432
General(ref cases) => {
434-
struct_field_ptr(bcx, &cases[discr as uint], val, ix + 1, true)
433+
struct_field_ptr(bcx, &cases[discr], val, ix + 1, true)
435434
}
436435
NullablePointer{ nonnull: ref nonnull, nullfields: ref nullfields, nndiscr, _ } => {
437436
if (discr == nndiscr) {
@@ -495,22 +494,22 @@ pub fn trans_drop_flag_ptr(bcx: @mut Block, r: &Repr, val: ValueRef) -> ValueRef
495494
* this could be changed in the future to avoid allocating unnecessary
496495
* space after values of shorter-than-maximum cases.
497496
*/
498-
pub fn trans_const(ccx: &mut CrateContext, r: &Repr, discr: int,
497+
pub fn trans_const(ccx: &mut CrateContext, r: &Repr, discr: uint,
499498
vals: &[ValueRef]) -> ValueRef {
500499
match *r {
501500
CEnum(min, max) => {
502501
assert_eq!(vals.len(), 0);
503502
assert!(min <= discr && discr <= max);
504-
C_int(ccx, discr)
503+
C_uint(ccx, discr)
505504
}
506505
Univariant(ref st, _dro) => {
507506
assert_eq!(discr, 0);
508507
C_struct(build_const_struct(ccx, st, vals))
509508
}
510509
General(ref cases) => {
511-
let case = &cases[discr as uint];
510+
let case = &cases[discr];
512511
let max_sz = cases.iter().transform(|x| x.size).max().unwrap();
513-
let discr_ty = C_int(ccx, discr);
512+
let discr_ty = C_uint(ccx, discr);
514513
let contents = build_const_struct(ccx, case,
515514
~[discr_ty] + vals);
516515
C_struct(contents + &[padding(max_sz - case.size)])
@@ -582,13 +581,18 @@ fn roundup(x: u64, a: u64) -> u64 { ((x + (a - 1)) / a) * a }
582581

583582
/// Get the discriminant of a constant value. (Not currently used.)
584583
pub fn const_get_discrim(ccx: &mut CrateContext, r: &Repr, val: ValueRef)
585-
-> int {
584+
-> uint {
586585
match *r {
587-
CEnum(*) => const_to_int(val) as int,
586+
CEnum(*) => const_to_uint(val) as uint,
588587
Univariant(*) => 0,
589-
General(*) => const_to_int(const_get_elt(ccx, val, [0])) as int,
588+
General(*) => const_to_uint(const_get_elt(ccx, val, [0])) as uint,
590589
NullablePointer{ nndiscr, ptrfield, _ } => {
591-
if is_null(const_struct_field(ccx, val, ptrfield)) { 1 - nndiscr } else { nndiscr }
590+
if is_null(const_struct_field(ccx, val, ptrfield)) {
591+
/* subtraction as uint is ok because nndiscr is either 0 or 1 */
592+
(1 - nndiscr) as uint
593+
} else {
594+
nndiscr
595+
}
592596
}
593597
}
594598
}
@@ -601,7 +605,7 @@ pub fn const_get_discrim(ccx: &mut CrateContext, r: &Repr, val: ValueRef)
601605
* raw LLVM-level structs and arrays.)
602606
*/
603607
pub fn const_get_field(ccx: &mut CrateContext, r: &Repr, val: ValueRef,
604-
_discr: int, ix: uint) -> ValueRef {
608+
_discr: uint, ix: uint) -> ValueRef {
605609
match *r {
606610
CEnum(*) => ccx.sess.bug("element access in C-like enum const"),
607611
Univariant(*) => const_struct_field(ccx, val, ix),

src/librustc/middle/trans/base.rs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,6 @@ use middle::trans::type_::Type;
6767

6868
use std::hash;
6969
use std::hashmap::{HashMap, HashSet};
70-
use std::int;
7170
use std::io;
7271
use std::libc::c_uint;
7372
use std::uint;
@@ -732,7 +731,7 @@ pub fn iter_structural_ty(cx: @mut Block, av: ValueRef, t: ty::t,
732731
for (*variants).iter().advance |variant| {
733732
let variant_cx =
734733
sub_block(cx, ~"enum-iter-variant-" +
735-
int::to_str(variant.disr_val));
734+
uint::to_str(variant.disr_val));
736735
let variant_cx =
737736
iter_variant(variant_cx, repr, av, *variant,
738737
substs.tps, |x,y,z| f(x,y,z));
@@ -1979,7 +1978,7 @@ pub fn trans_enum_variant(ccx: @mut CrateContext,
19791978
_enum_id: ast::node_id,
19801979
variant: &ast::variant,
19811980
args: &[ast::variant_arg],
1982-
disr: int,
1981+
disr: uint,
19831982
param_substs: Option<@param_substs>,
19841983
llfndecl: ValueRef) {
19851984
let _icx = push_ctxt("trans_enum_variant");
@@ -2028,7 +2027,7 @@ pub fn trans_enum_variant_or_tuple_like_struct<A:IdAndTy>(
20282027
ccx: @mut CrateContext,
20292028
ctor_id: ast::node_id,
20302029
args: &[A],
2031-
disr: int,
2030+
disr: uint,
20322031
param_substs: Option<@param_substs>,
20332032
llfndecl: ValueRef)
20342033
{
@@ -2628,7 +2627,7 @@ pub fn trans_constant(ccx: &mut CrateContext, it: @ast::item) {
26282627
}
26292628
};
26302629
unsafe {
2631-
llvm::LLVMSetInitializer(discrim_gvar, C_int(ccx, disr_val));
2630+
llvm::LLVMSetInitializer(discrim_gvar, C_uint(ccx, disr_val));
26322631
llvm::LLVMSetGlobalConstant(discrim_gvar, True);
26332632
}
26342633
ccx.discrims.insert(

src/librustc/middle/trans/consts.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,7 @@ fn const_expr_unadjusted(cx: @mut CrateContext, e: &ast::expr) -> ValueRef {
446446
(expr::cast_enum, expr::cast_float) => {
447447
let repr = adt::represent_type(cx, basety);
448448
let discr = adt::const_get_discrim(cx, repr, v);
449-
let iv = C_int(cx, discr);
449+
let iv = C_uint(cx, discr);
450450
let ety_cast = expr::cast_type_kind(ety);
451451
match ety_cast {
452452
expr::cast_integral => {

src/librustc/middle/trans/expr.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,7 +1083,7 @@ pub fn trans_local_var(bcx: @mut Block, def: ast::def) -> Datum {
10831083
pub fn with_field_tys<R>(tcx: ty::ctxt,
10841084
ty: ty::t,
10851085
node_id_opt: Option<ast::node_id>,
1086-
op: &fn(int, (&[ty::field])) -> R) -> R {
1086+
op: &fn(uint, (&[ty::field])) -> R) -> R {
10871087
match ty::get(ty).sty {
10881088
ty::ty_struct(did, ref substs) => {
10891089
op(0, struct_fields(tcx, did, substs))
@@ -1200,7 +1200,7 @@ struct StructBaseInfo {
12001200
* - `optbase` contains information on the base struct (if any) from
12011201
* which remaining fields are copied; see comments on `StructBaseInfo`.
12021202
*/
1203-
fn trans_adt(bcx: @mut Block, repr: &adt::Repr, discr: int,
1203+
fn trans_adt(bcx: @mut Block, repr: &adt::Repr, discr: uint,
12041204
fields: &[(uint, @ast::expr)],
12051205
optbase: Option<StructBaseInfo>,
12061206
dest: Dest) -> @mut Block {

src/librustc/middle/trans/reflect.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ impl Reflector {
321321
for variants.iter().enumerate().advance |(i, v)| {
322322
let name = ccx.sess.str_of(v.name);
323323
let variant_args = ~[this.c_uint(i),
324-
this.c_int(v.disr_val),
324+
this.c_uint(v.disr_val),
325325
this.c_uint(v.args.len()),
326326
this.c_slice(name)];
327327
do this.bracketed("enum_variant", variant_args) |this| {

src/librustc/middle/ty.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ use syntax::opt_vec;
4949
use syntax::abi::AbiSet;
5050
use syntax;
5151

52-
pub static INITIAL_DISCRIMINANT_VALUE: int = 0;
52+
pub static INITIAL_DISCRIMINANT_VALUE: uint = 0;
5353

5454
// Data types
5555

@@ -3689,7 +3689,7 @@ pub struct VariantInfo {
36893689
ctor_ty: t,
36903690
name: ast::ident,
36913691
id: ast::def_id,
3692-
disr_val: int,
3692+
disr_val: uint,
36933693
vis: visibility
36943694
}
36953695

@@ -3700,7 +3700,7 @@ impl VariantInfo {
37003700
/// Does not do any caching of the value in the type context.
37013701
pub fn from_ast_variant(cx: ctxt,
37023702
ast_variant: &ast::variant,
3703-
discriminant: int) -> VariantInfo {
3703+
discriminant: uint) -> VariantInfo {
37043704

37053705
let ctor_ty = node_id_to_type(cx, ast_variant.node.id);
37063706

@@ -3894,7 +3894,7 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[@VariantInfo] {
38943894
node: ast::item_enum(ref enum_definition, _),
38953895
_
38963896
}, _) => {
3897-
let mut last_discriminant: Option<int> = None;
3897+
let mut last_discriminant: Option<uint> = None;
38983898
@enum_definition.variants.iter().transform(|variant| {
38993899

39003900
let mut discriminant = match last_discriminant {
@@ -3904,7 +3904,8 @@ pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[@VariantInfo] {
39043904

39053905
match variant.node.disr_expr {
39063906
Some(e) => match const_eval::eval_const_expr_partial(&cx, e) {
3907-
Ok(const_eval::const_int(val)) => discriminant = val as int,
3907+
Ok(const_eval::const_int(val)) => discriminant = val as uint,
3908+
Ok(const_eval::const_uint(val)) => discriminant = val as uint,
39083909
Ok(_) => {
39093910
cx.sess.span_err(e.span, "expected signed integer constant");
39103911
}

0 commit comments

Comments
 (0)