Represent kinds as a bitfield of capabilities.

This commit is contained in:
Eric Holk 2012-05-22 12:46:13 -07:00
parent 8d7f3bd1ca
commit f213c1f3a8
2 changed files with 58 additions and 56 deletions

View file

@ -1,7 +1,7 @@
import syntax::{visit, ast_util}; import syntax::{visit, ast_util};
import syntax::ast::*; import syntax::ast::*;
import syntax::codemap::span; import syntax::codemap::span;
import ty::{kind, kind_copyable, kind_sendable, kind_noncopyable}; import ty::{kind, kind_sendable, kind_copyable, kind_noncopyable };
import driver::session::session; import driver::session::session;
import std::map::hashmap; import std::map::hashmap;
import util::ppaux::{ty_to_str, tys_to_str}; import util::ppaux::{ty_to_str, tys_to_str};
@ -24,11 +24,10 @@ import freevars::freevar_entry;
// types. // types.
fn kind_to_str(k: kind) -> str { fn kind_to_str(k: kind) -> str {
alt k { if k == kind_sendable() { "sendable" }
kind_sendable { "sendable" } else if k == kind_copyable() { "copyable" }
kind_copyable { "copyable" } else if k == kind_noncopyable() { "noncopyable" }
kind_noncopyable { "noncopyable" } else { fail "unknown kind" }
}
} }
type rval_map = std::map::hashmap<node_id, ()>; type rval_map = std::map::hashmap<node_id, ()>;

View file

