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