Skip to content

Commit 33e8663

Browse files
committed
auto merge of #11449 : rcatolino/rust/assign-binop-handling, r=alexcrichton
So far the following code ``` struct Foo; fn main() { let mut t = Foo; let ref b = Foo; a += *b; } ``` errors with ``` test.rs:15:3: 13:11 error: binary operation + cannot be applied to type `Foo` test.rs:15 *a += *b; ``` Since assignment-operators are no longer expanded to ```left = left OP right``` but are independents operators it should be ``` test.rs:15:3: 13:11 error: binary operation += cannot be applied to type `Foo` test.rs:15 *a += *b; ``` to make it clear that implementing Add for Foo is not gonna work. (cf issues #11143, #11344) Besides that, we also need to typecheck the rhs expression even if the operator has no implementation, or we end up with unknown types for the nodes of the rhs and an ICE later on while resolving types. (once again cf #11143 and #11344). This probably would get fixed with #5992, but in the meantime it's a confusing error to stumble upon. @pcwalton, you wrote the original code, what do you think? (closes #11143 and #11344)
2 parents ff7ecca + 02d8621 commit 33e8663

File tree

3 files changed

+34
-14
lines changed

3 files changed

+34
-14
lines changed

src/librustc/middle/typeck/check/mod.rs

+16-13
Original file line numberDiff line numberDiff line change
@@ -213,11 +213,13 @@ impl PurityState {
213213
}
214214
}
215215

216-
/// Whether `check_binop` allows overloaded operators to be invoked.
216+
/// Whether `check_binop` is part of an assignment or not.
217+
/// Used to know wether we allow user overloads and to print
218+
/// better messages on error.
217219
#[deriving(Eq)]
218-
enum AllowOverloadedOperatorsFlag {
219-
AllowOverloadedOperators,
220-
DontAllowOverloadedOperators,
220+
enum IsBinopAssignment{
221+
SimpleBinop,
222+
BinopAssignment,
221223
}
222224

223225
#[deriving(Clone)]
@@ -2086,7 +2088,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
20862088
rhs: @ast::Expr,
20872089
// Used only in the error case
20882090
expected_result: Option<ty::t>,
2089-
allow_overloaded_operators: AllowOverloadedOperatorsFlag
2091+
is_binop_assignment: IsBinopAssignment
20902092
) {
20912093
let tcx = fcx.ccx.tcx;
20922094

@@ -2136,9 +2138,9 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
21362138

21372139
}
21382140

2139-
// Check for overloaded operators if allowed.
2141+
// Check for overloaded operators if not an assignment.
21402142
let result_t;
2141-
if allow_overloaded_operators == AllowOverloadedOperators {
2143+
if is_binop_assignment == SimpleBinop {
21422144
result_t = check_user_binop(fcx,
21432145
callee_id,
21442146
expr,
@@ -2150,13 +2152,14 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
21502152
} else {
21512153
fcx.type_error_message(expr.span,
21522154
|actual| {
2153-
format!("binary operation {} cannot be \
2154-
applied to type `{}`",
2155-
ast_util::binop_to_str(op),
2156-
actual)
2155+
format!("binary assignment operation \
2156+
{}= cannot be applied to type `{}`",
2157+
ast_util::binop_to_str(op),
2158+
actual)
21572159
},
21582160
lhs_t,
21592161
None);
2162+
check_expr(fcx, rhs);
21602163
result_t = ty::mk_err();
21612164
}
21622165

@@ -2760,7 +2763,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
27602763
lhs,
27612764
rhs,
27622765
expected,
2763-
AllowOverloadedOperators);
2766+
SimpleBinop);
27642767

27652768
let lhs_ty = fcx.expr_ty(lhs);
27662769
let rhs_ty = fcx.expr_ty(rhs);
@@ -2781,7 +2784,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
27812784
lhs,
27822785
rhs,
27832786
expected,
2784-
DontAllowOverloadedOperators);
2787+
BinopAssignment);
27852788

27862789
let lhs_t = fcx.expr_ty(lhs);
27872790
let result_t = fcx.expr_ty(expr);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
struct Foo;
12+
13+
fn main() {
14+
let mut a = Foo;
15+
let ref b = Foo;
16+
a += *b; //~ Error: binary assignment operation += cannot be applied to type `Foo`
17+
}

src/test/compile-fail/issue-5239-1.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -11,5 +11,5 @@
1111
// Regression test for issue #5239
1212

1313
fn main() {
14-
let x: |int| -> int = |ref x| { x += 1; }; //~ ERROR binary operation + cannot be applied to type `&int`
14+
let x: |int| -> int = |ref x| { x += 1; }; //~ ERROR binary assignment operation += cannot be applied to type `&int`
1515
}

0 commit comments

Comments
 (0)