about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_typeck/check/op.rs133
-rw-r--r--src/test/ui/type-check/missing_trait_impl.rs4
-rw-r--r--src/test/ui/type-check/missing_trait_impl.stderr15
3 files changed, 77 insertions, 75 deletions
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 69b891af663..51a455dc25c 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -246,7 +246,8 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             Err(()) => {
                 // error types are considered "builtin"
                 if !lhs_ty.references_error() {
-                    match is_assign{
+                    let codemap = self.tcx.sess.codemap();
+                    match is_assign {
                         IsAssign::Yes => {
                             let mut err = struct_span_err!(self.tcx.sess, expr.span, E0368,
                                                 "binary assignment operation `{}=` \
@@ -256,19 +257,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                             err.span_label(lhs_expr.span,
                                     format!("cannot use `{}=` on type `{}`",
                                     op.node.as_str(), lhs_ty));
-                            let missing_trait = match op.node {
-                                hir::BiAdd    => Some("std::ops::AddAssign"),
-                                hir::BiSub    => Some("std::ops::SubAssign"),
-                                hir::BiMul    => Some("std::ops::MulAssign"),
-                                hir::BiDiv    => Some("std::ops::DivAssign"),
-                                hir::BiRem    => Some("std::ops::RemAssign"),
-                                hir::BiBitAnd => Some("std::ops::BitAndAssign"),
-                                hir::BiBitXor => Some("std::ops::BitXorAssign"),
-                                hir::BiBitOr  => Some("std::ops::BitOrAssign"),
-                                hir::BiShl    => Some("std::ops::ShlAssign"),
-                                hir::BiShr    => Some("std::ops::ShrAssign"),
-                                _             => None
-                            };
                             let mut suggested_deref = false;
                             if let TyRef(_, ref ty_mut) = lhs_ty.sty {
                                 if {
@@ -280,22 +268,31 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                                                 Op::Binary(op, is_assign))
                                             .is_ok()
                                 } {
-                                    let codemap = self.tcx.sess.codemap();
-                                    match codemap.span_to_snippet(lhs_expr.span) {
-                                        Ok(lstring) =>{
-                                            let msg = &format!(
+                                    if let Ok(lstring) = codemap.span_to_snippet(lhs_expr.span) {
+                                        let msg = &format!(
                                                 "`{}=` can be used on '{}', you can \
                                                 dereference `{2}`: `*{2}`",
                                                 op.node.as_str(), ty_mut.ty, lstring);
-                                            err.help(msg);
-                                            suggested_deref = true;
-                                        },
-                                        _ => {}
-                                    };
+                                        err.help(msg);
+                                        suggested_deref = true;
+                                    }
                                 }
                             }
+                            let missing_trait = match op.node {
+                                hir::BiAdd    => Some("std::ops::AddAssign"),
+                                hir::BiSub    => Some("std::ops::SubAssign"),
+                                hir::BiMul    => Some("std::ops::MulAssign"),
+                                hir::BiDiv    => Some("std::ops::DivAssign"),
+                                hir::BiRem    => Some("std::ops::RemAssign"),
+                                hir::BiBitAnd => Some("std::ops::BitAndAssign"),
+                                hir::BiBitXor => Some("std::ops::BitXorAssign"),
+                                hir::BiBitOr  => Some("std::ops::BitOrAssign"),
+                                hir::BiShl    => Some("std::ops::ShlAssign"),
+                                hir::BiShr    => Some("std::ops::ShrAssign"),
+                                _             => None
+                            };
                             if let Some(missing_trait) = missing_trait {
-                                if missing_trait == "std::ops::AddAssign" &&
+                                if op.node == hir::BiAdd &&
                                     self.check_str_addition(expr, lhs_expr, rhs_expr, lhs_ty,
                                                             rhs_ty, &mut err) {
                                     // This has nothing here because it means we did string
@@ -306,13 +303,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                     err.note(
                                         &format!("`{}` might need a bound for `{}`",
                                                     lhs_ty, missing_trait));
-                                } else {
-                                    if !suggested_deref{
-                                        err.note(
-                                            &format!("an implementation of `{}` might \
-                                                        be missing for `{}`",
-                                                        missing_trait, lhs_ty));
-                                    }
+                                } else if !suggested_deref {
+                                    err.note(
+                                        &format!("an implementation of `{}` might \
+                                                    be missing for `{}`",
+                                                    missing_trait, lhs_ty));
                                 }
                             }
                             err.emit();
@@ -322,22 +317,6 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                             "binary operation `{}` cannot be applied to type `{}`",
                                             op.node.as_str(),
                                             lhs_ty);
-                            let missing_trait = match op.node {
-                                hir::BiAdd    => Some("std::ops::Add"),
-                                hir::BiSub    => Some("std::ops::Sub"),
-                                hir::BiMul    => Some("std::ops::Mul"),
-                                hir::BiDiv    => Some("std::ops::Div"),
-                                hir::BiRem    => Some("std::ops::Rem"),
-                                hir::BiBitAnd => Some("std::ops::BitAnd"),
-                                hir::BiBitXor => Some("std::ops::BitXor"),
-                                hir::BiBitOr  => Some("std::ops::BitOr"),
-                                hir::BiShl    => Some("std::ops::Shl"),
-                                hir::BiShr    => Some("std::ops::Shr"),
-                                hir::BiEq | hir::BiNe => Some("std::cmp::PartialEq"),
-                                hir::BiLt | hir::BiLe | hir::BiGt | hir::BiGe =>
-                                    Some("std::cmp::PartialOrd"),
-                                _             => None
-                            };
                             let mut suggested_deref = false;
                             if let TyRef(_, ref ty_mut) = lhs_ty.sty {
                                 if {
@@ -349,22 +328,34 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                                                 Op::Binary(op, is_assign))
                                             .is_ok()
                                 } {
-                                    let codemap = self.tcx.sess.codemap();
-                                    match codemap.span_to_snippet(lhs_expr.span) {
-                                        Ok(lstring) =>{
-                                            let msg = &format!(
+                                    if let Ok(lstring) = codemap.span_to_snippet(lhs_expr.span) {
+                                        let msg = &format!(
                                                 "`{}` can be used on '{}', you can \
                                                 dereference `{2}`: `*{2}`",
                                                 op.node.as_str(), ty_mut.ty, lstring);
-                                            err.help(msg);
-                                            suggested_deref = true;
-                                        },
-                                        _ =>{}
+                                        err.help(msg);
+                                        suggested_deref = true;
                                     }
                                 }
                             }
+                            let missing_trait = match op.node {
+                                hir::BiAdd    => Some("std::ops::Add"),
+                                hir::BiSub    => Some("std::ops::Sub"),
+                                hir::BiMul    => Some("std::ops::Mul"),
+                                hir::BiDiv    => Some("std::ops::Div"),
+                                hir::BiRem    => Some("std::ops::Rem"),
+                                hir::BiBitAnd => Some("std::ops::BitAnd"),
+                                hir::BiBitXor => Some("std::ops::BitXor"),
+                                hir::BiBitOr  => Some("std::ops::BitOr"),
+                                hir::BiShl    => Some("std::ops::Shl"),
+                                hir::BiShr    => Some("std::ops::Shr"),
+                                hir::BiEq | hir::BiNe => Some("std::cmp::PartialEq"),
+                                hir::BiLt | hir::BiLe | hir::BiGt | hir::BiGe =>
+                                    Some("std::cmp::PartialOrd"),
+                                _             => None
+                            };
                             if let Some(missing_trait) = missing_trait {
-                                if missing_trait == "std::ops::Add" &&
+                                if op.node == hir::BiAdd &&
                                     self.check_str_addition(expr, lhs_expr, rhs_expr, lhs_ty,
                                                             rhs_ty, &mut err) {
                                     // This has nothing here because it means we did string
@@ -375,13 +366,11 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                     err.note(
                                         &format!("`{}` might need a bound for `{}`",
                                                     lhs_ty, missing_trait));
-                                } else {
-                                    if !suggested_deref{
-                                        err.note(
-                                            &format!("an implementation of `{}` might \
-                                                        be missing for `{}`",
-                                                        missing_trait, lhs_ty));
-                                    }
+                                } else if !suggested_deref {
+                                    err.note(
+                                        &format!("an implementation of `{}` might \
+                                                    be missing for `{}`",
+                                                    missing_trait, lhs_ty));
                                 }
                             }
                             err.emit();
@@ -468,20 +457,18 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                                      op.as_str(), actual);
                     err.span_label(ex.span, format!("cannot apply unary \
                                                     operator `{}`", op.as_str()));
-                    let missing_trait = match op {
-                        hir::UnNeg => "std::ops::Neg",
-                        hir::UnNot => "std::ops::Not",
-                        hir::UnDeref => "std::ops::UnDerf"
-                    };
-                    match actual.sty{
-                        TyUint(_) => {
-                            if op == hir::UnNeg{
-                                err.note(&format!("unsigned values cannot be negated"));
-                            }
+                    match actual.sty {
+                        TyUint(_) if op == hir::UnNeg => {
+                            err.note(&format!("unsigned values cannot be negated"));
                         },
                         TyStr | TyNever | TyChar | TyTuple(_) | TyArray(_,_) => {},
                         TyRef(_, ref lty) if lty.ty.sty == TyStr => {},
                         _ => {
+                            let missing_trait = match op {
+                                hir::UnNeg => "std::ops::Neg",
+                                hir::UnNot => "std::ops::Not",
+                                hir::UnDeref => "std::ops::UnDerf"
+                            };
                             err.note(&format!("an implementation of `{}` might \
                                                 be missing for `{}`",
                                              missing_trait, operand_ty));
diff --git a/src/test/ui/type-check/missing_trait_impl.rs b/src/test/ui/type-check/missing_trait_impl.rs
index adf6b85b642..b3e79ce2447 100644
--- a/src/test/ui/type-check/missing_trait_impl.rs
+++ b/src/test/ui/type-check/missing_trait_impl.rs
@@ -14,3 +14,7 @@ fn main() {
 fn foo<T>(x: T, y: T) {
     let z = x + y; //~ ERROR binary operation `+` cannot be applied to type `T`
 }
+
+fn bar<T>(x: T) {
+    x += x; //~ ERROR binary assignment operation `+=` cannot be applied to type `T`
+}
diff --git a/src/test/ui/type-check/missing_trait_impl.stderr b/src/test/ui/type-check/missing_trait_impl.stderr
index 777f16b12ce..4b01a626814 100644
--- a/src/test/ui/type-check/missing_trait_impl.stderr
+++ b/src/test/ui/type-check/missing_trait_impl.stderr
@@ -6,6 +6,17 @@ LL |     let z = x + y; //~ ERROR binary operation `+` cannot be applied to type
    |
    = note: `T` might need a bound for `std::ops::Add`
 
-error: aborting due to previous error
+error[E0368]: binary assignment operation `+=` cannot be applied to type `T`
+  --> $DIR/missing_trait_impl.rs:19:5
+   |
+LL |     x += x; //~ ERROR binary assignment operation `+=` cannot be applied to type `T`
+   |     -^^^^^
+   |     |
+   |     cannot use `+=` on type `T`
+   |
+   = note: `T` might need a bound for `std::ops::AddAssign`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0369`.
+Some errors occurred: E0368, E0369.
+For more information about an error, try `rustc --explain E0368`.