diff options
| -rw-r--r-- | src/librustc_typeck/check/op.rs | 133 | ||||
| -rw-r--r-- | src/test/ui/type-check/missing_trait_impl.rs | 4 | ||||
| -rw-r--r-- | src/test/ui/type-check/missing_trait_impl.stderr | 15 |
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`. |
