Skip to content

Commit 8ca4796

Browse files
committed
---
yaml --- r: 6373 b: refs/heads/master c: 17b78c4 h: refs/heads/master i: 6371: bcb7bbb v: v3
1 parent bada883 commit 8ca4796

File tree

5 files changed

+190
-127
lines changed

5 files changed

+190
-127
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
---
2-
refs/heads/master: cefff237bf36c4868f047ceb3e98646710ef7ac0
2+
refs/heads/master: 17b78c4a7a8e2a1699e8443cc88fa5f3fd224368

trunk/src/comp/middle/kind.rs

Lines changed: 119 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,122 @@
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+
1120
/*
2121
* Kinds are types of type.
3122
*
@@ -84,28 +203,6 @@
84203
*
85204
*/
86205

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-
}
109206
/*
110207
fn type_and_kind(tcx: ty::ctxt, e: @ast::expr) ->
111208
{ty: ty::t, kind: ast::kind} {
@@ -296,15 +393,6 @@ fn check_stmt(tcx: ty::ctxt, stmt: @ast::stmt) {
296393
}
297394
}
298395
*/
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-
}
308396

309397
//
310398
// Local Variables:

trunk/src/comp/middle/trans.rs

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3128,7 +3128,7 @@ fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
31283128
ast::expr_path(p) { ret trans_path(bcx, p, e.id); }
31293129
ast::expr_field(base, ident) {
31303130
// Lval means this is a record field, so not a method
3131-
if !expr_is_lval(bcx_tcx(bcx), e) {
3131+
if !ty::expr_is_lval(bcx_tcx(bcx), e) {
31323132
let of = trans_object_field(bcx, base, ident);
31333133
ret {bcx: of.bcx, val: of.mthptr, kind: owned,
31343134
env: obj_env(of.objptr), generic: none};
@@ -3149,25 +3149,6 @@ fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
31493149
ret lval_no_env(lv.bcx, lv.val, lv.kind);
31503150
}
31513151

3152-
fn expr_is_lval(tcx: ty::ctxt, e: @ast::expr) -> bool {
3153-
alt e.node {
3154-
ast::expr_path(_) | ast::expr_index(_, _) |
3155-
ast::expr_unary(ast::deref., _) { true }
3156-
ast::expr_field(base, ident) {
3157-
let basety = ty::type_autoderef(tcx, ty::expr_ty(tcx, base));
3158-
alt ty::struct(tcx, basety) {
3159-
ty::ty_obj(_) { false }
3160-
ty::ty_rec(_) { true }
3161-
}
3162-
}
3163-
ast::expr_call(f, _, _) {
3164-
let fty = ty::expr_ty(tcx, f);
3165-
ast_util::ret_by_ref(ty::ty_fn_ret_style(tcx, fty))
3166-
}
3167-
_ { false }
3168-
}
3169-
}
3170-
31713152
// Use this when you know you are compiling an lval.
31723153
// The additional bool returned indicates whether it's mem (that is
31733154
// represented as an alloca or heap, hence needs a 'load' to be used as an
@@ -4103,7 +4084,7 @@ fn trans_expr_save_in(bcx: @block_ctxt, e: @ast::expr, dest: ValueRef)
41034084
// use trans_temp_expr.
41044085
fn trans_temp_lval(bcx: @block_ctxt, e: @ast::expr) -> lval_result {
41054086
let bcx = bcx;
4106-
if expr_is_lval(bcx_tcx(bcx), e) {
4087+
if ty::expr_is_lval(bcx_tcx(bcx), e) {
41074088
ret trans_lval(bcx, e);
41084089
} else {
41094090
let tcx = bcx_tcx(bcx);
@@ -4141,7 +4122,7 @@ fn trans_temp_expr(bcx: @block_ctxt, e: @ast::expr) -> result {
41414122
// - exprs with non-immediate type never get dest=by_val
41424123
fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
41434124
let tcx = bcx_tcx(bcx);
4144-
if expr_is_lval(tcx, e) { ret lval_to_dps(bcx, e, dest); }
4125+
if ty::expr_is_lval(tcx, e) { ret lval_to_dps(bcx, e, dest); }
41454126

41464127
alt e.node {
41474128
ast::expr_if(cond, thn, els) | ast::expr_if_check(cond, thn, els) {
@@ -4176,7 +4157,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
41764157
ast::expr_fn(f) { ret trans_expr_fn(bcx, f, e.span, e.id, dest); }
41774158
ast::expr_bind(f, args) { ret trans_bind(bcx, f, args, e.id, dest); }
41784159
ast::expr_copy(a) {
4179-
if !expr_is_lval(tcx, a) { ret trans_expr(bcx, a, dest); }
4160+
if !ty::expr_is_lval(tcx, a) { ret trans_expr(bcx, a, dest); }
41804161
else { ret lval_to_dps(bcx, a, dest); }
41814162
}
41824163
ast::expr_cast(val, _) { ret trans_cast(bcx, val, e.id, dest); }
@@ -4574,7 +4555,7 @@ fn init_local(bcx: @block_ctxt, local: @ast::local) -> @block_ctxt {
45744555
alt local.node.init {
45754556
some(init) {
45764557
if init.op == ast::init_assign ||
4577-
!expr_is_lval(bcx_tcx(bcx), init.expr) {
4558+
!ty::expr_is_lval(bcx_tcx(bcx), init.expr) {
45784559
bcx = trans_expr_save_in(bcx, init.expr, llptr);
45794560
} else { // This is a move from an lval, must perform an actual move
45804561
let sub = trans_lval(bcx, init.expr);

0 commit comments

Comments
 (0)