Skip to content

Commit caf787e

Browse files
kevinagraydon
authored andcommitted
---
yaml --- r: 7164 b: refs/heads/master c: 1dc3deb h: refs/heads/master v: v3
1 parent b3ef55d commit caf787e

File tree

6 files changed

+64
-7
lines changed

6 files changed

+64
-7
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: 08abf8d37fa549ebc67f80d80530f4aa43d716e4
2+
refs/heads/master: 1dc3debdafbf29c6ac4ff3cf336da62e13e1871e

trunk/src/comp/middle/trans.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3017,7 +3017,7 @@ fn trans_cast(cx: @block_ctxt, e: @ast::expr, id: ast::node_id,
30173017
check (type_has_static_size(ccx, t_out));
30183018
let ll_t_out = type_of(ccx, e.span, t_out);
30193019

3020-
tag kind { pointer; integral; float; other; }
3020+
tag kind { pointer; integral; float; tag_; other; }
30213021
fn t_kind(tcx: ty::ctxt, t: ty::t) -> kind {
30223022
ret if ty::type_is_fp(tcx, t) {
30233023
float
@@ -3026,6 +3026,8 @@ fn trans_cast(cx: @block_ctxt, e: @ast::expr, id: ast::node_id,
30263026
pointer
30273027
} else if ty::type_is_integral(tcx, t) {
30283028
integral
3029+
} else if ty::type_is_tag(tcx, t) {
3030+
tag_
30293031
} else { other };
30303032
}
30313033
let k_in = t_kind(ccx.tcx, t_in);
@@ -3059,6 +3061,18 @@ fn trans_cast(cx: @block_ctxt, e: @ast::expr, id: ast::node_id,
30593061
{in: pointer., out: pointer.} {
30603062
PointerCast(e_res.bcx, e_res.val, ll_t_out)
30613063
}
3064+
{in: tag_., out: integral.} | {in: tag_., out: float.} {
3065+
let cx = e_res.bcx;
3066+
let lltagty = T_opaque_tag_ptr(ccx);
3067+
let av_tag = PointerCast(cx, e_res.val, lltagty);
3068+
let lldiscrim_a_ptr = GEPi(cx, av_tag, [0, 0]);
3069+
let lldiscrim_a = Load(cx, lldiscrim_a_ptr);
3070+
alt k_out {
3071+
integral. {int_cast(e_res.bcx, ll_t_out,
3072+
val_ty(lldiscrim_a), lldiscrim_a, true)}
3073+
float. {SIToFP(e_res.bcx, lldiscrim_a, ll_t_out)}
3074+
}
3075+
}
30623076
_ { ccx.sess.bug("Translating unsupported cast.") }
30633077
};
30643078
ret store_in_dest(e_res.bcx, newval, dest);

trunk/src/comp/middle/ty.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,8 @@ export type_is_copyable;
173173
export type_is_tup_like;
174174
export type_is_str;
175175
export type_is_unique;
176+
export type_is_tag;
177+
export type_is_enum_like;
176178
export type_structurally_contains_uniques;
177179
export type_autoderef;
178180
export type_param;
@@ -1263,6 +1265,26 @@ fn type_is_pod(cx: ctxt, ty: t) -> bool {
12631265
ret result;
12641266
}
12651267

1268+
fn type_is_tag(cx: ctxt, ty: t) -> bool {
1269+
alt struct(cx, ty) {
1270+
ty_tag(_, _) { ret true; }
1271+
_ { ret false;}
1272+
}
1273+
}
1274+
1275+
// Whether a type is enum like, that is a tag type with only nullary
1276+
// constructors
1277+
fn type_is_enum_like(cx: ctxt, ty: t) -> bool {
1278+
alt struct(cx, ty) {
1279+
ty_tag(did, tps) {
1280+
let variants = tag_variants(cx, did);
1281+
let some_n_ary = vec::any(*variants, {|v| vec::len(v.args) > 0u});
1282+
ret !some_n_ary;
1283+
}
1284+
_ { ret false;}
1285+
}
1286+
}
1287+
12661288
fn type_param(cx: ctxt, ty: t) -> option::t<uint> {
12671289
alt struct(cx, ty) {
12681290
ty_param(id, _) { ret some(id); }

trunk/src/comp/middle/typeck.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,6 +211,10 @@ fn type_is_scalar(fcx: @fn_ctxt, sp: span, typ: ty::t) -> bool {
211211
ret ty::type_is_scalar(fcx.ccx.tcx, typ_s);
212212
}
213213

214+
fn type_is_enum_like(fcx: @fn_ctxt, sp: span, typ: ty::t) -> bool {
215+
let typ_s = structurally_resolved_type(fcx, sp, typ);
216+
ret ty::type_is_enum_like(fcx.ccx.tcx, typ_s);
217+
}
214218

215219
// Parses the programmer's textual representation of a type into our internal
216220
// notion of a type. `getter` is a function that returns the type
@@ -2211,10 +2215,13 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
22112215
// This will be looked up later on
22122216
ty::ty_iface(_, _) {}
22132217
_ {
2214-
// FIXME there are more forms of cast to support, eventually.
2215-
if !( type_is_scalar(fcx, expr.span, t_e)
2216-
&& type_is_scalar(fcx, expr.span, t_1)) {
2217-
tcx.sess.span_err(expr.span, "non-scalar cast: " +
2218+
let t_1_is_scalar = type_is_scalar(fcx, expr.span, t_1);
2219+
if type_is_enum_like(fcx,expr.span,t_e) && t_1_is_scalar {
2220+
/* this case is allowed */
2221+
} else if !(type_is_scalar(fcx,expr.span,t_e) && t_1_is_scalar) {
2222+
// FIXME there are more forms of cast to support, eventually.
2223+
tcx.sess.span_err(expr.span,
2224+
"non-scalar cast: " +
22182225
ty_to_str(tcx, t_e) + " as " +
22192226
ty_to_str(tcx, t_1));
22202227
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//error-pattern: non-scalar cast
2+
// black and white have the same discriminator value ...
3+
4+
tag non_nullary {
5+
nullary;
6+
other(int);
7+
}
8+
9+
fn main() {
10+
let v = nullary;
11+
let val = v as int;
12+
}

trunk/src/test/run-pass/tag-variant-disr-val.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ fn main() {
1717
}
1818

1919
fn test_color(color: color, val: int, name: str) unsafe {
20-
assert unsafe::reinterpret_cast(color) == val;
20+
//assert unsafe::reinterpret_cast(color) == val;
21+
assert color as int == val;
22+
assert color as float == val as float;
2123
assert get_color_alt(color) == name;
2224
assert get_color_if(color) == name;
2325
}

0 commit comments

Comments
 (0)