Skip to content

Commit f34833a

Browse files
committed
librustc: Make a.b() always a method call. r=nmatsakis
1 parent 54ae377 commit f34833a

File tree

24 files changed

+413
-97
lines changed

24 files changed

+413
-97
lines changed

src/libcore/io.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1047,7 +1047,7 @@ pub mod fsync {
10471047
option::None => (),
10481048
option::Some(level) => {
10491049
// fail hard if not succesful
1050-
assert(self.arg.fsync_fn(self.arg.val, level) != -1);
1050+
assert((self.arg.fsync_fn)(self.arg.val, level) != -1);
10511051
}
10521052
}
10531053
}

src/librustc/middle/borrowck/check_loans.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -646,6 +646,9 @@ fn check_loans_in_expr(expr: @ast::expr,
646646
ast::expr_call(f, args, _) => {
647647
self.check_call(expr, Some(f), f.id, f.span, args);
648648
}
649+
ast::expr_method_call(_, _, _, args, _) => {
650+
self.check_call(expr, None, expr.callee_id, expr.span, args);
651+
}
649652
ast::expr_index(_, rval) |
650653
ast::expr_binary(_, _, rval)
651654
if self.bccx.method_map.contains_key(expr.id) => {

src/librustc/middle/borrowck/gather_loans.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,38 @@ fn req_loans_in_expr(ex: @ast::expr,
125125
visit::visit_expr(ex, self, vt);
126126
}
127127

128+
ast::expr_method_call(rcvr, _, _, args, _) => {
129+
let arg_tys = ty::ty_fn_args(ty::node_id_to_type(self.tcx(),
130+
ex.callee_id));
131+
let scope_r = ty::re_scope(ex.id);
132+
for vec::each2(args, arg_tys) |arg, arg_ty| {
133+
match ty::resolved_mode(self.tcx(), arg_ty.mode) {
134+
ast::by_ref => {
135+
let arg_cmt = self.bccx.cat_expr(*arg);
136+
self.guarantee_valid(arg_cmt, m_imm, scope_r);
137+
}
138+
ast::by_val | ast::by_move | ast::by_copy => {}
139+
}
140+
}
141+
142+
match self.bccx.method_map.find(ex.id) {
143+
Some(method_map_entry) => {
144+
match method_map_entry.explicit_self {
145+
ast::sty_by_ref => {
146+
let rcvr_cmt = self.bccx.cat_expr(rcvr);
147+
self.guarantee_valid(rcvr_cmt, m_imm, scope_r);
148+
}
149+
_ => {} // Nothing to do.
150+
}
151+
}
152+
None => {
153+
self.tcx().sess.span_bug(ex.span, ~"no method map entry");
154+
}
155+
}
156+
157+
visit::visit_expr(ex, self, vt);
158+
}
159+
128160
ast::expr_match(ex_v, arms) => {
129161
let cmt = self.bccx.cat_expr(ex_v);
130162
for arms.each |arm| {

src/librustc/middle/kind.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,18 @@ fn check_expr(e: @expr, cx: ctx, v: visit::vt<ctx>) {
339339
}
340340
}
341341
}
342+
expr_method_call(_, _, _, args, _) => {
343+
for ty::ty_fn_args(ty::node_id_to_type(cx.tcx, e.callee_id)).eachi
344+
|i, arg_t| {
345+
match ty::arg_mode(cx.tcx, *arg_t) {
346+
by_copy => maybe_copy(cx, args[i],
347+
Some(("function arguments must be copyable",
348+
"try changing the function to take a \
349+
reference instead"))),
350+
by_ref | by_val | by_move => ()
351+
}
352+
}
353+
}
342354
expr_field(lhs, _, _) => {
343355
// If this is a method call with a by-val argument, we need
344356
// to check the copy

src/librustc/middle/liveness.rs

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -550,8 +550,8 @@ fn visit_expr(expr: @expr, &&self: @IrMaps, vt: vt<@IrMaps>) {
550550

551551
// otherwise, live nodes are not required:
552552
expr_index(*) | expr_field(*) | expr_vstore(*) |
553-
expr_vec(*) | expr_rec(*) | expr_call(*) | expr_tup(*) |
554-
expr_log(*) | expr_binary(*) |
553+
expr_vec(*) | expr_rec(*) | expr_call(*) | expr_method_call(*) |
554+
expr_tup(*) | expr_log(*) | expr_binary(*) |
555555
expr_assert(*) | expr_addr_of(*) | expr_copy(*) |
556556
expr_loop_body(*) | expr_do_body(*) | expr_cast(*) |
557557
expr_unary(*) | expr_fail(*) |
@@ -1237,6 +1237,17 @@ impl Liveness {
12371237
self.propagate_through_expr(f, succ)
12381238
}
12391239

1240+
expr_method_call(rcvr, _, _, args, _) => {
1241+
// calling a method with bot return type means that the method
1242+
// will fail, and hence the successors can be ignored
1243+
let t_ret = ty::ty_fn_ret(ty::node_id_to_type(self.tcx,
1244+
expr.callee_id));
1245+
let succ = if ty::type_is_bot(t_ret) {self.s.exit_ln}
1246+
else {succ};
1247+
let succ = self.propagate_through_exprs(args, succ);
1248+
self.propagate_through_expr(rcvr, succ)
1249+
}
1250+
12401251
expr_tup(exprs) => {
12411252
self.propagate_through_exprs(exprs, succ)
12421253
}
@@ -1486,6 +1497,26 @@ fn check_arm(arm: arm, &&self: @Liveness, vt: vt<@Liveness>) {
14861497
visit::visit_arm(arm, self, vt);
14871498
}
14881499

1500+
fn check_call(args: &[@expr],
1501+
targs: &[ty::arg],
1502+
&&self: @Liveness) {
1503+
for vec::each2(args, targs) |arg_expr, arg_ty| {
1504+
match ty::resolved_mode(self.tcx, arg_ty.mode) {
1505+
by_val | by_copy | by_ref => {}
1506+
by_move => {
1507+
if ty::expr_is_lval(self.tcx, self.ir.method_map, *arg_expr) {
1508+
// Probably a bad error message (what's an rvalue?)
1509+
// but I can't think of anything better
1510+
self.tcx.sess.span_err(arg_expr.span,
1511+
fmt!("move mode argument must be an rvalue: try (move \
1512+
%s) instead",
1513+
expr_to_str(*arg_expr, self.tcx.sess.intr())));
1514+
}
1515+
}
1516+
}
1517+
}
1518+
}
1519+
14891520
fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) {
14901521
match expr.node {
14911522
expr_path(_) => {
@@ -1531,23 +1562,14 @@ fn check_expr(expr: @expr, &&self: @Liveness, vt: vt<@Liveness>) {
15311562

15321563
expr_call(f, args, _) => {
15331564
let targs = ty::ty_fn_args(ty::expr_ty(self.tcx, f));
1534-
for vec::each2(args, targs) |arg_expr, arg_ty| {
1535-
match ty::resolved_mode(self.tcx, arg_ty.mode) {
1536-
by_val | by_copy | by_ref => {}
1537-
by_move => {
1538-
if ty::expr_is_lval(self.tcx, self.ir.method_map,
1539-
*arg_expr) {
1540-
// Probably a bad error message (what's an rvalue?)
1541-
// but I can't think of anything better
1542-
self.tcx.sess.span_err(arg_expr.span,
1543-
fmt!("Move mode argument must be an rvalue: try \
1544-
(move %s) instead", expr_to_str(*arg_expr,
1545-
self.tcx.sess.intr())));
1546-
}
1547-
}
1548-
}
1549-
}
1565+
check_call(args, targs, self);
1566+
visit::visit_expr(expr, self, vt);
1567+
}
15501568

1569+
expr_method_call(_, _, _, args, _) => {
1570+
let targs = ty::ty_fn_args(ty::node_id_to_type(self.tcx,
1571+
expr.callee_id));
1572+
check_call(args, targs, self);
15511573
visit::visit_expr(expr, self, vt);
15521574
}
15531575

src/librustc/middle/mem_categorization.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -530,7 +530,8 @@ impl &mem_categorization_ctxt {
530530
ast::expr_swap(*) | ast::expr_assign(*) |
531531
ast::expr_assign_op(*) | ast::expr_fn(*) | ast::expr_fn_block(*) |
532532
ast::expr_assert(*) | ast::expr_ret(*) |
533-
ast::expr_loop_body(*) | ast::expr_do_body(*) | ast::expr_unary(*) |
533+
ast::expr_loop_body(*) | ast::expr_do_body(*) |
534+
ast::expr_unary(*) | ast::expr_method_call(*) |
534535
ast::expr_copy(*) | ast::expr_cast(*) | ast::expr_fail(*) |
535536
ast::expr_vstore(*) | ast::expr_vec(*) | ast::expr_tup(*) |
536537
ast::expr_if(*) | ast::expr_log(*) |

src/librustc/middle/region.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ fn resolve_expr(expr: @ast::expr, cx: ctxt, visitor: visit::vt<ctxt>) {
258258
// FIXME #3387
259259
// ast::expr_index(*) | ast::expr_binary(*) |
260260
// ast::expr_unary(*) |
261-
ast::expr_call(*) => {
261+
ast::expr_call(*) | ast::expr_method_call(*) => {
262262
debug!("node %d: %s", expr.id, pprust::expr_to_str(expr,
263263
cx.sess.intr()));
264264
new_cx.parent = Some(expr.id);

src/librustc/middle/resolve.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,11 @@ use syntax::ast::{def_foreign_mod, def_id, def_label, def_local, def_mod};
1616
use syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param};
1717
use syntax::ast::{def_typaram_binder, def_static_method};
1818
use syntax::ast::{def_upvar, def_use, def_variant, expr, expr_assign_op};
19-
use syntax::ast::{expr_binary, expr_cast, expr_field, expr_fn};
20-
use syntax::ast::{expr_fn_block, expr_index, expr_path};
19+
use syntax::ast::{expr_binary, expr_break, expr_cast, expr_field, expr_fn};
20+
use syntax::ast::{expr_fn_block, expr_index, expr_method_call, expr_path};
2121
use syntax::ast::{def_prim_ty, def_region, def_self, def_ty, def_ty_param};
2222
use syntax::ast::{def_upvar, def_use, def_variant, div, eq};
2323
use syntax::ast::{enum_variant_kind, expr, expr_again, expr_assign_op};
24-
use syntax::ast::{expr_binary, expr_break, expr_cast, expr_field, expr_fn};
2524
use syntax::ast::{expr_fn_block, expr_index, expr_loop};
2625
use syntax::ast::{expr_path, expr_struct, expr_unary, fn_decl};
2726
use syntax::ast::{foreign_item, foreign_item_const, foreign_item_fn, ge};
@@ -4971,6 +4970,10 @@ impl Resolver {
49714970
let traits = self.search_for_traits_containing_method(ident);
49724971
self.trait_map.insert(expr.id, traits);
49734972
}
4973+
expr_method_call(_, ident, _, _, _) => {
4974+
let traits = self.search_for_traits_containing_method(ident);
4975+
self.trait_map.insert(expr.id, traits);
4976+
}
49744977
expr_binary(add, _, _) | expr_assign_op(add, _, _) => {
49754978
self.add_fixed_trait_for_expr(expr.id,
49764979
self.lang_items.add_trait);

src/librustc/middle/trans/callee.rs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,38 @@ fn trans_call(in_cx: block,
292292
|cx| trans(cx, f), args, dest, DontAutorefArg)
293293
}
294294

295+
fn trans_method_call(in_cx: block,
296+
call_ex: @ast::expr,
297+
rcvr: @ast::expr,
298+
args: CallArgs,
299+
dest: expr::Dest)
300+
-> block {
301+
let _icx = in_cx.insn_ctxt("trans_method_call");
302+
trans_call_inner(
303+
in_cx,
304+
call_ex.info(),
305+
node_id_type(in_cx, call_ex.callee_id),
306+
expr_ty(in_cx, call_ex),
307+
|cx| {
308+
match cx.ccx().maps.method_map.find(call_ex.id) {
309+
Some(origin) => {
310+
meth::trans_method_callee(cx,
311+
call_ex.callee_id,
312+
rcvr,
313+
origin)
314+
}
315+
None => {
316+
cx.tcx().sess.span_bug(call_ex.span,
317+
~"method call expr wasn't in \
318+
method map")
319+
}
320+
}
321+
},
322+
args,
323+
dest,
324+
DontAutorefArg)
325+
}
326+
295327
fn trans_rtcall(bcx: block, name: ~str, args: ~[ValueRef], dest: expr::Dest)
296328
-> block
297329
{

src/librustc/middle/trans/expr.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,13 @@ fn trans_rvalue_dps_unadjusted(bcx: block, expr: @ast::expr,
592592
return callee::trans_call(
593593
bcx, expr, f, callee::ArgExprs(args), expr.id, dest);
594594
}
595+
ast::expr_method_call(rcvr, _, _, args, _) => {
596+
return callee::trans_method_call(bcx,
597+
expr,
598+
rcvr,
599+
callee::ArgExprs(args),
600+
dest);
601+
}
595602
ast::expr_binary(_, lhs, rhs) => {
596603
// if not overloaded, would be RvalueDatumExpr
597604
return trans_overloaded_op(bcx, expr, lhs, ~[rhs], dest,

src/librustc/middle/trans/reachable.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,18 @@ fn traverse_inline_body(cx: ctx, body: blk) {
170170
_ => ()
171171
}
172172
}
173+
expr_method_call(*) => {
174+
match cx.method_map.find(e.id) {
175+
Some({origin: typeck::method_static(did), _}) => {
176+
traverse_def_id(cx, did);
177+
}
178+
Some(_) => {}
179+
None => {
180+
cx.tcx.sess.span_bug(e.span, ~"expr_method_call not in \
181+
method map");
182+
}
183+
}
184+
}
173185
_ => ()
174186
}
175187
visit::visit_expr(e, cx, v);

src/librustc/middle/trans/type_use.rs

Lines changed: 35 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,25 @@ fn node_type_needs(cx: ctx, use_: uint, id: node_id) {
173173
type_needs(cx, use_, ty::node_id_to_type(cx.ccx.tcx, id));
174174
}
175175

176+
fn mark_for_method_call(cx: ctx, e_id: node_id) {
177+
do option::iter(&cx.ccx.maps.method_map.find(e_id)) |mth| {
178+
match mth.origin {
179+
typeck::method_static(did) => {
180+
do cx.ccx.tcx.node_type_substs.find(e_id).iter |ts| {
181+
let type_uses = type_uses_for(cx.ccx, did, ts.len());
182+
for vec::each2(type_uses, *ts) |uses, subst| {
183+
type_needs(cx, *uses, *subst)
184+
}
185+
}
186+
}
187+
typeck::method_param({param_num: param, _}) => {
188+
cx.uses[param] |= use_tydesc;
189+
}
190+
typeck::method_trait(*) | typeck::method_self(*) => (),
191+
}
192+
}
193+
}
194+
176195
fn mark_for_expr(cx: ctx, e: @expr) {
177196
match e.node {
178197
expr_vstore(_, _) |
@@ -231,23 +250,7 @@ fn mark_for_expr(cx: ctx, e: @expr) {
231250
// the chosen field.
232251
let base_ty = ty::node_id_to_type(cx.ccx.tcx, base.id);
233252
type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty));
234-
235-
do option::iter(&cx.ccx.maps.method_map.find(e.id)) |mth| {
236-
match mth.origin {
237-
typeck::method_static(did) => {
238-
do cx.ccx.tcx.node_type_substs.find(e.id).iter |ts| {
239-
let type_uses = type_uses_for(cx.ccx, did, ts.len());
240-
for vec::each2(type_uses, *ts) |uses, subst| {
241-
type_needs(cx, *uses, *subst)
242-
}
243-
}
244-
}
245-
typeck::method_param({param_num: param, _}) => {
246-
cx.uses[param] |= use_tydesc;
247-
}
248-
typeck::method_trait(*) | typeck::method_self(*) => (),
249-
}
250-
}
253+
mark_for_method_call(cx, e.id);
251254
}
252255
expr_log(_, _, val) => {
253256
node_type_needs(cx, use_tydesc, val.id);
@@ -264,6 +267,21 @@ fn mark_for_expr(cx: ctx, e: @expr) {
264267
}
265268
}
266269
}
270+
expr_method_call(rcvr, _, _, _, _) => {
271+
let base_ty = ty::node_id_to_type(cx.ccx.tcx, rcvr.id);
272+
type_needs(cx, use_repr, ty::type_autoderef(cx.ccx.tcx, base_ty));
273+
274+
for ty::ty_fn_args(ty::node_id_to_type(cx.ccx.tcx,
275+
e.callee_id)).each |a| {
276+
match a.mode {
277+
expl(by_move) | expl(by_copy) | expl(by_val) => {
278+
type_needs(cx, use_repr, a.ty);
279+
}
280+
_ => ()
281+
}
282+
}
283+
mark_for_method_call(cx, e.id);
284+
}
267285
expr_paren(e) => mark_for_expr(cx, e),
268286
expr_match(*) | expr_block(_) | expr_if(*) |
269287
expr_while(*) | expr_fail(_) | expr_break(_) | expr_again(_) |

src/librustc/middle/ty.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3053,6 +3053,7 @@ fn expr_kind(tcx: ctxt,
30533053
}
30543054

30553055
ast::expr_call(*) |
3056+
ast::expr_method_call(*) |
30563057
ast::expr_rec(*) |
30573058
ast::expr_struct(*) |
30583059
ast::expr_tup(*) |

0 commit comments

Comments
 (0)