Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Const kind checking. The rules are almost certainly incomplete and un…

…sound...
  • Loading branch information...
commit 8b6bfc96cba80dd59c244acbb27487e28ef8280f 1 parent d993df7
@eholk eholk authored
View
27 src/rustc/middle/kind.rs
@@ -1,7 +1,8 @@
import syntax::{visit, ast_util};
import syntax::ast::*;
import syntax::codemap::span;
-import ty::{kind, kind_sendable, kind_copyable, kind_noncopyable };
+import ty::{kind, kind_sendable, kind_copyable, kind_noncopyable, kind_const,
+ operators};
import driver::session::session;
import std::map::hashmap;
import util::ppaux::{ty_to_str, tys_to_str};
@@ -24,12 +25,17 @@ import freevars::freevar_entry;
// types.
fn kind_to_str(k: kind) -> str {
- alt (ty::kind_can_be_copied(k), ty::kind_can_be_sent(k)) {
- (false, false) { "noncopyable" }
- (false, true) { "sendable" }
- (true, false) { "copyable" }
- (true, true) { "copy-sendable" }
+ let mut kinds = [];
+ if ty::kind_lteq(k, kind_const()) {
+ kinds += ["const"];
}
+ if ty::kind_can_be_copied(k) {
+ kinds += ["copy"];
+ }
+ if ty::kind_can_be_sent(k) {
+ kinds += ["send"];
+ }
+ str::connect(kinds, " ")
}
type rval_map = std::map::hashmap<node_id, ()>;
@@ -320,10 +326,11 @@ fn check_bounds(cx: ctx, sp: span, ty: ty::t, bounds: ty::param_bounds) {
let kind = ty::type_kind(cx.tcx, ty);
let p_kind = ty::param_bounds_to_kind(bounds);
if !ty::kind_lteq(p_kind, kind) {
- cx.tcx.sess.span_err(sp, "instantiating a " +
- kind_to_str(p_kind) +
- " type parameter with a "
- + kind_to_str(kind) + " type");
+ cx.tcx.sess.span_err(
+ sp, "instantiating a type parameter with an incompatible type " +
+ "(needs `" + kind_to_str(p_kind) +
+ "`, got `" + kind_to_str(kind) +
+ "`, missing `" + kind_to_str(p_kind - kind) + "`)");
}
}
View
85 src/rustc/middle/ty.rs
@@ -110,8 +110,9 @@ export ty_var_id;
export ty_to_def_id;
export ty_fn_args;
export type_constr;
-export kind, kind_sendable, kind_copyable, kind_noncopyable;
+export kind, kind_sendable, kind_copyable, kind_noncopyable, kind_const;
export kind_can_be_copied, kind_can_be_sent, proto_kind, kind_lteq, type_kind;
+export operators;
export type_err, terr_vstore_kind;
export type_err_to_str;
export type_needs_drop;
@@ -431,7 +432,8 @@ fn param_bounds_to_kind(bounds: param_bounds) -> kind {
kind = raise_kind(kind, kind_copyable());
}
bound_send { kind = raise_kind(kind, kind_send_only()); }
- _ {}
+ bound_const { kind = raise_kind(kind, kind_const()); }
+ bound_iface(_) {}
}
}
kind
@@ -1266,8 +1268,9 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
enum kind { kind_(u32) }
-const KIND_MASK_COPY : u32 = 0b00000000000000000000000000000001u32;
-const KIND_MASK_SEND : u32 = 0b00000000000000000000000000000010u32;
+const KIND_MASK_COPY : u32 = 0b00000000000000000000000000000001u32;
+const KIND_MASK_SEND : u32 = 0b00000000000000000000000000000010u32;
+const KIND_MASK_CONST : u32 = 0b00000000000000000000000000000100u32;
fn kind_noncopyable() -> kind {
kind_(0u32)
@@ -1285,10 +1288,37 @@ fn kind_send_only() -> kind {
kind_(KIND_MASK_SEND)
}
+fn kind_const() -> kind {
+ kind_(KIND_MASK_CONST)
+}
+
fn kind_top() -> kind {
kind_(0xffffffffu32)
}
+fn remove_const(k: kind, tm: mt) -> kind {
+ if tm.mutbl == ast::m_mutbl {
+ k - kind_const()
+ }
+ else {
+ k
+ }
+}
+
+impl operators for kind {
+ fn &(other: kind) -> kind {
+ lower_kind(self, other)
+ }
+
+ fn |(other: kind) -> kind {
+ raise_kind(self, other)
+ }
+
+ fn -(other: kind) -> kind {
+ kind_(*self & !*other)
+ }
+}
+
// Using these query functons is preferable to direct comparison or matching
// against the kind constants, as we may modify the kind hierarchy in the
// future.
@@ -1306,7 +1336,7 @@ fn proto_kind(p: proto) -> kind {
ast::proto_block { kind_noncopyable() }
ast::proto_box { kind_copyable() }
ast::proto_uniq { kind_sendable() }
- ast::proto_bare { kind_sendable() }
+ ast::proto_bare { kind_sendable() | kind_const() }
}
}
@@ -1345,7 +1375,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
let result = alt get(ty).struct {
// Scalar and unique types are sendable
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
- ty_ptr(_) | ty_str { kind_sendable() }
+ ty_ptr(_) | ty_str { kind_sendable() | kind_const() }
ty_type { kind_copyable() }
ty_fn(f) { proto_kind(f.proto) }
@@ -1356,30 +1386,50 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
// Those with refcounts raise noncopyable to copyable,
// lower sendable to copyable. Therefore just set result to copyable.
- ty_box(_) | ty_iface(_, _) | ty_opaque_box { kind_copyable() }
+ ty_box(tm) {
+ if tm.mutbl == ast::m_mutbl {
+ kind_copyable()
+ }
+ else {
+ let k = type_kind(cx, tm.ty);
+ if kind_lteq(kind_const(), k) {
+ kind_copyable() | kind_const()
+ }
+ else { kind_copyable() }
+ }
+ }
+ ty_iface(_, _) | ty_opaque_box { kind_copyable() }
ty_rptr(_, _) { kind_copyable() }
// 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) { remove_const(type_kind(cx, tm.ty), tm) }
// Slice and refcounted evecs are copyable; uniques and interiors
// depend on the their contained type.
- ty_evec(_, vstore_box) |
- ty_evec(_, vstore_slice(_)) { kind_copyable() }
+ ty_evec(tm, vstore_box) |
+ ty_evec(tm, vstore_slice(_)) {
+ if kind_lteq(kind_const(), type_kind(cx, tm.ty)) {
+ kind_copyable() | kind_const()
+ }
+ else {
+ kind_const()
+ }
+ }
ty_evec(tm, vstore_uniq) |
- ty_evec(tm, vstore_fixed(_)) { type_kind(cx, tm.ty) }
+ ty_evec(tm, vstore_fixed(_)) { remove_const(type_kind(cx, tm.ty), tm) }
// All estrs are copyable; uniques and interiors are sendable.
ty_estr(vstore_box) |
- ty_estr(vstore_slice(_)) { kind_copyable() }
+ ty_estr(vstore_slice(_)) { kind_copyable() | kind_const() }
ty_estr(vstore_uniq) |
- ty_estr(vstore_fixed(_)) { kind_sendable() }
+ ty_estr(vstore_fixed(_)) { kind_sendable() | kind_const() }
// Records lower to the lowest of their members.
ty_rec(flds) {
- let mut lowest = kind_sendable();
+ let mut lowest = kind_top();
for flds.each {|f|
lowest = lower_kind(lowest, type_kind(cx, f.mt.ty));
+ lowest = remove_const(lowest, f.mt);
}
lowest
}
@@ -1387,7 +1437,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
// sendable, but I'm just treating them like records (#1726)
ty_class(did, substs) {
// also factor out this code, copied from the records case
- let mut lowest = kind_sendable();
+ let mut lowest = kind_top();
let flds = class_items_as_fields(cx, did, substs);
for flds.each {|f|
lowest = lower_kind(lowest, type_kind(cx, f.mt.ty));
@@ -1396,13 +1446,13 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
}
// Tuples lower to the lowest of their members.
ty_tup(tys) {
- let mut lowest = kind_sendable();
+ let mut lowest = kind_top();
for tys.each {|ty| lowest = lower_kind(lowest, type_kind(cx, ty)); }
lowest
}
// Enums lower to the lowest of their variants.
ty_enum(did, substs) {
- let mut lowest = kind_sendable();
+ let mut lowest = kind_top();
let variants = enum_variants(cx, did);
if vec::len(*variants) == 0u {
lowest = kind_noncopyable();
@@ -1423,6 +1473,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
param_bounds_to_kind(cx.ty_param_bounds.get(did.node))
}
ty_constr(t, _) { type_kind(cx, t) }
+ // FIXME: is self ever const?
ty_self { kind_noncopyable() }
ty_var(_) { cx.sess.bug("Asked to compute kind of a type variable"); }
View
3  src/test/compile-fail/bad-method-typaram-kind.rs
@@ -1,6 +1,5 @@
-// error-pattern:instantiating a copyable type parameter with a noncopyable
fn foo<T>() {
- 1u.bar::<T>();
+ 1u.bar::<T>(); //! ERROR: missing `copy`
}
impl methods for uint {
View
19 src/test/compile-fail/non-const.rs
@@ -0,0 +1,19 @@
+// Test that various non const things are rejected.
+
+fn foo<T: const>(_x: T) { }
+
+resource r(_x: int) {}
+
+fn main() {
+ foo({f: 3});
+ foo({mut f: 3}); //! ERROR missing `const`
+ foo([1]);
+ foo([mut 1]); //! ERROR missing `const`
+ foo(~1);
+ foo(~mut 1); //! ERROR missing `const`
+ foo(@1);
+ foo(@mut 1); //! ERROR missing `const`
+ foo(r(1)); //! ERROR missing `const`
+ foo("123");
+ foo({f: {mut f: 1}}); //! ERROR missing `const`
+}
View
8 src/test/compile-fail/unique-unique-kind.rs
@@ -1,9 +1,7 @@
-// error-pattern: instantiating a sendable type parameter with a copyable type
-
-fn f<T: send>(i: T) {
+fn f<T: send>(_i: T) {
}
fn main() {
let i = ~@100;
- f(i);
-}
+ f(i); //! ERROR missing `send`
+}
View
2  src/test/run-pass/const-bound.rs
@@ -10,4 +10,6 @@ fn main() {
foo([1, 2, 3]);
foo({field: 42});
foo((1, 2u));
+ foo(@1);
+ foo(~1);
}
Please sign in to comment.
Something went wrong with that request. Please try again.