Skip to content

Commit 3366090

Browse files
committed
---
yaml --- r: 146300 b: refs/heads/try2 c: a027f16 h: refs/heads/master v: v3
1 parent f4bd6d9 commit 3366090

File tree

4 files changed

+65
-17
lines changed

4 files changed

+65
-17
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: 78a7676898d9f80ab540c6df5d4c9ce35bb50463
55
refs/heads/try: 519addf6277dbafccbb4159db4b710c37eaa2ec5
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: c8c08763ec12b0e693f400390957249c1f6583b9
8+
refs/heads/try2: a027f164bcda6f99d0b44f79ca9f676ecc12a50a
99
refs/heads/dist-snap: ba4081a5a8573875fed17545846f6f6902c8ba8d
1010
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596
1111
refs/tags/release-0.3: b5f0d0f648d9a6153664837026ba1be43d3e2503

branches/try2/src/librustc/middle/trans/adt.rs

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,8 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
150150

151151
if cases.len() == 0 {
152152
// Uninhabitable; represent as unit
153+
// (Typechecking will reject discriminant-sizing attrs.)
154+
assert_eq!(hint, attr::ReprAny);
153155
return Univariant(mk_struct(cx, [], false), false);
154156
}
155157

@@ -165,13 +167,6 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
165167
return mk_cenum(cx, hint, &bounds);
166168
}
167169

168-
if cases.len() == 1 {
169-
// Equivalent to a struct/tuple/newtype.
170-
// FIXME: should this conflict with a discriminant size hint?
171-
assert_eq!(cases[0].discr, 0);
172-
return Univariant(mk_struct(cx, cases[0].tys, false), false)
173-
}
174-
175170
// Since there's at least one
176171
// non-empty body, explicit discriminants should have
177172
// been rejected by a checker before this point.
@@ -181,8 +176,15 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
181176
ty::item_path_str(cx.tcx, def_id)))
182177
}
183178

