|
| 1 | +import std::option::some; |
| 2 | +import syntax::{visit, ast_util}; |
| 3 | +import syntax::ast::*; |
| 4 | +import syntax::codemap::span; |
| 5 | + |
| 6 | +fn kind_to_str(k: kind) -> str { |
| 7 | + alt k { |
| 8 | + kind_sendable. { "sendable" } |
| 9 | + kind_copyable. { "copyable" } |
| 10 | + kind_noncopyable. { "noncopyable" } |
| 11 | + } |
| 12 | +} |
| 13 | + |
| 14 | +type rval_map = std::map::hashmap<node_id, ()>; |
| 15 | + |
| 16 | +type ctx = {tcx: ty::ctxt, |
| 17 | + rval_map: rval_map, |
| 18 | + mutable ret_by_ref: bool}; |
| 19 | + |
| 20 | +fn check_crate(tcx: ty::ctxt, crate: @crate) -> rval_map { |
| 21 | + let ctx = {tcx: tcx, |
| 22 | + rval_map: std::map::new_int_hash(), |
| 23 | + mutable ret_by_ref: false}; |
| 24 | + let visit = visit::mk_vt(@{ |
| 25 | + visit_expr: check_expr, |
| 26 | + visit_stmt: check_stmt, |
| 27 | + visit_fn: visit_fn |
| 28 | + with *visit::default_visitor() |
| 29 | + }); |
| 30 | + visit::visit_crate(*crate, ctx, visit); |
| 31 | + // FIXME go through alias's copy_map, check implicit copies (either here, |
| 32 | + // or in alias.rs) |
| 33 | + tcx.sess.abort_if_errors(); |
| 34 | + ret ctx.rval_map; |
| 35 | +} |
| 36 | + |
| 37 | +fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) { |
| 38 | + alt e.node { |
| 39 | + expr_assign(_, ex) | expr_assign_op(_, _, ex) | |
| 40 | + expr_block({node: {expr: some(ex), _}, _}) | |
| 41 | + expr_unary(box(_), ex) | expr_unary(uniq(_), ex) { maybe_copy(cx, ex); } |
| 42 | + expr_ret(some(ex)) { if !cx.ret_by_ref { maybe_copy(cx, ex); } } |
| 43 | + expr_copy(expr) { check_copy_ex(cx, expr, false); } |
| 44 | + // Vector add copies. |
| 45 | + expr_binary(add., ls, rs) { maybe_copy(cx, ls); maybe_copy(cx, rs); } |
| 46 | + expr_rec(fields, _) { |
| 47 | + for field in fields { maybe_copy(cx, field.node.expr); } |
| 48 | + } |
| 49 | + expr_tup(exprs) | expr_vec(exprs, _) { |
| 50 | + for expr in exprs { maybe_copy(cx, expr); } |
| 51 | + } |
| 52 | + expr_bind(_, args) { |
| 53 | + for a in args { alt a { some(ex) { maybe_copy(cx, ex); } _ {} } } |
| 54 | + } |
| 55 | + // FIXME check for by-copy args |
| 56 | + expr_call(_f, _args, _) { |
| 57 | + |
| 58 | + } |
| 59 | + // FIXME: generic instantiation |
| 60 | + expr_path(_) {} |
| 61 | + expr_fn({proto: proto_shared(_), _}) { |
| 62 | + for free in *freevars::get_freevars(cx.tcx, e.id) { |
| 63 | + let id = ast_util::def_id_of_def(free).node; |
| 64 | + let ty = ty::node_id_to_type(cx.tcx, id); |
| 65 | + check_copy(cx, ty, e.span); |
| 66 | + } |
| 67 | + } |
| 68 | + expr_ternary(_, a, b) { maybe_copy(cx, a); maybe_copy(cx, b); } |
| 69 | + _ { } |
| 70 | + } |
| 71 | + visit::visit_expr(e, cx, v); |
| 72 | +} |
| 73 | + |
| 74 | +fn check_stmt(stmt: @stmt, cx: ctx, v: visit::vt<ctx>) { |
| 75 | + alt stmt.node { |
| 76 | + stmt_decl(@{node: decl_local(locals), _}, _) { |
| 77 | + for (_, local) in locals { |
| 78 | + alt local.node.init { |
| 79 | + some({op: init_assign., expr}) { maybe_copy(cx, expr); } |
| 80 | + _ {} |
| 81 | + } |
| 82 | + } |
| 83 | + } |
| 84 | + _ {} |
| 85 | + } |
| 86 | + visit::visit_stmt(stmt, cx, v); |
| 87 | +} |
| 88 | + |
| 89 | +fn visit_fn(f: _fn, tps: [ty_param], sp: span, ident: fn_ident, |
| 90 | + id: node_id, cx: ctx, v: visit::vt<ctx>) { |
| 91 | + let old_ret = cx.ret_by_ref; |
| 92 | + cx.ret_by_ref = ast_util::ret_by_ref(f.decl.cf); |
| 93 | + visit::visit_fn(f, tps, sp, ident, id, cx, v); |
| 94 | + cx.ret_by_ref = old_ret; |
| 95 | +} |
| 96 | + |
| 97 | +fn maybe_copy(cx: ctx, ex: @expr) { |
| 98 | + check_copy_ex(cx, ex, true); |
| 99 | +} |
| 100 | + |
| 101 | +fn check_copy_ex(cx: ctx, ex: @expr, _warn: bool) { |
| 102 | + if ty::expr_is_lval(cx.tcx, ex) { |
| 103 | + let ty = ty::expr_ty(cx.tcx, ex); |
| 104 | + check_copy(cx, ty, ex.span); |
| 105 | + // FIXME turn this on again once vector types are no longer unique. |
| 106 | + // Right now, it is too annoying to be useful. |
| 107 | + /* if warn && ty::type_is_unique(cx.tcx, ty) { |
| 108 | + cx.tcx.sess.span_warn(ex.span, "copying a unique value"); |
| 109 | + }*/ |
| 110 | + } |
| 111 | +} |
| 112 | + |
| 113 | +fn check_copy(cx: ctx, ty: ty::t, sp: span) { |
| 114 | + if ty::type_kind(cx.tcx, ty) == kind_noncopyable { |
| 115 | + cx.tcx.sess.span_err(sp, "copying a noncopyable value"); |
| 116 | + } |
| 117 | +} |
| 118 | + |
| 119 | + |
1 | 120 | /*
|
2 | 121 | * Kinds are types of type.
|
3 | 122 | *
|
|
84 | 203 | *
|
85 | 204 | */
|
86 | 205 |
|
87 |
| -import syntax::ast; |
88 |
| -import ast::{kind, kind_sendable, kind_copyable, kind_noncopyable}; |
89 |
| - |
90 |
| -fn kind_lteq(a: kind, b: kind) -> bool { |
91 |
| - alt a { |
92 |
| - kind_noncopyable. { true } |
93 |
| - kind_copyable. { b != kind_noncopyable } |
94 |
| - kind_sendable. { b == kind_sendable } |
95 |
| - } |
96 |
| -} |
97 |
| - |
98 |
| -fn lower_kind(a: kind, b: kind) -> kind { |
99 |
| - if kind_lteq(a, b) { a } else { b } |
100 |
| -} |
101 |
| - |
102 |
| -fn kind_to_str(k: kind) -> str { |
103 |
| - alt k { |
104 |
| - ast::kind_sendable. { "sendable" } |
105 |
| - ast::kind_copyable. { "copyable" } |
106 |
| - ast::kind_noncopyable. { "noncopyable" } |
107 |
| - } |
108 |
| -} |
109 | 206 | /*
|
110 | 207 | fn type_and_kind(tcx: ty::ctxt, e: @ast::expr) ->
|
111 | 208 | {ty: ty::t, kind: ast::kind} {
|
@@ -296,15 +393,6 @@ fn check_stmt(tcx: ty::ctxt, stmt: @ast::stmt) {
|
296 | 393 | }
|
297 | 394 | }
|
298 | 395 | */
|
299 |
| -fn check_crate(_tcx: ty::ctxt, _crate: @ast::crate) { |
300 |
| - // FIXME stubbed out |
301 |
| -/* let visit = |
302 |
| - visit::mk_simple_visitor(@{visit_expr: bind check_expr(tcx, _), |
303 |
| - visit_stmt: bind check_stmt(tcx, _) |
304 |
| - with *visit::default_simple_visitor()}); |
305 |
| - visit::visit_crate(*crate, (), visit); |
306 |
| - tcx.sess.abort_if_errors();*/ |
307 |
| -} |
308 | 396 |
|
309 | 397 | //
|
310 | 398 | // Local Variables:
|
|
0 commit comments