Skip to content

Commit 907d961

Browse files
committed
auto merge of #14590 : pcwalton/rust/overloaded-call, r=nick29581
gate. This is part of unboxed closures. r? @nick29581
2 parents 0ea7aa3 + 966c734 commit 907d961

File tree

12 files changed

+701
-234
lines changed

12 files changed

+701
-234
lines changed

src/libcore/ops.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -726,6 +726,27 @@ pub trait DerefMut<Result>: Deref<Result> {
726726
fn deref_mut<'a>(&'a mut self) -> &'a mut Result;
727727
}
728728

729+
/// A version of the call operator that takes an immutable receiver.
730+
#[lang="fn"]
731+
pub trait Fn<Args,Result> {
732+
/// This is called when the call operator is used.
733+
fn call(&self, args: Args) -> Result;
734+
}
735+
736+
/// A version of the call operator that takes a mutable receiver.
737+
#[lang="fn_mut"]
738+
pub trait FnMut<Args,Result> {
739+
/// This is called when the call operator is used.
740+
fn call_mut(&mut self, args: Args) -> Result;
741+
}
742+
743+
/// A version of the call operator that takes a by-value receiver.
744+
#[lang="fn_once"]
745+
pub trait FnOnce<Args,Result> {
746+
/// This is called when the call operator is used.
747+
fn call_once(self, args: Args) -> Result;
748+
}
749+
729750
#[cfg(test)]
730751
mod bench {
731752
extern crate test;

src/librustc/front/feature_gate.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ static KNOWN_FEATURES: &'static [(&'static str, Status)] = &[
5656
("quote", Active),
5757
("linkage", Active),
5858
("struct_inherit", Active),
59+
("overloaded_calls", Active),
5960

6061
("quad_precision_float", Active),
6162

@@ -86,6 +87,7 @@ pub struct Features {
8687
pub default_type_params: Cell<bool>,
8788
pub quad_precision_float: Cell<bool>,
8889
pub issue_5723_bootstrap: Cell<bool>,
90+
pub overloaded_calls: Cell<bool>,
8991
}
9092

9193
impl Features {
@@ -94,6 +96,7 @@ impl Features {
9496
default_type_params: Cell::new(false),
9597
quad_precision_float: Cell::new(false),
9698
issue_5723_bootstrap: Cell::new(false),
99+
overloaded_calls: Cell::new(false),
97100
}
98101
}
99102
}
@@ -375,4 +378,5 @@ pub fn check_crate(sess: &Session, krate: &ast::Crate) {
375378
sess.features.default_type_params.set(cx.has_feature("default_type_params"));
376379
sess.features.quad_precision_float.set(cx.has_feature("quad_precision_float"));
377380
sess.features.issue_5723_bootstrap.set(cx.has_feature("issue_5723_bootstrap"));
381+
sess.features.overloaded_calls.set(cx.has_feature("overloaded_calls"));
378382
}

src/librustc/middle/expr_use_visitor.rs

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ use middle::def;
1919
use middle::freevars;
2020
use middle::pat_util;
2121
use middle::ty;
22+
use middle::typeck::MethodCall;
2223
use middle::typeck;
2324
use syntax::ast;
2425
use syntax::codemap::{Span};
@@ -427,10 +428,20 @@ impl<'d,'t,TYPER:mc::Typer> ExprUseVisitor<'d,'t,TYPER> {
427428
}
428429
}
429430
_ => {
430-
self.tcx().sess.span_bug(
431-
callee.span,
432-
format!("unxpected callee type {}",
433-
callee_ty.repr(self.tcx())).as_slice());
431+
match self.tcx()
432+
.method_map
433+
.borrow()
434+
.find(&MethodCall::expr(call.id)) {
435+
Some(_) => {
436+
// FIXME(#14774, pcwalton): Implement this.
437+
}
438+
None => {
439+
self.tcx().sess.span_bug(
440+
callee.span,
441+
format!("unxpected callee type {}",
442+
callee_ty.repr(self.tcx())).as_slice());
443+
}
444+
}
434445
}
435446
}
436447
}