184-
if cases.len() == 2 {
185-
// FIXME: disable if size hint present?
179+
if cases.len() == 1 {
180+
// Equivalent to a struct/tuple/newtype.
181+
// (Typechecking will reject discriminant-sizing attrs.)
182+
assert_eq!(hint, attr::ReprAny);
183+
return Univariant(mk_struct(cx, cases[0].tys, false), false)
184+
}
185+
186+
if cases.len() == 2 && hint == attr::ReprAny {
187+
// Nullable pointer optimization
186188
let mut discr = 0;
187189
while discr < 2 {
188190
if cases[1 - discr].is_zerolen(cx) {
@@ -205,7 +207,6 @@ fn represent_type_uncached(cx: &mut CrateContext, t: ty::t) -> Repr {
205207
}
206208

207209
// The general case.
208-
let hint = ty::lookup_repr_hint(cx.tcx, def_id);
209210
assert!((cases.len() - 1) as i64 >= 0);
210211
let bounds = IntBounds { ulo: 0, uhi: (cases.len() - 1) as u64,
211212
slo: 0, shi: (cases.len() - 1) as i64 };
@@ -307,7 +308,7 @@ fn range_to_inttype(cx: &mut CrateContext, hint: Hint, bounds: &IntBounds) -> In
307308
match hint {
308309
attr::ReprInt(span, ity) => {
309310
if !bounds_usable(cx, ity, bounds) {
310-
cx.sess.span_err(span, "representation hint insufficient for discriminant range")
311+
cx.sess.span_bug(span, "representation hint insufficient for discriminant range")
311312
}
312313
return ity;
313314
}
@@ -365,6 +366,7 @@ fn ty_of_inttype(ity: IntType) -> ty::t {
365366
}
366367
}
367368

369+
368370
/**
369371
* Returns the fields of a struct for the given representation.
370372
* All nominal types are LLVM structs, in order to be able to use

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

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ use syntax::ast;
121121
use syntax::ast_map;
122122
use syntax::ast_util::local_def;
123123
use syntax::ast_util;
124+
use syntax::attr;
124125
use syntax::codemap::Span;
125126
use syntax::codemap;
126127
use syntax::opt_vec::OptVec;
@@ -3159,9 +3160,38 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt,
31593160
sp: Span,
31603161
vs: &[ast::variant],
31613162
id: ast::NodeId) {
3163+
3164+
fn disr_in_range(ccx: @mut CrateCtxt,
3165+
ty: attr::IntType,
3166+
disr: ty::Disr) -> bool {
3167+
fn uint_in_range(ccx: @mut CrateCtxt, ty: ast::uint_ty, disr: ty::Disr) -> bool {
3168+
match ty {
3169+
ast::ty_u8 => disr as u8 as Disr == disr,
3170+
ast::ty_u16 => disr as u16 as Disr == disr,
3171+
ast::ty_u32 => disr as u32 as Disr == disr,
3172+
ast::ty_u64 => disr as u64 as Disr == disr,
3173+
ast::ty_u => uint_in_range(ccx, ccx.tcx.sess.targ_cfg.uint_type, disr)
3174+
}
3175+
}
3176+
fn int_in_range(ccx: @mut CrateCtxt, ty: ast::int_ty, disr: ty::Disr) -> bool {
3177+
match ty {
3178+
ast::ty_i8 => disr as i8 as Disr == disr,
3179+
ast::ty_i16 => disr as i16 as Disr == disr,
3180+
ast::ty_i32 => disr as i32 as Disr == disr,
3181+
ast::ty_i64 => disr as i64 as Disr == disr,
3182+
ast::ty_i => int_in_range(ccx, ccx.tcx.sess.targ_cfg.int_type, disr)
3183+
}
3184+
}
3185+
match ty {
3186+
attr::UnsignedInt(ty) => uint_in_range(ccx, ty, disr),
3187+
attr::SignedInt(ty) => int_in_range(ccx, ty, disr)
3188+
}
3189+
}
3190+
31623191
fn do_check(ccx: @mut CrateCtxt,
31633192
vs: &[ast::variant],
3164-
id: ast::NodeId)
3193+
id: ast::NodeId,
3194+
hint: attr::ReprAttr)
31653195
-> ~[@ty::VariantInfo] {
31663196

31673197
let rty = ty::node_id_to_type(ccx.tcx, id);
@@ -3203,9 +3233,20 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt,
32033233
None => ()
32043234
};
32053235

3206-
// Check for duplicate discriminator values
3236+
// Check for duplicate discriminant values
32073237
if disr_vals.contains(&current_disr_val) {
3208-
ccx.tcx.sess.span_err(v.span, "discriminator value already exists");
3238+
ccx.tcx.sess.span_err(v.span, "discriminant value already exists");
3239+
}
3240+
// Check for unrepresentable discriminant values
3241+
match hint {
3242+
attr::ReprAny | attr::ReprExtern => (),
3243+
attr::ReprInt(sp, ity) => {
3244+
if !disr_in_range(ccx, ity, current_disr_val) {
3245+
ccx.tcx.sess.span_err(v.span,
3246+
"discriminant value outside specified type");
3247+
ccx.tcx.sess.span_note(sp, "discriminant type specified here");
3248+
}
3249+
}
32093250
}
32103251
disr_vals.push(current_disr_val);
32113252

@@ -3219,8 +3260,13 @@ pub fn check_enum_variants(ccx: @mut CrateCtxt,
32193260
}
32203261

32213262
let rty = ty::node_id_to_type(ccx.tcx, id);
3263+
let hint = ty::lookup_repr_hint(ccx.tcx, ast::DefId { crate: ast::LOCAL_CRATE, node: id });
3264+
if hint != attr::ReprAny && vs.len() <= 1 {
3265+
ccx.tcx.sess.span_err(sp, format!("unsupported representation for {}variant enum",
3266+
if vs.len() == 1 { "uni" } else { "zero-" }))
3267+
}
32223268

3223-
let variants = do_check(ccx, vs, id);
3269+
let variants = do_check(ccx, vs, id, hint);
32243270

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

branches/try2/src/test/compile-fail/tag-variant-disr-dup.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
//error-pattern:discriminator value already exists
11+
//error-pattern:discriminant value already exists
1212

1313
// black and white have the same discriminator value ...
1414

0 commit comments

Comments
 (0)