Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
14c0a70
syntax/ast_util: add `is_by_value_binop()`
Dec 1, 2014
c3a6d28
Tell typeck which binops are by value
Dec 1, 2014
f64e52a
Tell trans which binops are by value
Dec 1, 2014
5038f5a
Tell expr_use_visitor which binops are by value
Dec 1, 2014
227435a
Tell regionck which binops are by value
Dec 1, 2014
c73259a
libcore: convert binop traits to by value
Dec 1, 2014
65d3a40
libcore: fix move semantics fallout
Dec 1, 2014
dbc7e17
libcollections: Vec<T> + &[T]
Dec 1, 2014
076e932
libcollections: String + &str
Dec 1, 2014
baf79d4
libcollections: make `EnumSet` binops by value
Dec 1, 2014
32168fa
libstd: convert `BitFlags` binops to by value
Dec 1, 2014
9126a24
libstd: convert `Duration` binops to by value
Dec 1, 2014
b5537fa
libtime: convert `Timespec` binops to by value
Dec 1, 2014
265b89a
libsyntax: convert `BytePos`/`CharPos` binops to by value
Dec 1, 2014
c4fa2a3
libsyntax: convert `LockstepIterSize` binops to by value
Dec 1, 2014
eb71976
librustc: convert `TypeContents` binops to by value
Dec 1, 2014
fb1d4f1
librustdoc: convert `Counts` binops to by value
Dec 1, 2014
2b17083
Test that binops consume their arguments
Dec 1, 2014
971add8
Fix run-pass tests
Dec 1, 2014
f0b6567
Fix compile-fail tests
Dec 1, 2014
a672b27
libcollections: fix unit tests
Dec 1, 2014
1ec5650
libcoretest: fix unit tests
Dec 1, 2014
bc23b8e
libstd: fix unit tests
Dec 1, 2014
d193bf3
libcore: fix doctests
Dec 2, 2014
f4abb12
Address Niko's comments
Dec 3, 2014
949b55e
libcollections: add commutative version of `Vec`/`String` addition
Dec 3, 2014
dff2b39
Test binops move semantics
Dec 3, 2014
3084604
libcollections: convert `TrieSet` binops to by value
Dec 6, 2014
e00e461
libcollections: convert `TreeSet` binops to by value
Dec 13, 2014
89d2061
libcollections: convert `BTreeSet` binops to by value
Dec 13, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Address Niko's comments
  • Loading branch information
Jorge Aparicio committed Dec 14, 2014
commit f4abb12b0c822e119e69023ab94664415061d955
32 changes: 22 additions & 10 deletions src/librustc/middle/expr_use_visitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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);
}
}
Expand All @@ -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);
}
Expand All @@ -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);
}

Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
Expand Down
79 changes: 39 additions & 40 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ type parameter).
*/

pub use self::LvaluePreference::*;
pub use self::DerefArgs::*;
pub use self::Expectation::*;
use self::IsBinopAssignment::*;
use self::TupleArgumentsFlag::*;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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| {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand All @@ -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())
Expand All @@ -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
Expand All @@ -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;
Expand Down Expand Up @@ -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 => (),
Expand All @@ -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);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 {
Expand All @@ -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);
Expand Down Expand Up @@ -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()
Expand All @@ -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()
}
Expand Down Expand Up @@ -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();
Expand All @@ -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>,
Expand All @@ -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
Expand Down