Address Niko's comments
This commit is contained in:
parent
d193bf30ce
commit
f4abb12b0c
@ -329,6 +329,12 @@ macro_rules! return_if_err(
|
||||
)
|
||||
)
|
||||
|
||||
/// 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,
|
||||
@ -438,7 +444,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,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);
|
||||
}
|
||||
}
|
||||
@ -452,7 +458,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@ -465,7 +471,8 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||
(&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);
|
||||
}
|
||||
|
||||
@ -570,14 +577,19 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
@ -913,21 +925,21 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
|
||||
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);
|
||||
|
@ -77,7 +77,6 @@ type parameter).
|
||||
*/
|
||||
|
||||
pub use self::LvaluePreference::*;
|
||||
pub use self::DerefArgs::*;
|
||||
pub use self::Expectation::*;
|
||||
use self::IsBinopAssignment::*;
|
||||
use self::TupleArgumentsFlag::*;
|
||||
@ -2117,7 +2116,7 @@ fn try_overloaded_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
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);
|
||||
@ -2274,7 +2273,7 @@ fn try_overloaded_slice<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
method_ty_or_err,
|
||||
expr,
|
||||
args.as_slice(),
|
||||
DoDerefArgs,
|
||||
AutorefArgs::Yes,
|
||||
DontTupleArguments);
|
||||
|
||||
opt_method_ty.map(|method_ty| {
|
||||
@ -2480,7 +2479,7 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
method_type,
|
||||
iterator_expr,
|
||||
&[],
|
||||
DontDerefArgs,
|
||||
AutorefArgs::No,
|
||||
DontTupleArguments);
|
||||
|
||||
match method {
|
||||
@ -2522,7 +2521,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
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) {
|
||||
@ -2538,7 +2537,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
err_inputs.as_slice(),
|
||||
callee_expr,
|
||||
args_no_rcvr,
|
||||
deref_args,
|
||||
autoref_args,
|
||||
false,
|
||||
tuple_arguments);
|
||||
ty::FnConverging(ty::mk_err())
|
||||
@ -2551,7 +2550,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
fty.sig.inputs.slice_from(1),
|
||||
callee_expr,
|
||||
args_no_rcvr,
|
||||
deref_args,
|
||||
autoref_args,
|
||||
fty.sig.variadic,
|
||||
tuple_arguments);
|
||||
fty.sig.output
|
||||
@ -2571,7 +2570,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
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;
|
||||
@ -2674,8 +2673,8 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, '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 => (),
|
||||
@ -2690,7 +2689,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
}
|
||||
}
|
||||
}
|
||||
DontDerefArgs => {}
|
||||
AutorefArgs::No => {}
|
||||
}
|
||||
|
||||
check_expr_coercable_to_type(fcx, &***arg, formal_ty);
|
||||
@ -2905,12 +2904,12 @@ pub fn lookup_tup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
|
||||
// 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.
|
||||
@ -2998,7 +2997,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
fn_sig.inputs.as_slice(),
|
||||
f,
|
||||
args,
|
||||
DontDerefArgs,
|
||||
AutorefArgs::No,
|
||||
fn_sig.variadic,
|
||||
DontTupleArguments);
|
||||
|
||||
@ -3048,7 +3047,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
fn_ty,
|
||||
expr,
|
||||
args.as_slice(),
|
||||
DontDerefArgs,
|
||||
AutorefArgs::No,
|
||||
DontTupleArguments);
|
||||
|
||||
write_call(fcx, expr, ret_ty);
|
||||
@ -3132,7 +3131,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
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 {
|
||||
@ -3148,7 +3147,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
// 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);
|
||||
@ -3185,7 +3184,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
method_ty,
|
||||
op_ex,
|
||||
args.as_slice(),
|
||||
deref_args,
|
||||
autoref_args,
|
||||
DontTupleArguments) {
|
||||
ty::FnConverging(result_type) => result_type,
|
||||
ty::FnDiverging => ty::mk_err()
|
||||
@ -3201,7 +3200,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
expected_ty,
|
||||
op_ex,
|
||||
args.as_slice(),
|
||||
deref_args,
|
||||
autoref_args,
|
||||
DontTupleArguments);
|
||||
ty::mk_err()
|
||||
}
|
||||
@ -3320,23 +3319,23 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
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();
|
||||
@ -3349,7 +3348,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
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>,
|
||||
@ -3365,7 +3364,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
|
||||
format!("cannot apply unary operator `{}` to type `{}`",
|
||||
op_str, actual)
|
||||
}, rhs_t, None);
|
||||
}, DontDerefArgs)
|
||||
}, AutorefArgs::Yes)
|
||||
}
|
||||
|
||||
// Check field access expressions
|
||||
|
Loading…
x
Reference in New Issue
Block a user