added missing implementation hint

This commit is contained in:
Roman Stoliar 2018-04-22 20:35:21 +03:00
parent 4e5a155a93
commit 2f6945c776
8 changed files with 86 additions and 36 deletions

View File

@ -280,43 +280,67 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
op.node.as_str()));
}
}
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::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" &&
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
// concatenation (e.g. "Hello " + "World!"). This means
// we don't want the note in the else clause to be emitted
} else if let ty::TyParam(_) = lhs_ty.sty {
// FIXME: point to span of param
err.note(
&format!("`{}` might need a bound for `{}`",
lhs_ty, missing_trait));
} else {
err.note(
&format!("an implementation of `{}` might be missing for `{}`",
missing_trait, lhs_ty));
IsAssign::No => {
let mut err = struct_span_err!(self.tcx.sess, expr.span, E0369,
"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
};
if let TypeVariants::TyRef(_, ref ty_mut) = lhs_ty.sty {
if {
!self.infcx.type_moves_by_default(self.param_env,
ty_mut.ty,
lhs_expr.span) &&
self.lookup_op_method(ty_mut.ty,
&[rhs_ty],
Op::Binary(op, is_assign))
.is_ok()
} {
err.note(
&format!(
"this is a reference to a type that `{}` can be \
applied to; you need to dereference this variable \
once for this operation to work",
op.node.as_str()));
}
}
(err, missing_trait)
}
};
if let Some(missing_trait) = missing_trait {
if missing_trait == "std::ops::Add" &&
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
// concatenation (e.g. "Hello " + "World!"). This means
// we don't want the note in the else clause to be emitted
} else if let ty::TyParam(_) = lhs_ty.sty {
// FIXME: point to span of param
err.note(
&format!("`{}` might need a bound for `{}`",
lhs_ty, missing_trait));
} else {
err.note(
&format!("an implementation of `{}` might be missing for `{}`",
missing_trait, lhs_ty));
}
err.emit();
}
err.emit();
}
self.tcx.types.err
}
@ -393,9 +417,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
Err(()) => {
let actual = self.resolve_type_vars_if_possible(&operand_ty);
if !actual.references_error() {
struct_span_err!(self.tcx.sess, ex.span, E0600,
let mut err = struct_span_err!(self.tcx.sess, ex.span, E0600,
"cannot apply unary operator `{}` to type `{}`",
op.as_str(), actual).emit();
op.as_str(), actual);
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));
err.emit();
}
self.tcx.types.err
}

View File

@ -3,6 +3,8 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str`
|
LL | assert!("foo");
| ^^^^^^^^^^^^^^^
|
= note: an implementation of `std::ops::Not` might be missing for `&'static str`
error: aborting due to previous error

View File

@ -5,6 +5,8 @@ LL | LinkedList::new() += 1; //~ ERROR E0368
| -----------------^^^^^
| |
| cannot use `+=` on type `std::collections::LinkedList<_>`
|
= note: an implementation of `std::ops::AddAssign` might be missing for `std::collections::LinkedList<_>`
error[E0067]: invalid left-hand side expression
--> $DIR/E0067.rs:14:5

View File

@ -3,6 +3,8 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str`
|
LL | !"a"; //~ ERROR E0600
| ^^^^
|
= note: an implementation of `std::ops::Not` might be missing for `&'static str`
error: aborting due to previous error

View File

@ -17,6 +17,8 @@ LL | x += 2;
| -^^^^^
| |
| cannot use `+=` on type `&str`
|
= note: an implementation of `std::ops::AddAssign` might be missing for `&str`
error[E0599]: no method named `z` found for type `&str` in the current scope
--> $DIR/error-festival.rs:26:7
@ -29,6 +31,8 @@ error[E0600]: cannot apply unary operator `!` to type `Question`
|
LL | !Question::Yes;
| ^^^^^^^^^^^^^^
|
= note: an implementation of `std::ops::Not` might be missing for `Question`
error[E0604]: only `u8` can be cast as `char`, not `u32`
--> $DIR/error-festival.rs:35:5

View File

@ -3,12 +3,16 @@ error[E0600]: cannot apply unary operator `-` to type `usize`
|
LL | let _max: usize = -1;
| ^^
|
= note: an implementation of `std::ops::Neg` might be missing for `usize`
error[E0600]: cannot apply unary operator `-` to type `u8`
--> $DIR/feature-gate-negate-unsigned.rs:24:14
|
LL | let _y = -x;
| ^^
|
= note: an implementation of `std::ops::Neg` might be missing for `u8`
error: aborting due to 2 previous errors

View File

@ -5,6 +5,8 @@ LL | let x = |ref x: isize| { x += 1; };
| -^^^^^
| |
| cannot use `+=` on type `&isize`
|
= note: an implementation of `std::ops::AddAssign` might be missing for `&isize`
error: aborting due to previous error

View File

@ -3,6 +3,8 @@ error[E0600]: cannot apply unary operator `!` to type `!`
|
LL | let x: ! = ! { return; }; //~ ERROR unreachable
| ^^^^^^^^^^^^^
|
= note: an implementation of `std::ops::Not` might be missing for `!`
error: unreachable expression
--> $DIR/expr_unary.rs:17:16