src/librustc/middle/lang_items.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,10 @@ lets_do_this! {
240240
DerefTraitLangItem, "deref", deref_trait;
241241
DerefMutTraitLangItem, "deref_mut", deref_mut_trait;
242242

243+
FnTraitLangItem, "fn", fn_trait;
244+
FnMutTraitLangItem, "fn_mut", fn_mut_trait;
245+
FnOnceTraitLangItem, "fn_once", fn_once_trait;
246+
243247
EqTraitLangItem, "eq", eq_trait;
244248
OrdTraitLangItem, "ord", ord_trait;
245249

src/librustc/middle/liveness.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@
105105
use middle::def::*;
106106
use middle::freevars;
107107
use middle::lint::{UnusedVariable, DeadAssignment};
108+
use middle::mem_categorization::Typer;
108109
use middle::pat_util;
109110
use middle::ty;
110111
use util::nodemap::NodeMap;
@@ -1146,9 +1147,15 @@ impl<'a> Liveness<'a> {
11461147
ExprCall(f, ref args) => {
11471148
// calling a fn with bot return type means that the fn
11481149
// will fail, and hence the successors can be ignored
1149-
let t_ret = ty::ty_fn_ret(ty::expr_ty(self.ir.tcx, f));
1150-
let succ = if ty::type_is_bot(t_ret) {self.s.exit_ln}
1151-
else {succ};
1150+
let is_bot = !self.ir.tcx.is_method_call(expr.id) && {
1151+
let t_ret = ty::ty_fn_ret(ty::expr_ty(self.ir.tcx, f));
1152+
ty::type_is_bot(t_ret)
1153+
};
1154+
let succ = if is_bot {
1155+
self.s.exit_ln
1156+
} else {
1157+
succ
1158+
};
11521159
let succ = self.propagate_through_exprs(args.as_slice(), succ);
11531160
self.propagate_through_expr(f, succ)
11541161
}

src/librustc/middle/trans/expr.rs

Lines changed: 86 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ use lib;
3939
use metadata::csearch;
4040
use middle::def;
4141
use middle::lang_items::MallocFnLangItem;
42+
use middle::mem_categorization::Typer;
4243
use middle::trans::_match;
4344
use middle::trans::adt;
4445
use middle::trans::asm;
@@ -65,6 +66,7 @@ use middle::ty::{AutoBorrowObj, AutoDerefRef, AutoAddEnv, AutoObject, AutoUnsafe
6566
use middle::ty::{AutoPtr, AutoBorrowVec, AutoBorrowVecRef};
6667
use middle::ty;
6768
use middle::typeck::MethodCall;
69+
use middle::typeck;
6870
use util::common::indenter;
6971
use util::ppaux::Repr;
7072
use util::nodemap::NodeMap;
@@ -713,7 +715,20 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
713715
closure::trans_expr_fn(bcx, store, decl, body, expr.id, dest)
714716
}
715717
ast::ExprCall(f, ref args) => {
716-
callee::trans_call(bcx, expr, f, callee::ArgExprs(args.as_slice()), dest)
718+
if bcx.tcx().is_method_call(expr.id) {
719+
let callee_datum = unpack_datum!(bcx, trans(bcx, f));
720+
trans_overloaded_call(bcx,
721+
expr,
722+
callee_datum,
723+
args.as_slice(),
724+
Some(dest))
725+
} else {
726+
callee::trans_call(bcx,
727+
expr,
728+
f,
729+
callee::ArgExprs(args.as_slice()),
730+
dest)
731+
}
717732
}
718733
ast::ExprMethodCall(_, _, ref args) => {
719734
callee::trans_method_call(bcx,
@@ -1461,6 +1476,76 @@ fn trans_overloaded_op<'a, 'b>(
14611476
dest)
14621477
}
14631478

1479+
fn trans_overloaded_call<'a>(
1480+
mut bcx: &'a Block<'a>,
1481+
expr: &ast::Expr,
1482+
callee: Datum<Expr>,
1483+
args: &[@ast::Expr],
1484+
dest: Option<Dest>)
1485+
-> &'a Block<'a> {
1486+
// Evaluate and tuple the arguments.
1487+
let tuple_type = ty::mk_tup(bcx.tcx(),
1488+
args.iter()
1489+
.map(|e| expr_ty(bcx, *e))
1490+
.collect());
1491+
let repr = adt::represent_type(bcx.ccx(), tuple_type);
1492+
let numbered_fields: Vec<(uint, @ast::Expr)> =
1493+
args.iter().enumerate().map(|(i, arg)| (i, *arg)).collect();
1494+
let argument_scope = bcx.fcx.push_custom_cleanup_scope();
1495+
let tuple_datum =
1496+
unpack_datum!(bcx,
1497+
lvalue_scratch_datum(bcx,
1498+
tuple_type,
1499+
"tupled_arguments",
1500+
false,
1501+
cleanup::CustomScope(
1502+
argument_scope),
1503+
(),
1504+
|(), bcx, addr| {
1505+
trans_adt(bcx,
1506+
&*repr,
1507+
0,
1508+
numbered_fields.as_slice(),
1509+
None,
1510+
SaveIn(addr))
1511+
}));
1512+
1513+
let method_call = typeck::MethodCall::expr(expr.id);
1514+
let method_type = bcx.tcx()
1515+
.method_map
1516+
.borrow()
1517+
.get(&method_call)
1518+
.ty;
1519+
let callee_rvalue = unpack_datum!(bcx,
1520+
callee.to_rvalue_datum(bcx, "callee"));
1521+
let tuple_datum = tuple_datum.to_expr_datum();
1522+
let tuple_rvalue = unpack_datum!(bcx,
1523+
tuple_datum.to_rvalue_datum(bcx,
1524+
"tuple"));
1525+
let argument_values = [
1526+
callee_rvalue.add_clean(bcx.fcx,
1527+
cleanup::CustomScope(argument_scope)),
1528+
tuple_rvalue.add_clean(bcx.fcx, cleanup::CustomScope(argument_scope))
1529+
];
1530+
unpack_result!(bcx,
1531+
callee::trans_call_inner(bcx,
1532+
Some(expr_info(expr)),
1533+
monomorphize_type(bcx,
1534+
method_type),
1535+
|bcx, arg_cleanup_scope| {
1536+
meth::trans_method_callee(
1537+
bcx,
1538+
method_call,
1539+
None,
1540+
arg_cleanup_scope)
1541+
},
1542+
callee::ArgVals(argument_values),
1543+
dest));
1544+
1545+
bcx.fcx.pop_custom_cleanup_scope(argument_scope);
1546+
bcx
1547+
}
1548+
14641549
fn int_cast(bcx: &Block,
14651550
lldsttype: Type,
14661551
llsrctype: Type,

0 commit comments

Comments
 (0)