Skip to content
This repository
Browse code

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

…sound...
  • Loading branch information...
commit 8b6bfc96cba80dd59c244acbb27487e28ef8280f 1 parent d993df7
Eric Holk authored May 24, 2012
27  src/rustc/middle/kind.rs
... ...
@@ -1,7 +1,8 @@
1 1
 import syntax::{visit, ast_util};
2 2
 import syntax::ast::*;
3 3
 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};
5 6
 import driver::session::session;
6 7
 import std::map::hashmap;
7 8
 import util::ppaux::{ty_to_str, tys_to_str};
@@ -24,12 +25,17 @@ import freevars::freevar_entry;
24 25
 // types.
25 26
 
26 27
 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"];
32 31
     }
  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, " ")
33 39
 }
34 40
 
35 41
 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) {
320 326
     let kind = ty::type_kind(cx.tcx, ty);
321 327
     let p_kind = ty::param_bounds_to_kind(bounds);
322 328
     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) + "`)");
327 334
     }
328 335
 }
329 336
 
85  src/rustc/middle/ty.rs
@@ -110,8 +110,9 @@ export ty_var_id;
110 110
 export ty_to_def_id;
111 111
 export ty_fn_args;
112 112
 export type_constr;
113  
-export kind, kind_sendable, kind_copyable, kind_noncopyable;
  113
+export kind, kind_sendable, kind_copyable, kind_noncopyable, kind_const;
114 114
 export kind_can_be_copied, kind_can_be_sent, proto_kind, kind_lteq, type_kind;
  115
+export operators;
115 116
 export type_err, terr_vstore_kind;
116 117
 export type_err_to_str;
117 118
 export type_needs_drop;
@@ -431,7 +432,8 @@ fn param_bounds_to_kind(bounds: param_bounds) -> kind {
431 432
             kind = raise_kind(kind, kind_copyable());
432 433
           }
433 434
           bound_send { kind = raise_kind(kind, kind_send_only()); }
434  
-          _ {}
  435
+          bound_const { kind = raise_kind(kind, kind_const()); }
  436
+          bound_iface(_) {}
435 437
         }
436 438
     }
437 439
     kind
@@ -1266,8 +1268,9 @@ fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
1266 1268
 
1267 1269
 enum kind { kind_(u32) }
1268 1270
 
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;
1271 1274
 
1272 1275
 fn kind_noncopyable() -> kind {
1273 1276
     kind_(0u32)
@@ -1285,10 +1288,37 @@ fn kind_send_only() -> kind {
1285 1288
     kind_(KIND_MASK_SEND)
1286 1289
 }
1287 1290
 
  1291
+fn kind_const() -> kind {
  1292
+    kind_(KIND_MASK_CONST)
  1293
+}
  1294
+
1288 1295
 fn kind_top() -> kind {
1289 1296
     kind_(0xffffffffu32)
1290 1297
 }
1291 1298
 
  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
+
1292 1322
 // Using these query functons is preferable to direct comparison or matching
1293 1323
 // against the kind constants, as we may modify the kind hierarchy in the
1294 1324
 // future.
@@ -1306,7 +1336,7 @@ fn proto_kind(p: proto) -> kind {
1306 1336
       ast::proto_block { kind_noncopyable() }
1307 1337
       ast::proto_box { kind_copyable() }
1308 1338
       ast::proto_uniq { kind_sendable() }
1309  
-      ast::proto_bare { kind_sendable() }
  1339
+      ast::proto_bare { kind_sendable() | kind_const() }
1310 1340
     }
1311 1341
 }
1312 1342
 
@@ -1345,7 +1375,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
1345 1375
     let result = alt get(ty).struct {
1346 1376
       // Scalar and unique types are sendable
1347 1377
       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() }
1349 1379
       ty_type { kind_copyable() }
1350 1380
       ty_fn(f) { proto_kind(f.proto) }
1351 1381
 
@@ -1356,30 +1386,50 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
1356 1386
 
1357 1387
       // Those with refcounts raise noncopyable to copyable,
1358 1388
       // 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() }
1360 1402
       ty_rptr(_, _) { kind_copyable() }
1361 1403
 
1362 1404
       // 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) }
1364 1406
 
