Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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.