Skip to content

Commit 8b6bfc9

Browse files
committed
Const kind checking. The rules are almost certainly incomplete and unsound...
1 parent d993df7 commit 8b6bfc9

File tree

6 files changed

+110
-34
lines changed

6 files changed

+110
-34
lines changed

src/rustc/middle/kind.rs

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
import syntax::{visit, ast_util};
22
import syntax::ast::*;
33
import syntax::codemap::span;
4-
import ty::{kind, kind_sendable, kind_copyable, kind_noncopyable };
4+
import ty::{kind, kind_sendable, kind_copyable, kind_noncopyable, kind_const,
5+
operators};
56
import driver::session::session;
67
import std::map::hashmap;
78
import util::ppaux::{ty_to_str, tys_to_str};
@@ -24,12 +25,17 @@ import freevars::freevar_entry;
2425
// types.
2526

2627
fn kind_to_str(k: kind) -> str {
27-
alt (ty::kind_can_be_copied(k), ty::kind_can_be_sent(k)) {
28-
(false, false) { "noncopyable" }
29-
(false, true) { "sendable" }
30-
(true, false) { "copyable" }
31-
(true, true) { "copy-sendable" }
28+
let mut kinds = [];
29+
if ty::kind_lteq(k, kind_const()) {
30+
kinds += ["const"];
3231
}
32+
if ty::kind_can_be_copied(k) {
33+
kinds += ["copy"];
34+
}
35+
if ty::kind_can_be_sent(k) {
36+
kinds += ["send"];
37+
}
38+
str::connect(kinds, " ")
3339
}
3440

3541
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) {
320326
let kind = ty::type_kind(cx.tcx, ty);
321327
let p_kind = ty::param_bounds_to_kind(bounds);
322328
if !ty::kind_lteq(p_kind, kind) {
323-
cx.tcx.sess.span_err(sp, "instantiating a " +
324-
kind_to_str(p_kind) +
325-
" type parameter with a "
326-
+ kind_to_str(kind) + " type");
329+
cx.tcx.sess.span_err(
330+
sp, "instantiating a type parameter with an incompatible type " +
331+
"(needs `" + kind_to_str(p_kind) +
332+
"`, got `" + kind_to_str(kind) +
333+
"`, missing `" + kind_to_str(p_kind - kind) + "`)");
327334
}
328335
}
329336

src/rustc/middle/ty.rs

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -110,8 +110,9 @@ export ty_var_id;
110110
export ty_to_def_id;
111111
export ty_fn_args;
112112
export type_constr;
113-
export kind, kind_sendable, kind_copyable, kind_noncopyable;
113+
export kind, kind_sendable, kind_copyable, kind_noncopyable, kind_const;
114114
export kind_can_be_copied, kind_can_be_sent, proto_kind, kind_lteq, type_kind;
115+
export operators;
115116
export type_err, terr_vstore_kind;
116117
export type_err_to_str;
117118
export type_needs_drop;
@@ -431,7 +432,8 @@ fn param_bounds_to_kind(bounds: param_bounds) -> kind {
431432
kind = raise_kind(kind, kind_copyable());
432433
}
433434
bound_send { kind = raise_kind(kind, kind_send_only()); }
434-
_ {}
435+
bound_const { kind = raise_kind(kind, kind_const()); }
436+
bound_iface(_) {}
435437
}
436438
}
437439
kind
@@ -1266,8 +1268,9 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
12661268

12671269
enum kind { kind_(u32) }
12681270

1269-
const KIND_MASK_COPY : u32 = 0b00000000000000000000000000000001u32;
1270-
const KIND_MASK_SEND : u32 = 0b00000000000000000000000000000010u32;
1271+
const KIND_MASK_COPY : u32 = 0b00000000000000000000000000000001u32;
1272+
const KIND_MASK_SEND : u32 = 0b00000000000000000000000000000010u32;
1273+
const KIND_MASK_CONST : u32 = 0b00000000000000000000000000000100u32;
12711274