1365 1407
       // Slice and refcounted evecs are copyable; uniques and interiors
1366 1408
       // 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
+      }
1369 1418
       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) }
1371 1420
 
1372 1421
       // All estrs are copyable; uniques and interiors are sendable.
1373 1422
       ty_estr(vstore_box) |
1374  
-      ty_estr(vstore_slice(_)) { kind_copyable() }
  1423
+      ty_estr(vstore_slice(_)) { kind_copyable() | kind_const() }
1375 1424
       ty_estr(vstore_uniq) |
1376  
-      ty_estr(vstore_fixed(_)) { kind_sendable()  }
  1425
+      ty_estr(vstore_fixed(_)) { kind_sendable() | kind_const() }
1377 1426
 
1378 1427
       // Records lower to the lowest of their members.
1379 1428
       ty_rec(flds) {
1380  
-        let mut lowest = kind_sendable();
  1429
+        let mut lowest = kind_top();
1381 1430
         for flds.each {|f|
1382 1431
             lowest = lower_kind(lowest, type_kind(cx, f.mt.ty));
  1432
+            lowest = remove_const(lowest, f.mt);
1383 1433
         }
1384 1434
         lowest
1385 1435
       }
@@ -1387,7 +1437,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
1387 1437
       // sendable, but I'm just treating them like records (#1726)
1388 1438
       ty_class(did, substs) {
1389 1439
           // also factor out this code, copied from the records case
1390  
-          let mut lowest = kind_sendable();
  1440
+          let mut lowest = kind_top();
1391 1441
           let flds = class_items_as_fields(cx, did, substs);
1392 1442
           for flds.each {|f|
1393 1443
             lowest = lower_kind(lowest, type_kind(cx, f.mt.ty));
@@ -1396,13 +1446,13 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
1396 1446
       }
1397 1447
       // Tuples lower to the lowest of their members.
1398 1448
       ty_tup(tys) {
1399  
-        let mut lowest = kind_sendable();
  1449
+        let mut lowest = kind_top();
1400 1450
         for tys.each {|ty| lowest = lower_kind(lowest, type_kind(cx, ty)); }
1401 1451
         lowest
1402 1452
       }
1403 1453
       // Enums lower to the lowest of their variants.
1404 1454
       ty_enum(did, substs) {
1405  
-        let mut lowest = kind_sendable();
  1455
+        let mut lowest = kind_top();
1406 1456
         let variants = enum_variants(cx, did);
1407 1457
         if vec::len(*variants) == 0u {
1408 1458
             lowest = kind_noncopyable();
@@ -1423,6 +1473,7 @@ fn type_kind(cx: ctxt, ty: t) -> kind {
1423 1473
           param_bounds_to_kind(cx.ty_param_bounds.get(did.node))
1424 1474
       }
1425 1475
       ty_constr(t, _) { type_kind(cx, t) }
  1476
+      // FIXME: is self ever const?
1426 1477
       ty_self { kind_noncopyable() }
1427 1478
 
1428 1479
       ty_var(_) { cx.sess.bug("Asked to compute kind of a type variable"); }
3  src/test/compile-fail/bad-method-typaram-kind.rs
... ...
@@ -1,6 +1,5 @@
1  
-// error-pattern:instantiating a copyable type parameter with a noncopyable
2 1
 fn foo<T>() {
3  
-    1u.bar::<T>();
  2
+    1u.bar::<T>(); //! ERROR: missing `copy`
4 3
 }
5 4
 
6 5
 impl methods for uint {
19  src/test/compile-fail/non-const.rs
... ...
@@ -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
+}
8  src/test/compile-fail/unique-unique-kind.rs
... ...
@@ -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) {
4 2
 }
5 3
 
6 4
 fn main() {
7 5
     let i = ~@100;
8  
-    f(i);
9  
-}
  6
+    f(i); //! ERROR missing `send`
  7
+}
2  src/test/run-pass/const-bound.rs
@@ -10,4 +10,6 @@ fn main() {
10 10
     foo([1, 2, 3]);
11 11
     foo({field: 42});
12 12
     foo((1, 2u));
  13
+    foo(@1);
  14
+    foo(~1);
13 15
 }

0 notes on commit 8b6bfc9

Please sign in to comment.
Something went wrong with that request. Please try again.