Skip to content

Commit

Permalink
librustc: Make a.b() always a method call. r=nmatsakis
Browse files Browse the repository at this point in the history
  • Loading branch information
pcwalton committed Dec 1, 2012
1 parent 54ae377 commit f34833a
Show file tree
Hide file tree
Showing 24 changed files with 413 additions and 97 deletions.
2 changes: 1 addition & 1 deletion src/libcore/io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1047,7 +1047,7 @@ pub mod fsync {
option::None => (),
option::Some(level) => {
// fail hard if not succesful
assert(self.arg.fsync_fn(self.arg.val, level) != -1);
assert((self.arg.fsync_fn)(self.arg.val, level) != -1);
}
}
}
Expand Down
3 changes: 3 additions & 0 deletions src/librustc/middle/borrowck/check_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,9 @@ fn check_loans_in_expr(expr: @ast::expr,
ast::expr_call(f, args, _) => {
self.check_call(expr, Some(f), f.id, f.span, args);
}
ast::expr_method_call(_, _, _, args, _) => {
self.check_call(expr, None, expr.callee_id, expr.span, args);
}
ast::expr_index(_, rval) |
ast::expr_binary(_, _, rval)
if self.bccx.method_map.contains_key(expr.id) => {
Expand Down
32 changes: 32 additions & 0 deletions src/librustc/middle/borrowck/gather_loans.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,38 @@ fn req_loans_in_expr(ex: @ast::expr,
visit::visit_expr(ex, self, vt);
}

ast::expr_method_call(rcvr, _, _, args, _) => {
let arg_tys = ty::ty_fn_args(ty::node_id_to_type(self.tcx(),
ex.callee_id));
let scope_r = ty::re_scope(ex.id);
for vec::each2(args, arg_tys) |arg, arg_ty| {
match ty::resolved_mode(self.tcx(), arg_ty.mode) {
ast::by_ref => {
let arg_cmt = self.bccx.cat_expr(*arg);
self.guarantee_valid(arg_cmt, m_imm, scope_r);
}
ast::by_val | ast::by_move | ast::by_copy => {}
}
}

match self.bccx.method_map.find(ex.id) {
Some(method_map_entry) => {
match method_map_entry.explicit_self {
ast::sty_by_ref => {
let rcvr_cmt = self.bccx.cat_expr(rcvr);
self.guarantee_valid(rcvr_cmt, m_imm, scope_r);
}
_ => {} // Nothing to do.
}
}
None => {
self.tcx().sess.span_bug(ex.span, ~"no method map entry");
}
}

visit::visit_expr(ex, self, vt);
}

ast::expr_match(ex_v, arms) => {
let cmt = self.bccx.cat_expr(ex_v);
for arms.each |arm| {
Expand Down
12 changes: 12 additions & 0 deletions src/librustc/middle/kind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -339,6 +339,18 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
}
}
}
expr_method_call(_, _, _, args, _) => {
for ty::ty_fn_args(ty::node_id_to_type(cx.tcx, e.callee_id)).eachi
|i, arg_t| {
match ty::arg_mode(cx.tcx, *arg_t) {
by_copy => maybe_copy(cx, args[i],
Some(("function arguments must be copyable",
"try changing the function to take a \
reference instead"))),
by_ref | by_val | by_move => ()
}
}
}
expr_field(lhs, _, _) => {
// If this is a method call with a by-val argument, we need
// to check the copy
Expand Down
58 changes: 40 additions & 18 deletions src/librustc/middle/liveness.rs
Original file line number Diff line number Diff line change
Expand Up @@ -550,8 +550,8 @@ fn visit_expr(expr: @expr, &&self: @IrMaps, vt: vt<@IrMaps>) {

// otherwise, live nodes are not required:
expr_index(*) | expr_field(*) | expr_vstore(*) |
expr_vec(*) | expr_rec(*) | expr_call(*) | expr_tup(*) |
expr_log(*) | expr_binary(*) |
expr_vec(*) | expr_rec(*) | expr_call(*) | expr_method_call(*) |
expr_tup(*) | expr_log(*) | expr_binary(*) |
expr_assert(*) | expr_addr_of(*) | expr_copy(*) |
expr_loop_body(*) | expr_do_body(*) | expr_cast(*) |
expr_unary(*) | expr_fail(*) |
Expand Down Expand Up @@ -1237,6 +1237,17 @@ impl Liveness {
self.propagate_through_expr(f, succ)
}

expr_method_call(rcvr, _, _, args, _) => {
// calling a method with bot return type means that the method
// will fail, and hence the successors can be ignored
let t_ret = ty::ty_fn_ret(ty::node_id_to_type(self.tcx,
expr.callee_id));
let succ = if ty::type_is_bot(t_ret) {self.s.exit_ln}
else {succ};
let succ = self.propagate_through_exprs(args, succ);
self.propagate_through_expr(rcvr, succ)
}

expr_tup(exprs) => {
self.propagate_through_exprs(exprs, succ)
}
Expand Down Expand Up @@ -1486,6 +1497,26 @@ fn check_arm(arm: arm, &&self: @Liveness, vt: vt<@Liveness>) {
visit::visit_arm(arm, self, vt);
}

fn check_call(args: &[@expr],
targs: &[ty::arg],
&&self: @Liveness) {
for vec::each2(args, targs) |arg_expr, arg_ty| {
match ty::resolved_mode(self.tcx, arg_ty.mode) {
by_val | by_copy | by_ref => {}
by_move => {
if ty::expr_is_lval(self.tcx, self.ir.method_map, *arg_expr) {
// Probably a bad error message (what's an rvalue?)
// but I can't think of anything better
self.tcx.sess.span_err(arg_expr.span,
fmt!("move mode argument must be an rvalue: try (move \
%s) instead",
expr_to_str(*arg_expr, self.tcx.sess.intr())));
}
}
}
}
}

fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) {
match expr.node {
expr_path(_) => {
Expand Down Expand Up @@ -1531,23 +1562,14 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) {

expr_call(f, args, _) => {
let targs = ty::ty_fn_args(ty::expr_ty(self.tcx, f));
for vec::each2(args, targs) |arg_expr, arg_ty| {
match ty::resolved_mode(self.tcx, arg_ty.mode) {
by_val | by_copy | by_ref => {}
by_move => {
if ty::expr_is_lval(self.tcx, self.ir.method_map,
*arg_expr) {
// Probably a bad error message (what's an rvalue?)
// but I can't think of anything better
self.tcx.sess.span_err(arg_expr.span,
fmt!("Move mode argument must be an rvalue: try \
(move %s) instead", expr_to_str(*arg_expr,
self.tcx.sess.intr())));
}
}
}
}
check_call(args, targs, self);
visit::visit_expr(expr, self, vt);
}

expr_method_call(_, _, _, args, _) => {
let targs = ty::ty_fn_args(ty::node_id_to_type(self.tcx,
expr.callee_id));
check_call(args, targs, self);
visit::visit_expr(expr, self, vt);
}

Expand Down
3 changes: 2 additions & 1 deletion src/librustc/middle/mem_categorization.rs
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,8 @@ impl &mem_categorization_ctxt {
ast::expr_swap(*) | ast::expr_assign(*) |
ast::expr_assign_op(*) | ast::expr_fn(*) | ast::expr_fn_block(*) |
ast::expr_assert(*) | ast::expr_ret(*) |
ast::expr_loop_body(*) | ast::expr_do_body(*) | ast::expr_unary(*) |
ast::expr_loop_body(*) | ast::expr_do_body(*) |
ast::expr_unary(*) | ast::expr_method_call(*) |
ast::expr_copy(*) | ast::expr_cast(*) | ast::expr_fail(*) |
ast::expr_vstore(*) | ast::expr_vec(*) | ast::expr_tup(*) |
ast::expr_if(*) | ast::expr_log(*) |
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/region.rs
Original file line number Diff line number Diff line change
Expand Up @@ -258,7 +258,7 @@ fn resolve_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt<ctxt>) {
// FIXME #3387
// ast::expr_index(*) | ast::expr_binary(*) |
// ast::expr_unary(*) |
ast::expr_call(*) => {
ast::expr_call(*) | ast::expr_method_call(*) => {
debug!("node %d: %s", expr.id, pprust::expr_to_str(expr,
cx.sess.intr()));
new_cx.parent = Some(expr.id);
Expand Down
9 changes: 6 additions & 3 deletions src/librustc/middle/resolve.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,11 @@ use syntax::ast::{def_foreign_mod, def_id, def_label, def_local, def_mod};
use syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param};
use syntax::ast::{def_typaram_binder, def_static_method};
use syntax::ast::{def_upvar, def_use, def_variant, expr, expr_assign_op};
use syntax::ast::{expr_binary, expr_cast, expr_field, expr_fn};
use syntax::ast::{expr_fn_block, expr_index, expr_path};
use syntax::ast::{expr_binary, expr_break, expr_cast, expr_field, expr_fn};
use syntax::ast::{expr_fn_block, expr_index, expr_method_call, expr_path};
use syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param};
use syntax::ast::{def_upvar, def_use, def_variant, div, eq};
use syntax::ast::{enum_variant_kind, expr, expr_again, expr_assign_op};
use syntax::ast::{expr_binary, expr_break, expr_cast, expr_field, expr_fn};
use syntax::ast::{expr_fn_block, expr_index, expr_loop};
use syntax::ast::{expr_path, expr_struct, expr_unary, fn_decl};
use syntax::ast::{foreign_item, foreign_item_const, foreign_item_fn, ge};
Expand Down Expand Up @@ -4971,6 +4970,10 @@ impl Resolver {
let traits = self.search_for_traits_containing_method(ident);
self.trait_map.insert(expr.id, traits);
}
expr_method_call(_, ident, _, _, _) => {
let traits = self.search_for_traits_containing_method(ident);
self.trait_map.insert(expr.id, traits);
}
expr_binary(add, _, _) | expr_assign_op(add, _, _) => {
self.add_fixed_trait_for_expr(expr.id,
self.lang_items.add_trait);
Expand Down
32 changes: 32 additions & 0 deletions src/librustc/middle/trans/callee.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,38 @@ fn trans_call(in_cx: block,
|cx| trans(cx, f), args, dest, DontAutorefArg)
}

fn trans_method_call(in_cx: block,
call_ex: @ast::expr,
rcvr: @ast::expr,
args: CallArgs,
dest: expr::Dest)
-> block {
let _icx = in_cx.insn_ctxt("trans_method_call");
trans_call_inner(
in_cx,
call_ex.info(),
node_id_type(in_cx, call_ex.callee_id),
expr_ty(in_cx, call_ex),
|cx| {
match cx.ccx().maps.method_map.find(call_ex.id) {
Some(origin) => {
meth::trans_method_callee(cx,
call_ex.callee_id,
rcvr,
origin)
}
None => {
cx.tcx().sess.span_bug(call_ex.span,
~"method call expr wasn't in \
method map")
}
}
},
args,
dest,
DontAutorefArg)
}

fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef], dest: expr::Dest)
-> block
{
Expand Down
7 changes: 7 additions & 0 deletions src/librustc/middle/trans/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -592,6 +592,13 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
return callee::trans_call(
bcx, expr, f, callee::ArgExprs(args), expr.id, dest);
}
ast::expr_method_call(rcvr, _, _, args, _) => {
return callee::trans_method_call(bcx,
expr,
rcvr,
callee::ArgExprs(args),
dest);
}
ast::expr_binary(_, lhs, rhs) => {
// if not overloaded, would be RvalueDatumExpr
return trans_overloaded_op(bcx, expr, lhs, ~[rhs], dest,
Expand Down
12 changes: 12 additions & 0 deletions src/librustc/middle/trans/reachable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,18 @@ fn traverse_inline_body(cx: ctx, body: blk) {
_ => ()
}
}
expr_method_call(*) => {
match cx.method_map.find(e.id) {
Some({origin: typeck::method_static(did), _}) => {
traverse_def_id(cx, did);
}
Some(_) => {}
None => {
cx.tcx.sess.span_bug(e.span, ~"expr_method_call not in \
method map");
}
}
}
_ => ()
}
visit::visit_expr(e, cx, v);
Expand Down
52 changes: 35 additions & 17 deletions src/librustc/middle/trans/type_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,25 @@ fn node_type_needs(cx: ctx, use_: uint, id: node_id) {
type_needs(cx, use_, ty::node_id_to_type(cx.ccx.tcx, id));
}

fn mark_for_method_call(cx: ctx, e_id: node_id) {
do option::iter(&cx.ccx.maps.method_map.find(e_id)) |mth| {
match mth.origin {
typeck::method_static(did) => {
do cx.ccx.tcx.node_type_substs.find(e_id).iter |ts| {
let type_uses = type_uses_for(cx.ccx, did, ts.len());
for vec::each2(type_uses, *ts) |uses, subst| {
type_needs(cx, *uses, *subst)
}
}
}
typeck::method_param({param_num: param, _}) => {
cx.uses[param] |= use_tydesc;
}
typeck::method_trait(*) | typeck::method_self(*) => (),
}
}
}

fn mark_for_expr(cx: ctx, e: @expr) {
match e.node {
expr_vstore(_, _) |
Expand Down Expand Up @@ -231,23 +250,7 @@ fn mark_for_expr(cx: ctx, e: @expr) {
// the chosen field.
let base_ty = ty::node_id_to_type(cx.ccx.tcx, base.id);
type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty));

do option::iter(&cx.ccx.maps.method_map.find(e.id)) |mth| {
match mth.origin {
typeck::method_static(did) => {
do cx.ccx.tcx.node_type_substs.find(e.id).iter |ts| {
let type_uses = type_uses_for(cx.ccx, did, ts.len());
for vec::each2(type_uses, *ts) |uses, subst| {
type_needs(cx, *uses, *subst)
}
}
}
typeck::method_param({param_num: param, _}) => {
cx.uses[param] |= use_tydesc;
}
typeck::method_trait(*) | typeck::method_self(*) => (),
}
}
mark_for_method_call(cx, e.id);
}
expr_log(_, _, val) => {
node_type_needs(cx, use_tydesc, val.id);
Expand All @@ -264,6 +267,21 @@ fn mark_for_expr(cx: ctx, e: @expr) {
}
}
}
expr_method_call(rcvr, _, _, _, _) => {
let base_ty = ty::node_id_to_type(cx.ccx.tcx, rcvr.id);
type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty));

for ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx,
e.callee_id)).each |a| {
match a.mode {
expl(by_move) | expl(by_copy) | expl(by_val) => {
type_needs(cx, use_repr, a.ty);
}
_ => ()
}
}
mark_for_method_call(cx, e.id);
}
expr_paren(e) => mark_for_expr(cx, e),
expr_match(*) | expr_block(_) | expr_if(*) |
expr_while(*) | expr_fail(_) | expr_break(_) | expr_again(_) |
Expand Down
1 change: 1 addition & 0 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3053,6 +3053,7 @@ fn expr_kind(tcx: ctxt,
}

ast::expr_call(*) |
ast::expr_method_call(*) |
ast::expr_rec(*) |
ast::expr_struct(*) |
ast::expr_tup(*) |
Expand Down
Loading

0 comments on commit f34833a

Please sign in to comment.