12721275
fn kind_noncopyable() -> kind {
12731276
kind_(0u32)
@@ -1285,10 +1288,37 @@ fn kind_send_only() -> kind {
12851288
kind_(KIND_MASK_SEND)
12861289
}
12871290

1291+
fn kind_const() -> kind {
1292+
kind_(KIND_MASK_CONST)
1293+
}
1294+
12881295
fn kind_top() -> kind {
12891296
kind_(0xffffffffu32)
12901297
}
12911298

1299+
fn remove_const(k: kind, tm: mt) -> kind {
1300+
if tm.mutbl == ast::m_mutbl {
1301+
k - kind_const()
1302+
}
1303+
else {
1304+
k
1305+
}
1306+
}
1307+
1308+
impl operators for kind {
1309+
fn &(other: kind) -> kind {
1310+
lower_kind(self, other)
1311+
}
1312+
1313+
fn |(other: kind) -> kind {
1314+
raise_kind(self, other)
1315+
}
1316+
1317+
fn -(other: kind) -> kind {
1318+
kind_(*self & !*other)
1319+
}
1320+
}
1321+
12921322
// Using these query functons is preferable to direct comparison or matching
12931323
// against the kind constants, as we may modify the kind hierarchy in the
12941324
// future.
@@ -1306,7 +1336,7 @@ fn proto_kind(p: proto) -> kind {
13061336
ast::proto_block { kind_noncopyable() }
13071337
ast::proto_box { kind_copyable() }
13081338
ast::proto_uniq { kind_sendable() }
1309-
ast::proto_bare { kind_sendable() }
1339+
ast::proto_bare { kind_sendable() | kind_const() }
13101340
}
13111341
}
13121342