@ -421,13 +421,13 @@ impl of vid for region_vid {
} }
fn param_bounds_to_kind(bounds: param_bounds) -> kind { fn param_bounds_to_kind(bounds: param_bounds) -> kind {
let mut kind = kind_noncopyable; let mut kind = kind_noncopyable();
for vec::each(*bounds) {|bound| for vec::each(*bounds) {|bound|
alt bound { alt bound {
bound_copy { bound_copy {
if kind != kind_sendable { kind = kind_copyable; } if kind != kind_sendable() { kind = kind_copyable(); }
} }
bound_send { kind = kind_sendable; } bound_send { kind = kind_sendable(); }
_ {} _ {}
} }
} }
@ -1260,43 +1260,46 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
ret needs_unwind_cleanup; ret needs_unwind_cleanup;
} }
enum kind { kind_sendable, kind_copyable, kind_noncopyable, } enum kind { kind_(u32) }
const KIND_MASK_COPY : u32 = 0b00000000000000000000000000000001u32;
const KIND_MASK_SEND : u32 = 0b00000000000000000000000000000010u32;
fn kind_noncopyable() -> kind {
kind_(0u32)
}
fn kind_copyable() -> kind {
kind_(KIND_MASK_COPY)
}
fn kind_sendable() -> kind {
kind_(KIND_MASK_COPY | KIND_MASK_SEND)
}
// Using these query functons is preferable to direct comparison or matching // Using these query functons is preferable to direct comparison or matching
// against the kind constants, as we may modify the kind hierarchy in the // against the kind constants, as we may modify the kind hierarchy in the
// future. // future.
pure fn kind_can_be_copied(k: kind) -> bool { pure fn kind_can_be_copied(k: kind) -> bool {
ret alt k { *k & KIND_MASK_COPY != 0u32
kind_sendable { true }
kind_copyable { true }
kind_noncopyable { false }
};
} }
pure fn kind_can_be_sent(k: kind) -> bool { pure fn kind_can_be_sent(k: kind) -> bool {
ret alt k { *k & KIND_MASK_SEND != 0u32
kind_sendable { true }
kind_copyable { false }
kind_noncopyable { false }
};
} }
fn proto_kind(p: proto) -> kind { fn proto_kind(p: proto) -> kind {
alt p { alt p {
ast::proto_any { kind_noncopyable } ast::proto_any { kind_noncopyable() }
ast::proto_block { kind_noncopyable } ast::proto_block { kind_noncopyable() }
ast::proto_box { kind_copyable } ast::proto_box { kind_copyable() }
ast::proto_uniq { kind_sendable } ast::proto_uniq { kind_sendable() }
ast::proto_bare { kind_sendable } ast::proto_bare { kind_sendable() }
} }
} }
fn kind_lteq(a: kind, b: kind) -> bool { fn kind_lteq(a: kind, b: kind) -> bool {
alt a { *a & *b == *a
kind_noncopyable { true }
kind_copyable { b != kind_noncopyable }
kind_sendable { b == kind_sendable }
}
} }
fn lower_kind(a: kind, b: kind) -> kind { fn lower_kind(a: kind, b: kind) -> kind {
@ -1306,12 +1309,12 @@ fn lower_kind(a: kind, b: kind) -> kind {
#[test] #[test]
fn test_kinds() { fn test_kinds() {
// The kind "lattice" is nocopy <= copy <= send // The kind "lattice" is nocopy <= copy <= send
assert kind_lteq(kind_sendable, kind_sendable); assert kind_lteq(kind_sendable(), kind_sendable());
assert kind_lteq(kind_copyable, kind_sendable); assert kind_lteq(kind_copyable(), kind_sendable());
assert kind_lteq(kind_copyable, kind_copyable); assert kind_lteq(kind_copyable(), kind_copyable());
assert kind_lteq(kind_noncopyable, kind_sendable); assert kind_lteq(kind_noncopyable(), kind_sendable());
assert kind_lteq(kind_noncopyable, kind_copyable); assert kind_lteq(kind_noncopyable(), kind_copyable());
assert kind_lteq(kind_noncopyable, kind_noncopyable); assert kind_lteq(kind_noncopyable(), kind_noncopyable());
} }
fn type_kind(cx: ctxt, ty: t) -> kind { fn type_kind(cx: ctxt, ty: t) -> kind {
@ -1321,24 +1324,24 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
} }
// Insert a default in case we loop back on self recursively. // Insert a default in case we loop back on self recursively.
cx.kind_cache.insert(ty, kind_sendable); cx.kind_cache.insert(ty, kind_sendable());
let result = alt get(ty).struct { let result = alt get(ty).struct {
// Scalar and unique types are sendable // Scalar and unique types are sendable
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) | ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_ptr(_) | ty_str { kind_sendable } ty_ptr(_) | ty_str { kind_sendable() }
ty_type { kind_copyable } ty_type { kind_copyable() }
ty_fn(f) { proto_kind(f.proto) } ty_fn(f) { proto_kind(f.proto) }
// Closures have kind determined by capture mode // Closures have kind determined by capture mode
ty_opaque_closure_ptr(ck_block) { kind_noncopyable } ty_opaque_closure_ptr(ck_block) { kind_noncopyable() }
ty_opaque_closure_ptr(ck_box) { kind_copyable } ty_opaque_closure_ptr(ck_box) { kind_copyable() }
ty_opaque_closure_ptr(ck_uniq) { kind_sendable } ty_opaque_closure_ptr(ck_uniq) { kind_sendable() }
// Those with refcounts raise noncopyable to copyable, // Those with refcounts raise noncopyable to copyable,
// lower sendable to copyable. Therefore just set result to copyable. // lower sendable to copyable. Therefore just set result to copyable.
ty_box(_) | ty_iface(_, _) | ty_opaque_box { kind_copyable } ty_box(_) | ty_iface(_, _) | ty_opaque_box { kind_copyable() }
ty_rptr(_, _) { kind_copyable } ty_rptr(_, _) { kind_copyable() }
// Unique boxes and vecs have the kind of their contained type. // Unique boxes and vecs have the kind of their contained type.
ty_vec(tm) | ty_uniq(tm) { type_kind(cx, tm.ty) } ty_vec(tm) | ty_uniq(tm) { type_kind(cx, tm.ty) }
@ -1346,19 +1349,19 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
// Slice and refcounted evecs are copyable; uniques and interiors // Slice and refcounted evecs are copyable; uniques and interiors
// depend on the their contained type. // depend on the their contained type.
ty_evec(_, vstore_box) | ty_evec(_, vstore_box) |
ty_evec(_, vstore_slice(_)) { kind_copyable } ty_evec(_, vstore_slice(_)) { kind_copyable() }
ty_evec(tm, vstore_uniq) | ty_evec(tm, vstore_uniq) |
ty_evec(tm, vstore_fixed(_)) { type_kind(cx, tm.ty) } ty_evec(tm, vstore_fixed(_)) { type_kind(cx, tm.ty) }
// All estrs are copyable; uniques and interiors are sendable. // All estrs are copyable; uniques and interiors are sendable.
ty_estr(vstore_box) | ty_estr(vstore_box) |
ty_estr(vstore_slice(_)) { kind_copyable } ty_estr(vstore_slice(_)) { kind_copyable() }
ty_estr(vstore_uniq) | ty_estr(vstore_uniq) |
ty_estr(vstore_fixed(_)) { kind_sendable } ty_estr(vstore_fixed(_)) { kind_sendable() }
// Records lower to the lowest of their members. // Records lower to the lowest of their members.
ty_rec(flds) { ty_rec(flds) {
let mut lowest = kind_sendable; let mut lowest = kind_sendable();
for flds.each {|f| for flds.each {|f|
lowest = lower_kind(lowest, type_kind(cx, f.mt.ty)); lowest = lower_kind(lowest, type_kind(cx, f.mt.ty));
} }
@ -1368,7 +1371,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
// sendable, but I'm just treating them like records (#1726) // sendable, but I'm just treating them like records (#1726)
ty_class(did, substs) { ty_class(did, substs) {
// also factor out this code, copied from the records case // also factor out this code, copied from the records case
let mut lowest = kind_sendable; let mut lowest = kind_sendable();
let flds = class_items_as_fields(cx, did, substs); let flds = class_items_as_fields(cx, did, substs);
for flds.each {|f| for flds.each {|f|
lowest = lower_kind(lowest, type_kind(cx, f.mt.ty)); lowest = lower_kind(lowest, type_kind(cx, f.mt.ty));
@ -1377,34 +1380,34 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
} }
// Tuples lower to the lowest of their members. // Tuples lower to the lowest of their members.
ty_tup(tys) { ty_tup(tys) {
let mut lowest = kind_sendable; let mut lowest = kind_sendable();
for tys.each {|ty| lowest = lower_kind(lowest, type_kind(cx, ty)); } for tys.each {|ty| lowest = lower_kind(lowest, type_kind(cx, ty)); }
lowest lowest
} }
// Enums lower to the lowest of their variants. // Enums lower to the lowest of their variants.
ty_enum(did, substs) { ty_enum(did, substs) {
let mut lowest = kind_sendable; let mut lowest = kind_sendable();
let variants = enum_variants(cx, did); let variants = enum_variants(cx, did);
if vec::len(*variants) == 0u { if vec::len(*variants) == 0u {
lowest = kind_noncopyable; lowest = kind_noncopyable();
} else { } else {
for vec::each(*variants) {|variant| for vec::each(*variants) {|variant|
for variant.args.each {|aty| for variant.args.each {|aty|
// Perform any type parameter substitutions. // Perform any type parameter substitutions.
let arg_ty = subst(cx, substs, aty); let arg_ty = subst(cx, substs, aty);
lowest = lower_kind(lowest, type_kind(cx, arg_ty)); lowest = lower_kind(lowest, type_kind(cx, arg_ty));
if lowest == kind_noncopyable { break; } if lowest == kind_noncopyable() { break; }
} }
} }
} }
lowest lowest
} }
ty_res(did, inner, tps) { kind_noncopyable } ty_res(did, inner, tps) { kind_noncopyable() }
ty_param(_, did) { ty_param(_, did) {
param_bounds_to_kind(cx.ty_param_bounds.get(did.node)) param_bounds_to_kind(cx.ty_param_bounds.get(did.node))
} }
ty_constr(t, _) { type_kind(cx, t) } ty_constr(t, _) { type_kind(cx, t) }
ty_self { kind_noncopyable } ty_self { kind_noncopyable() }
ty_var(_) { cx.sess.bug("Asked to compute kind of a type variable"); } ty_var(_) { cx.sess.bug("Asked to compute kind of a type variable"); }
}; };
@ -1605,7 +1608,7 @@ fn type_allows_implicit_copy(cx: ctxt, ty: t) -> bool {
} }
_ { false } _ { false }
} }
}) && type_kind(cx, ty) != kind_noncopyable; }) && type_kind(cx, ty) != kind_noncopyable();
} }
fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool { fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {