@@ -2988,19 +2988,20 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
2988
2988
let result_t = if is_binop_assignment == SimpleBinop {
2989
2989
check_user_binop ( fcx, expr, lhs, lhs_t, op, rhs)
2990
2990
} else {
2991
- fcx. type_error_message ( expr. span ,
2992
- |actual| {
2993
- format ! ( "binary assignment \
2994
- operation `{}=` \
2995
- cannot be applied to \
2996
- type `{}`",
2997
- ast_util:: binop_to_string( op. node) ,
2998
- actual)
2999
- } ,
3000
- lhs_t,
3001
- None ) ;
3002
- check_expr ( fcx, & * * rhs) ;
3003
- fcx. tcx ( ) . types . err
2991
+ if fcx. tcx ( ) . sess . features . borrow ( ) . op_assign {
2992
+ check_user_binop_assign ( fcx, expr, lhs, lhs_t, op, rhs)
2993
+ } else {
2994
+ fcx. tcx ( ) . sess . span_err (
2995
+ expr. span ,
2996
+ "overloaded augmented assignment is not stable" ,
2997
+ ) ;
2998
+ fileline_help ! (
2999
+ fcx. tcx( ) . sess,
3000
+ expr. span,
3001
+ "add `#![feature(op_assign)]` to the crate attributes to enable" ) ;
3002
+
3003
+ fcx. tcx ( ) . types . err
3004
+ }
3004
3005
} ;
3005
3006
3006
3007
fcx. write_ty ( expr. id , result_t) ;
@@ -3049,6 +3050,42 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3049
3050
} , if ast_util:: is_by_value_binop ( op. node ) { AutorefArgs :: No } else { AutorefArgs :: Yes } )
3050
3051
}
3051
3052
3053
+ fn check_user_binop_assign < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
3054
+ ex : & ' tcx ast:: Expr ,
3055
+ lhs_expr : & ' tcx ast:: Expr ,
3056
+ lhs_resolved_t : Ty < ' tcx > ,
3057
+ op : ast:: BinOp ,
3058
+ rhs : & ' tcx P < ast:: Expr > ) -> Ty < ' tcx > {
3059
+ let tcx = fcx. ccx . tcx ;
3060
+ let lang = & tcx. lang_items ;
3061
+ let ( name, trait_did) = match op. node {
3062
+ ast:: BiAdd => ( "add_assign" , lang. add_assign_trait ( ) ) ,
3063
+ ast:: BiSub => ( "sub_assign" , lang. sub_assign_trait ( ) ) ,
3064
+ ast:: BiMul => ( "mul_assign" , lang. mul_assign_trait ( ) ) ,
3065
+ ast:: BiDiv => ( "div_assign" , lang. div_assign_trait ( ) ) ,
3066
+ ast:: BiRem => ( "rem_assign" , lang. rem_assign_trait ( ) ) ,
3067
+ ast:: BiBitXor => ( "bitxor_assign" , lang. bitxor_assign_trait ( ) ) ,
3068
+ ast:: BiBitAnd => ( "bitand_assign" , lang. bitand_assign_trait ( ) ) ,
3069
+ ast:: BiBitOr => ( "bitor_assign" , lang. bitor_assign_trait ( ) ) ,
3070
+ ast:: BiShl => ( "shl_assign" , lang. shl_assign_trait ( ) ) ,
3071
+ ast:: BiShr => ( "shr_assign" , lang. shr_assign_trait ( ) ) ,
3072
+ ast:: BiLt | ast:: BiLe | ast:: BiGe | ast:: BiGt | ast:: BiEq | ast:: BiNe | ast:: BiAnd |
3073
+ ast:: BiOr =>
3074
+ {
3075
+ check_expr ( fcx, & * * rhs) ;
3076
+ return tcx. types . err ;
3077
+ }
3078
+ } ;
3079
+ lookup_op_method ( fcx, ex, lhs_resolved_t, token:: intern ( name) ,
3080
+ trait_did, lhs_expr, Some ( rhs) , || {
3081
+ fcx. type_error_message ( ex. span , |actual| {
3082
+ format ! ( "binary operation `{}=` cannot be applied to type `{}`" ,
3083
+ ast_util:: binop_to_string( op. node) ,
3084
+ actual)
3085
+ } , lhs_resolved_t, None )
3086
+ } , AutorefArgs :: Yes )
3087
+ }
3088
+
3052
3089
fn check_user_unop < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
3053
3090
op_str : & str ,
3054
3091
mname : & str ,
@@ -3480,10 +3517,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3480
3517
ast:: ExprAssignOp ( op, ref lhs, ref rhs) => {
3481
3518
check_binop ( fcx, expr, op, & * * lhs, rhs, BinopAssignment ) ;
3482
3519
3483
- let lhs_t = fcx. expr_ty ( & * * lhs) ;
3484
- let result_t = fcx. expr_ty ( expr) ;
3485
- demand:: suptype ( fcx, expr. span , result_t, lhs_t) ;
3486
-
3487
3520
let tcx = fcx. tcx ( ) ;
3488
3521
if !ty:: expr_is_lval ( tcx, & * * lhs) {
3489
3522
span_err ! ( tcx. sess, lhs. span, E0067 , "illegal left-hand side expression" ) ;
@@ -3494,7 +3527,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
3494
3527
// Overwrite result of check_binop...this preserves existing behavior
3495
3528
// but seems quite dubious with regard to user-defined methods
3496
3529
// and so forth. - Niko
3497
- if !ty:: type_is_error ( result_t ) {
3530
+ if !ty:: type_is_error ( fcx . expr_ty ( expr ) ) {
3498
3531
fcx. write_nil ( expr. id ) ;
3499
3532
}
3500
3533
}
0 commit comments