@@ -2992,19 +2992,20 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
29922992 let result_t = if is_binop_assignment == SimpleBinop {
29932993 check_user_binop ( fcx, expr, lhs, lhs_t, op, rhs)
29942994 } 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+ }
30083009 } ;
30093010
30103011 fcx. write_ty ( expr. id , result_t) ;
@@ -3053,6 +3054,42 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
30533054 } , if ast_util:: is_by_value_binop ( op. node ) { AutorefArgs :: No } else { AutorefArgs :: Yes } )
30543055 }
30553056
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+
30563093 fn check_user_unop < ' a , ' tcx > ( fcx : & FnCtxt < ' a , ' tcx > ,
30573094 op_str : & str ,
30583095 mname : & str ,
@@ -3484,10 +3521,6 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
34843521 ast:: ExprAssignOp ( op, ref lhs, ref rhs) => {
34853522 check_binop ( fcx, expr, op, & * * lhs, rhs, BinopAssignment ) ;
34863523
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-
34913524 let tcx = fcx. tcx ( ) ;
34923525 if !ty:: expr_is_lval ( tcx, & * * lhs) {
34933526 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>,
34983531 // Overwrite result of check_binop...this preserves existing behavior
34993532 // but seems quite dubious with regard to user-defined methods
35003533 // and so forth. - Niko
3501- if !ty:: type_is_error ( result_t ) {
3534+ if !ty:: type_is_error ( fcx . expr_ty ( expr ) ) {
35023535 fcx. write_nil ( expr. id ) ;
35033536 }
35043537 }
0 commit comments