Skip to content

Commit f28d8b1

Browse files
committed
suggest constraining param for unary ops when missing trait impl
1 parent 051d117 commit f28d8b1

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

compiler/rustc_typeck/src/check/op.rs

+21
Original file line numberDiff line numberDiff line change
@@ -672,6 +672,27 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
672672
ex.span,
673673
format!("cannot apply unary operator `{}`", op.as_str()),
674674
);
675+
let missing_trait = match op {
676+
hir::UnOp::Deref => unreachable!("check unary op `-` or `!` only"),
677+
hir::UnOp::Not => "std::ops::Not",
678+
hir::UnOp::Neg => "std::ops::Neg",
679+
};
680+
let mut visitor = TypeParamVisitor(vec![]);
681+
visitor.visit_ty(operand_ty);
682+
if let [ty] = &visitor.0[..] {
683+
if let ty::Param(p) = *operand_ty.kind() {
684+
suggest_constraining_param(
685+
self.tcx,
686+
self.body_id,
687+
&mut err,
688+
*ty,
689+
operand_ty,
690+
missing_trait,
691+
p,
692+
true,
693+
);
694+
}
695+
}
675696

676697
let sp = self.tcx.sess.source_map().start_point(ex.span);
677698
if let Some(sp) =

src/test/ui/type/type-check/missing_trait_impl.rs

+6
Original file line numberDiff line numberDiff line change
@@ -8,3 +8,9 @@ fn foo<T>(x: T, y: T) {
88
fn bar<T>(x: T) {
99
x += x; //~ ERROR binary assignment operation `+=` cannot be applied to type `T`
1010
}
11+
12+
fn baz<T>(x: T) {
13+
let y = -x; //~ ERROR cannot apply unary operator `-` to type `T`
14+
let y = !x; //~ ERROR cannot apply unary operator `!` to type `T`
15+
let y = *x; //~ ERROR type `T` cannot be dereferenced
16+
}

src/test/ui/type/type-check/missing_trait_impl.stderr

+30-2
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,35 @@ help: consider restricting type parameter `T`
2424
LL | fn bar<T: std::ops::AddAssign>(x: T) {
2525
| +++++++++++++++++++++
2626

27-
error: aborting due to 2 previous errors
27+
error[E0600]: cannot apply unary operator `-` to type `T`
28+
--> $DIR/missing_trait_impl.rs:13:13
29+
|
30+
LL | let y = -x;
31+
| ^^ cannot apply unary operator `-`
32+
|
33+
help: consider restricting type parameter `T`
34+
|
35+
LL | fn baz<T: std::ops::Neg<Output = T>>(x: T) {
36+
| +++++++++++++++++++++++++++
37+
38+
error[E0600]: cannot apply unary operator `!` to type `T`
39+
--> $DIR/missing_trait_impl.rs:14:13
40+
|
41+
LL | let y = !x;
42+
| ^^ cannot apply unary operator `!`
43+
|
44+
help: consider restricting type parameter `T`
45+
|
46+
LL | fn baz<T: std::ops::Not<Output = T>>(x: T) {
47+
| +++++++++++++++++++++++++++
48+
49+
error[E0614]: type `T` cannot be dereferenced
50+
--> $DIR/missing_trait_impl.rs:15:13
51+
|
52+
LL | let y = *x;
53+
| ^^
54+
55+
error: aborting due to 5 previous errors
2856

29-
Some errors have detailed explanations: E0368, E0369.
57+
Some errors have detailed explanations: E0368, E0369, E0600, E0614.
3058
For more information about an error, try `rustc --explain E0368`.

0 commit comments

Comments
 (0)