Skip to content

Commit 265bc31

Browse files
committed
added missing implementation hint
1 parent 835b864 commit 265bc31

File tree

8 files changed

+110
-69
lines changed

8 files changed

+110
-69
lines changed

src/librustc_typeck/check/op.rs

Lines changed: 92 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -246,77 +246,92 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
246246
Err(()) => {
247247
// error types are considered "builtin"
248248
if !lhs_ty.references_error() {
249-
if let IsAssign::Yes = is_assign {
250-
struct_span_err!(self.tcx.sess, expr.span, E0368,
251-
"binary assignment operation `{}=` \
252-
cannot be applied to type `{}`",
253-
op.node.as_str(),
254-
lhs_ty)
255-
.span_label(lhs_expr.span,
256-
format!("cannot use `{}=` on type `{}`",
257-
op.node.as_str(), lhs_ty))
258-
.emit();
259-
} else {
260-
let mut err = struct_span_err!(self.tcx.sess, expr.span, E0369,
261-
"binary operation `{}` cannot be applied to type `{}`",
262-
op.node.as_str(),
263-
lhs_ty);
264-
265-
if let TypeVariants::TyRef(_, ref ty_mut) = lhs_ty.sty {
266-
if {
267-
!self.infcx.type_moves_by_default(self.param_env,
268-
ty_mut.ty,
269-
lhs_expr.span) &&
270-
self.lookup_op_method(ty_mut.ty,
271-
&[rhs_ty],
272-
Op::Binary(op, is_assign))
273-
.is_ok()
274-
} {
275-
err.note(
276-
&format!(
277-
"this is a reference to a type that `{}` can be applied \
278-
to; you need to dereference this variable once for this \
279-
operation to work",
280-
op.node.as_str()));
281-
}
249+
let (mut err, missing_trait) = match is_assign{
250+
IsAssign::Yes => {
251+
let mut err = struct_span_err!(self.tcx.sess, expr.span, E0368,
252+
"binary assignment operation `{}=` \
253+
cannot be applied to type `{}`",
254+
op.node.as_str(),
255+
lhs_ty);
256+
err.span_label(lhs_expr.span,
257+
format!("cannot use `{}=` on type `{}`",
258+
op.node.as_str(), lhs_ty));
259+
let missing_trait = match op.node {
260+
hir::BiAdd => Some("std::ops::AddAssign"),
261+
hir::BiSub => Some("std::ops::SubAssign"),
262+
hir::BiMul => Some("std::ops::MulAssign"),
263+
hir::BiDiv => Some("std::ops::DivAssign"),
264+
hir::BiRem => Some("std::ops::RemAssign"),
265+
hir::BiBitAnd => Some("std::ops::BitAndAssign"),
266+
hir::BiBitXor => Some("std::ops::BitXorAssign"),
267+
hir::BiBitOr => Some("std::ops::BitOrAssign"),
268+
hir::BiShl => Some("std::ops::ShlAssign"),
269+
hir::BiShr => Some("std::ops::ShrAssign"),
270+
_ => None
271+
};
272+
(err, missing_trait)
282273
}
283-
284-
let missing_trait = match op.node {
285-
hir::BiAdd => Some("std::ops::Add"),
286-
hir::BiSub => Some("std::ops::Sub"),
287-
hir::BiMul => Some("std::ops::Mul"),
288-
hir::BiDiv => Some("std::ops::Div"),
289-
hir::BiRem => Some("std::ops::Rem"),
290-
hir::BiBitAnd => Some("std::ops::BitAnd"),
291-
hir::BiBitOr => Some("std::ops::BitOr"),
292-
hir::BiShl => Some("std::ops::Shl"),
293-
hir::BiShr => Some("std::ops::Shr"),
294-
hir::BiEq | hir::BiNe => Some("std::cmp::PartialEq"),
295-
hir::BiLt | hir::BiLe | hir::BiGt | hir::BiGe =>
296-
Some("std::cmp::PartialOrd"),
297-
_ => None
298-
};
299-
300-
if let Some(missing_trait) = missing_trait {
301-
if missing_trait == "std::ops::Add" &&
302-
self.check_str_addition(expr, lhs_expr, rhs_expr, lhs_ty,
303-
rhs_ty, &mut err) {
304-
// This has nothing here because it means we did string
305-
// concatenation (e.g. "Hello " + "World!"). This means
306-
// we don't want the note in the else clause to be emitted
307-
} else if let ty::TyParam(_) = lhs_ty.sty {
308-
// FIXME: point to span of param
309-
err.note(
310-
&format!("`{}` might need a bound for `{}`",
311-
lhs_ty, missing_trait));
312-
} else {
313-
err.note(
314-
&format!("an implementation of `{}` might be missing for `{}`",
315-
missing_trait, lhs_ty));
274+
IsAssign::No => {
275+
let mut err = struct_span_err!(self.tcx.sess, expr.span, E0369,
276+
"binary operation `{}` cannot be applied to type `{}`",
277+
op.node.as_str(),
278+
lhs_ty);
279+
let missing_trait = match op.node {
280+
hir::BiAdd => Some("std::ops::Add"),
281+
hir::BiSub => Some("std::ops::Sub"),
282+
hir::BiMul => Some("std::ops::Mul"),
283+
hir::BiDiv => Some("std::ops::Div"),
284+
hir::BiRem => Some("std::ops::Rem"),
285+
hir::BiBitAnd => Some("std::ops::BitAnd"),
286+
hir::BiBitXor => Some("std::ops::BitXor"),
287+
hir::BiBitOr => Some("std::ops::BitOr"),
288+
hir::BiShl => Some("std::ops::Shl"),
289+
hir::BiShr => Some("std::ops::Shr"),
290+
hir::BiEq | hir::BiNe => Some("std::cmp::PartialEq"),
291+
hir::BiLt | hir::BiLe | hir::BiGt | hir::BiGe =>
292+
Some("std::cmp::PartialOrd"),
293+
_ => None
294+
};
295+
if let TypeVariants::TyRef(_, ref ty_mut) = lhs_ty.sty {
296+
if {
297+
!self.infcx.type_moves_by_default(self.param_env,
298+
ty_mut.ty,
299+
lhs_expr.span) &&
300+
self.lookup_op_method(ty_mut.ty,
301+
&[rhs_ty],
302+
Op::Binary(op, is_assign))
303+
.is_ok()
304+
} {
305+
err.note(
306+
&format!(
307+
"this is a reference to a type that `{}` can be \
308+
applied to; you need to dereference this variable \
309+
once for this operation to work",
310+
op.node.as_str()));
311+
}
316312
}
313+
(err, missing_trait)
314+
}
315+
};
316+
if let Some(missing_trait) = missing_trait {
317+
if missing_trait == "std::ops::Add" &&
318+
self.check_str_addition(expr, lhs_expr, rhs_expr, lhs_ty,
319+
rhs_ty, &mut err) {
320+
// This has nothing here because it means we did string
321+
// concatenation (e.g. "Hello " + "World!"). This means
322+
// we don't want the note in the else clause to be emitted
323+
} else if let ty::TyParam(_) = lhs_ty.sty {
324+
// FIXME: point to span of param
325+
err.note(
326+
&format!("`{}` might need a bound for `{}`",
327+
lhs_ty, missing_trait));
328+
} else {
329+
err.note(
330+
&format!("an implementation of `{}` might be missing for `{}`",
331+
missing_trait, lhs_ty));
317332
}
318-
err.emit();
319333
}
334+
err.emit();
320335
}
321336
self.tcx.types.err
322337
}
@@ -393,9 +408,17 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
393408
Err(()) => {
394409
let actual = self.resolve_type_vars_if_possible(&operand_ty);
395410
if !actual.references_error() {
396-
struct_span_err!(self.tcx.sess, ex.span, E0600,
411+
let mut err = struct_span_err!(self.tcx.sess, ex.span, E0600,
397412
"cannot apply unary operator `{}` to type `{}`",
398-
op.as_str(), actual).emit();
413+
op.as_str(), actual);
414+
let missing_trait = match op {
415+
hir::UnNeg => "std::ops::Neg",
416+
hir::UnNot => "std::ops::Not",
417+
hir::UnDeref => "std::ops::UnDerf"
418+
};
419+
err.note(&format!("an implementation of `{}` might be missing for `{}`",
420+
missing_trait, operand_ty));
421+
err.emit();
399422
}
400423
self.tcx.types.err
401424
}

src/test/ui/codemap_tests/issue-28308.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str`
33
|
44
LL | assert!("foo");
55
| ^^^^^^^^^^^^^^^
6+
|
7+
= note: an implementation of `std::ops::Not` might be missing for `&'static str`
68

79
error: aborting due to previous error
810

src/test/ui/error-codes/E0067.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ LL | LinkedList::new() += 1; //~ ERROR E0368
55
| -----------------^^^^^
66
| |
77
| cannot use `+=` on type `std::collections::LinkedList<_>`
8+
|
9+
= note: an implementation of `std::ops::AddAssign` might be missing for `std::collections::LinkedList<_>`
810

911
error[E0067]: invalid left-hand side expression
1012
--> $DIR/E0067.rs:14:5

src/test/ui/error-codes/E0600.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ error[E0600]: cannot apply unary operator `!` to type `&'static str`
33
|
44
LL | !"a"; //~ ERROR E0600
55
| ^^^^
6+
|
7+
= note: an implementation of `std::ops::Not` might be missing for `&'static str`
68

79
error: aborting due to previous error
810

src/test/ui/error-festival.stderr

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ LL | x += 2;
1717
| -^^^^^
1818
| |
1919
| cannot use `+=` on type `&str`
20+
|
21+
= note: an implementation of `std::ops::AddAssign` might be missing for `&str`
2022

2123
error[E0599]: no method named `z` found for type `&str` in the current scope
2224
--> $DIR/error-festival.rs:26:7
@@ -29,6 +31,8 @@ error[E0600]: cannot apply unary operator `!` to type `Question`
2931
|
3032
LL | !Question::Yes;
3133
| ^^^^^^^^^^^^^^
34+
|
35+
= note: an implementation of `std::ops::Not` might be missing for `Question`
3236

3337
error[E0604]: only `u8` can be cast as `char`, not `u32`
3438
--> $DIR/error-festival.rs:35:5

src/test/ui/feature-gate-negate-unsigned.stderr

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,16 @@ error[E0600]: cannot apply unary operator `-` to type `usize`
33
|
44
LL | let _max: usize = -1;
55
| ^^
6+
|
7+
= note: an implementation of `std::ops::Neg` might be missing for `usize`
68

79
error[E0600]: cannot apply unary operator `-` to type `u8`
810
--> $DIR/feature-gate-negate-unsigned.rs:24:14
911
|
1012
LL | let _y = -x;
1113
| ^^
14+
|
15+
= note: an implementation of `std::ops::Neg` might be missing for `u8`
1216

1317
error: aborting due to 2 previous errors
1418

src/test/ui/issue-5239-1.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ LL | let x = |ref x: isize| { x += 1; };
55
| -^^^^^
66
| |
77
| cannot use `+=` on type `&isize`
8+
|
9+
= note: an implementation of `std::ops::AddAssign` might be missing for `&isize`
810

911
error: aborting due to previous error
1012

src/test/ui/reachable/expr_unary.stderr

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ error[E0600]: cannot apply unary operator `!` to type `!`
33
|
44
LL | let x: ! = ! { return; }; //~ ERROR unreachable
55
| ^^^^^^^^^^^^^
6+
|
7+
= note: an implementation of `std::ops::Not` might be missing for `!`
68

79
error: unreachable expression
810
--> $DIR/expr_unary.rs:17:16

0 commit comments

Comments
 (0)