@@ -2988,19 +2988,20 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
29882988 let result_t = if is_binop_assignment == SimpleBinop {
29892989 check_user_binop ( fcx, expr, lhs, lhs_t, op, rhs)
29902990 } 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+ }
30043005 } ;
30053006
30063007 fcx. write_ty ( expr. id , result_t) ;
@@ -3049,6 +3050,42 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
30493050 } , if ast_util:: is_by_value_binop ( op. node ) { AutorefArgs :: No } else { AutorefArgs :: Yes } )
30503051 }
30513052
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+
30523089 fn check_user_unop < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
30533090 op_str : & str ,
30543091 mname : & str ,
@@ -3480,10 +3517,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
34803517 ast:: ExprAssignOp ( op, ref lhs, ref rhs) => {
34813518 check_binop ( fcx, expr, op, & * * lhs, rhs, BinopAssignment ) ;
34823519
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-
34873520 let tcx = fcx. tcx ( ) ;
34883521 if !ty:: expr_is_lval ( tcx, & * * lhs) {
34893522 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>,
34943527 // Overwrite result of check_binop...this preserves existing behavior
34953528 // but seems quite dubious with regard to user-defined methods
34963529 // and so forth. - Niko
3497- if !ty:: type_is_error ( result_t ) {
3530+ if !ty:: type_is_error ( fcx . expr_ty ( expr ) ) {
34983531 fcx. write_nil ( expr. id ) ;
34993532 }
35003533 }
0 commit comments