@@ -1345,7 +1375,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
13451375
let result = alt get(ty).struct {
13461376
// Scalar and unique types are sendable
13471377
ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1348-
ty_ptr(_) | ty_str { kind_sendable() }
1378+
ty_ptr(_) | ty_str { kind_sendable() | kind_const() }
13491379
ty_type { kind_copyable() }
13501380
ty_fn(f) { proto_kind(f.proto) }
13511381

@@ -1356,38 +1386,58 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
13561386

13571387
// Those with refcounts raise noncopyable to copyable,
13581388
// lower sendable to copyable. Therefore just set result to copyable.
1359-
ty_box(_) | ty_iface(_, _) | ty_opaque_box { kind_copyable() }
1389+
ty_box(tm) {
1390+
if tm.mutbl == ast::m_mutbl {
1391+
kind_copyable()
1392+
}
1393+
else {
1394+
let k = type_kind(cx, tm.ty);
1395+
if kind_lteq(kind_const(), k) {
1396+
kind_copyable() | kind_const()
1397+
}
1398+
else { kind_copyable() }
1399+
}
1400+
}
1401+
ty_iface(_, _) | ty_opaque_box { kind_copyable() }
13601402
ty_rptr(_, _) { kind_copyable() }
13611403

13621404
// Unique boxes and vecs have the kind of their contained type.
1363-
ty_vec(tm) | ty_uniq(tm) { type_kind(cx, tm.ty) }
1405+
ty_vec(tm) | ty_uniq(tm) { remove_const(type_kind(cx, tm.ty), tm) }
13641406

13651407
// Slice and refcounted evecs are copyable; uniques and interiors
13661408
// depend on the their contained type.
1367-
ty_evec(_, vstore_box) |
1368-
ty_evec(_, vstore_slice(_)) { kind_copyable() }
1409+
ty_evec(tm, vstore_box) |
1410+
ty_evec(tm, vstore_slice(_)) {
1411+
if kind_lteq(kind_const(), type_kind(cx, tm.ty)) {
1412+
kind_copyable() | kind_const()
1413+
}
1414+
else {
1415+
kind_const()
1416+
}
1417+
}
13691418
ty_evec(tm, vstore_uniq) |
1370-
ty_evec(tm, vstore_fixed(_)) { type_kind(cx, tm.ty) }
1419+
ty_evec(tm, vstore_fixed(_)) { remove_const(type_kind(cx, tm.ty), tm) }
13711420

13721421
// All estrs are copyable; uniques and interiors are sendable.
13731422
ty_estr(vstore_box) |
1374-
ty_estr(vstore_slice(_)) { kind_copyable() }
1423+
ty_estr(vstore_slice(_)) { kind_copyable() | kind_const() }
13751424
ty_estr(vstore_uniq) |
1376-
ty_estr(vstore_fixed(_)) { kind_sendable() }
1425+
ty_estr(vstore_fixed(_)) { kind_sendable() | kind_const() }
13771426

13781427
// Records lower to the lowest of their members.
13791428
ty_rec(flds) {
1380-
let mut lowest = kind_sendable();
1429+
let mut lowest = kind_top();
13811430
for flds.each {|f|
13821431
lowest = lower_kind(lowest, type_kind(cx, f.mt.ty));
1432+
lowest = remove_const(lowest, f.mt);
13831433
}
13841434
lowest
13851435
}
13861436
// FIXME: (tjc) there are rules about when classes are copyable/
13871437
// sendable, but I'm just treating them like records (#1726)
13881438
ty_class(did, substs) {
13891439
// also factor out this code, copied from the records case
1390-
let mut lowest = kind_sendable();
1440+
let mut lowest = kind_top();
13911441
let flds = class_items_as_fields(cx, did, substs);
13921442
for flds.each {|f|
13931443
lowest = lower_kind(lowest, type_kind(cx, f.mt.ty));
@@ -1396,13 +1446,13 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
13961446
}
13971447
// Tuples lower to the lowest of their members.
13981448
ty_tup(tys) {
1399-
let mut lowest = kind_sendable();
1449+
let mut lowest = kind_top();
14001450
for tys.each {|ty| lowest = lower_kind(lowest, type_kind(cx, ty)); }
14011451
lowest
14021452
}
14031453
// Enums lower to the lowest of their variants.
14041454
ty_enum(did, substs) {
1405-
let mut lowest = kind_sendable();
1455+
let mut lowest = kind_top();
14061456
let variants = enum_variants(cx, did);
14071457
if vec::len(*variants) == 0u {
14081458
lowest = kind_noncopyable();
@@ -1423,6 +1473,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
14231473
param_bounds_to_kind(cx.ty_param_bounds.get(did.node))
14241474
}
14251475
ty_constr(t, _) { type_kind(cx, t) }
1476+
// FIXME: is self ever const?
14261477
ty_self { kind_noncopyable() }
14271478

14281479
ty_var(_) { cx.sess.bug("Asked to compute kind of a type variable"); }

src/test/compile-fail/bad-method-typaram-kind.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
1-
// error-pattern:instantiating a copyable type parameter with a noncopyable
21
fn foo<T>() {
3-
1u.bar::<T>();
2+
1u.bar::<T>(); //! ERROR: missing `copy`
43
}
54

65
impl methods for uint {

src/test/compile-fail/non-const.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Test that various non const things are rejected.
2+
3+
fn foo<T: const>(_x: T) { }
4+
5+
resource r(_x: int) {}
6+
7+
fn main() {
8+
foo({f: 3});
9+
foo({mut f: 3}); //! ERROR missing `const`
10+
foo([1]);
11+
foo([mut 1]); //! ERROR missing `const`
12+
foo(~1);
13+
foo(~mut 1); //! ERROR missing `const`
14+
foo(@1);
15+
foo(@mut 1); //! ERROR missing `const`
16+
foo(r(1)); //! ERROR missing `const`
17+
foo("123");
18+
foo({f: {mut f: 1}}); //! ERROR missing `const`
19+
}
Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,7 @@
1-
// error-pattern: instantiating a sendable type parameter with a copyable type
2-
3-
fn f<T: send>(i: T) {
1+
fn f<T: send>(_i: T) {
42
}
53

64
fn main() {
75
let i = ~@100;
8-
f(i);
9-
}
6+
f(i); //! ERROR missing `send`
7+
}

src/test/run-pass/const-bound.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ fn main() {
1010
foo([1, 2, 3]);
1111
foo({field: 42});
1212
foo((1, 2u));
13+
foo(@1);
14+
foo(~1);
1315
}

0 commit comments

Comments
 (0)