1
Fork 0

Improve invalid operator assignment handling.

This commit is contained in:
Raphael Catolino 2014-01-10 20:46:20 +01:00
parent 72a52522ca
commit 02d86216f3
3 changed files with 34 additions and 14 deletions

View file

@ -213,11 +213,13 @@ impl PurityState {
} }
} }
/// Whether `check_binop` allows overloaded operators to be invoked. /// Whether `check_binop` is part of an assignment or not.
/// Used to know wether we allow user overloads and to print
/// better messages on error.
#[deriving(Eq)] #[deriving(Eq)]
enum AllowOverloadedOperatorsFlag { enum IsBinopAssignment{
AllowOverloadedOperators, SimpleBinop,
DontAllowOverloadedOperators, BinopAssignment,
} }
#[deriving(Clone)] #[deriving(Clone)]
@ -2086,7 +2088,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
rhs: @ast::Expr, rhs: @ast::Expr,
// Used only in the error case // Used only in the error case
expected_result: Option<ty::t>, expected_result: Option<ty::t>,
allow_overloaded_operators: AllowOverloadedOperatorsFlag is_binop_assignment: IsBinopAssignment
) { ) {
let tcx = fcx.ccx.tcx; let tcx = fcx.ccx.tcx;
@ -2136,9 +2138,9 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
} }
// Check for overloaded operators if allowed. // Check for overloaded operators if not an assignment.
let result_t; let result_t;
if allow_overloaded_operators == AllowOverloadedOperators { if is_binop_assignment == SimpleBinop {
result_t = check_user_binop(fcx, result_t = check_user_binop(fcx,
callee_id, callee_id,
expr, expr,
@ -2150,13 +2152,14 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
} else { } else {
fcx.type_error_message(expr.span, fcx.type_error_message(expr.span,
|actual| { |actual| {
format!("binary operation {} cannot be \ format!("binary assignment operation \
applied to type `{}`", {}= cannot be applied to type `{}`",
ast_util::binop_to_str(op), ast_util::binop_to_str(op),
actual) actual)
}, },
lhs_t, lhs_t,
None); None);
check_expr(fcx, rhs);
result_t = ty::mk_err(); result_t = ty::mk_err();
} }
@ -2760,7 +2763,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
lhs, lhs,
rhs, rhs,
expected, expected,
AllowOverloadedOperators); SimpleBinop);
let lhs_ty = fcx.expr_ty(lhs); let lhs_ty = fcx.expr_ty(lhs);
let rhs_ty = fcx.expr_ty(rhs); let rhs_ty = fcx.expr_ty(rhs);
@ -2781,7 +2784,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
lhs, lhs,
rhs, rhs,
expected, expected,
DontAllowOverloadedOperators); BinopAssignment);
let lhs_t = fcx.expr_ty(lhs); let lhs_t = fcx.expr_ty(lhs);
let result_t = fcx.expr_ty(expr); let result_t = fcx.expr_ty(expr);

View file

@ -0,0 +1,17 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct Foo;
fn main() {
let mut a = Foo;
let ref b = Foo;
a += *b; //~ Error: binary assignment operation += cannot be applied to type `Foo`
}

View file

@ -11,5 +11,5 @@
// Regression test for issue #5239 // Regression test for issue #5239
fn main() { fn main() {
let x: |int| -> int = |ref x| { x += 1; }; //~ ERROR binary operation + cannot be applied to type `&int` let x: |int| -> int = |ref x| { x += 1; }; //~ ERROR binary assignment operation += cannot be applied to type `&int`
} }