)
)
+/// Whether the elements of an overloaded operation are passed by value or by reference
+enum PassArgs {
+ ByValue,
+ ByRef,
+}
+
impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
pub fn new(delegate: &'d mut Delegate<'tcx>,
typer: &'t TYPER,
ast::ExprPath(..) => { }
ast::ExprUnary(ast::UnDeref, ref base) => { // *base
- if !self.walk_overloaded_operator(expr, &**base, Vec::new(), None) {
+ if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) {
self.select_from_expr(&**base);
}
}
}
ast::ExprIndex(ref lhs, ref rhs) => { // lhs[rhs]
- if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs], None) {
+ if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs], PassArgs::ByRef) {
self.select_from_expr(&**lhs);
self.consume_expr(&**rhs);
}
(&None, &Some(ref e)) => vec![&**e],
(&None, &None) => Vec::new()
};
- let overloaded = self.walk_overloaded_operator(expr, &**base, args, None);
+ let overloaded =
+ self.walk_overloaded_operator(expr, &**base, args, PassArgs::ByRef);
assert!(overloaded);
}
}
ast::ExprUnary(_, ref lhs) => {
- if !self.walk_overloaded_operator(expr, &**lhs, Vec::new(), None) {
+ if !self.walk_overloaded_operator(expr, &**lhs, Vec::new(), PassArgs::ByRef) {
self.consume_expr(&**lhs);
}
}
ast::ExprBinary(op, ref lhs, ref rhs) => {
- if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs], Some(op))
- {
+ let pass_args = if ast_util::is_by_value_binop(op) {
+ PassArgs::ByValue
+ } else {
+ PassArgs::ByRef
+ };
+
+ if !self.walk_overloaded_operator(expr, &**lhs, vec![&**rhs], pass_args) {
self.consume_expr(&**lhs);
self.consume_expr(&**rhs);
}
expr: &ast::Expr,
receiver: &ast::Expr,
rhs: Vec<&ast::Expr>,
- binop: Option<ast::BinOp>)
+ pass_args: PassArgs)
-> bool
{
if !self.typer.is_method_call(expr.id) {
return false;
}
- match binop {
- Some(binop) if ast_util::is_by_value_binop(binop) => {
+ match pass_args {
+ PassArgs::ByValue => {
self.consume_expr(receiver);
self.consume_expr(rhs[0]);
return true;
},
- _ => {},
+ PassArgs::ByRef => {},
}
self.walk_expr(receiver);
*/
pub use self::LvaluePreference::*;
-pub use self::DerefArgs::*;
pub use self::Expectation::*;
use self::IsBinopAssignment::*;
use self::TupleArgumentsFlag::*;
method_callee.ty,
call_expression,
args,
- DontDerefArgs,
+ AutorefArgs::No,
TupleArguments);
fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
write_call(fcx, call_expression, output_type);
method_ty_or_err,
expr,
args.as_slice(),
- DoDerefArgs,
+ AutorefArgs::Yes,
DontTupleArguments);
opt_method_ty.map(|method_ty| {
method_type,
iterator_expr,
&[],
- DontDerefArgs,
+ AutorefArgs::No,
DontTupleArguments);
match method {
method_fn_ty: Ty<'tcx>,
callee_expr: &ast::Expr,
args_no_rcvr: &[&P<ast::Expr>],
- deref_args: DerefArgs,
+ autoref_args: AutorefArgs,
tuple_arguments: TupleArgumentsFlag)
-> ty::FnOutput<'tcx> {
if ty::type_is_error(method_fn_ty) {
err_inputs.as_slice(),
callee_expr,
args_no_rcvr,
- deref_args,
+ autoref_args,
false,
tuple_arguments);
ty::FnConverging(ty::mk_err())
fty.sig.inputs.slice_from(1),
callee_expr,
args_no_rcvr,
- deref_args,
+ autoref_args,
fty.sig.variadic,
tuple_arguments);
fty.sig.output
fn_inputs: &[Ty<'tcx>],
_callee_expr: &ast::Expr,
args: &[&P<ast::Expr>],
- deref_args: DerefArgs,
+ autoref_args: AutorefArgs,
variadic: bool,
tuple_arguments: TupleArgumentsFlag) {
let tcx = fcx.ccx.tcx;
debug!("checking the argument");
let mut formal_ty = formal_tys[i];
- match deref_args {
- DoDerefArgs => {
+ match autoref_args {
+ AutorefArgs::Yes => {
match formal_ty.sty {
ty::ty_rptr(_, mt) => formal_ty = mt.ty,
ty::ty_err => (),
}
}
}
- DontDerefArgs => {}
+ AutorefArgs::No => {}
}
check_expr_coercable_to_type(fcx, &***arg, formal_ty);
// Controls whether the arguments are automatically referenced. This is useful
// for overloaded binary and unary operators.
#[deriving(PartialEq)]
-pub enum DerefArgs {
- DontDerefArgs,
- DoDerefArgs
+pub enum AutorefArgs {
+ Yes,
+ No,
}
-impl Copy for DerefArgs {}
+impl Copy for AutorefArgs {}
/// Controls whether the arguments are tupled. This is used for the call
/// operator.
fn_sig.inputs.as_slice(),
f,
args,
- DontDerefArgs,
+ AutorefArgs::No,
fn_sig.variadic,
DontTupleArguments);
fn_ty,
expr,
args.as_slice(),
- DontDerefArgs,
+ AutorefArgs::No,
DontTupleArguments);
write_call(fcx, expr, ret_ty);
lhs: &'a ast::Expr,
rhs: Option<&P<ast::Expr>>,
unbound_method: F,
- deref_args: DerefArgs) -> Ty<'tcx> where
+ autoref_args: AutorefArgs) -> Ty<'tcx> where
F: FnOnce(),
{
let method = match trait_did {
// traits that don't force left and right to have same
// type.
let (adj_ty, adjustment) = match lhs_ty.sty {
- ty::ty_rptr(r_in, mt) if deref_args == DoDerefArgs => {
+ ty::ty_rptr(r_in, mt) => {
let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, r_in);
let adjusted_ty = ty::mk_rptr(fcx.tcx(), r_adj, mt);
method_ty,
op_ex,
args.as_slice(),
- deref_args,
+ autoref_args,
DontTupleArguments) {
ty::FnConverging(result_type) => result_type,
ty::FnDiverging => ty::mk_err()
expected_ty,
op_ex,
args.as_slice(),
- deref_args,
+ autoref_args,
DontTupleArguments);
ty::mk_err()
}
rhs: &P<ast::Expr>) -> Ty<'tcx> {
let tcx = fcx.ccx.tcx;
let lang = &tcx.lang_items;
- let (name, trait_did, deref_args) = match op {
- ast::BiAdd => ("add", lang.add_trait(), DontDerefArgs),
- ast::BiSub => ("sub", lang.sub_trait(), DontDerefArgs),
- ast::BiMul => ("mul", lang.mul_trait(), DontDerefArgs),
- ast::BiDiv => ("div", lang.div_trait(), DontDerefArgs),
- ast::BiRem => ("rem", lang.rem_trait(), DontDerefArgs),
- ast::BiBitXor => ("bitxor", lang.bitxor_trait(), DontDerefArgs),
- ast::BiBitAnd => ("bitand", lang.bitand_trait(), DontDerefArgs),
- ast::BiBitOr => ("bitor", lang.bitor_trait(), DontDerefArgs),
- ast::BiShl => ("shl", lang.shl_trait(), DontDerefArgs),
- ast::BiShr => ("shr", lang.shr_trait(), DontDerefArgs),
- ast::BiLt => ("lt", lang.ord_trait(), DoDerefArgs),
- ast::BiLe => ("le", lang.ord_trait(), DoDerefArgs),
- ast::BiGe => ("ge", lang.ord_trait(), DoDerefArgs),
- ast::BiGt => ("gt", lang.ord_trait(), DoDerefArgs),
- ast::BiEq => ("eq", lang.eq_trait(), DoDerefArgs),
- ast::BiNe => ("ne", lang.eq_trait(), DoDerefArgs),
+ let (name, trait_did) = match op {
+ ast::BiAdd => ("add", lang.add_trait()),
+ ast::BiSub => ("sub", lang.sub_trait()),
+ ast::BiMul => ("mul", lang.mul_trait()),
+ ast::BiDiv => ("div", lang.div_trait()),
+ ast::BiRem => ("rem", lang.rem_trait()),
+ ast::BiBitXor => ("bitxor", lang.bitxor_trait()),
+ ast::BiBitAnd => ("bitand", lang.bitand_trait()),
+ ast::BiBitOr => ("bitor", lang.bitor_trait()),
+ ast::BiShl => ("shl", lang.shl_trait()),
+ ast::BiShr => ("shr", lang.shr_trait()),
+ ast::BiLt => ("lt", lang.ord_trait()),
+ ast::BiLe => ("le", lang.ord_trait()),
+ ast::BiGe => ("ge", lang.ord_trait()),
+ ast::BiGt => ("gt", lang.ord_trait()),
+ ast::BiEq => ("eq", lang.eq_trait()),
+ ast::BiNe => ("ne", lang.eq_trait()),
ast::BiAnd | ast::BiOr => {
check_expr(fcx, &**rhs);
return ty::mk_err();
ast_util::binop_to_string(op),
actual)
}, lhs_resolved_t, None)
- }, deref_args)
+ }, if ast_util::is_by_value_binop(op) { AutorefArgs::No } else { AutorefArgs::Yes })
}
fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
format!("cannot apply unary operator `{}` to type `{}`",
op_str, actual)
}, rhs_t, None);
- }, DontDerefArgs)
+ }, AutorefArgs::Yes)
}
// Check field access expressions