Skip to content

Commit

Permalink
Suggest wapping expr in parentheses on invalid unary negation
Browse files Browse the repository at this point in the history
Fixes #88701
  • Loading branch information
andrewhickman committed Sep 6, 2021
1 parent 8ceea01 commit d6ce326
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 37 deletions.
78 changes: 43 additions & 35 deletions compiler/rustc_typeck/src/check/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -680,42 +680,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ex.span,
format!("cannot apply unary operator `{}`", op.as_str()),
);
match actual.kind() {
Uint(_) if op == hir::UnOp::Neg => {
err.note("unsigned values cannot be negated");

if let hir::ExprKind::Unary(
_,
hir::Expr {
kind:
hir::ExprKind::Lit(Spanned {
node: ast::LitKind::Int(1, _),
..
}),
..
},
) = ex.kind
{
err.span_suggestion(
ex.span,
&format!(
"you may have meant the maximum value of `{}`",
actual
),
format!("{}::MAX", actual),
Applicability::MaybeIncorrect,
);

let sp = self.tcx.sess.source_map().start_point(ex.span);
if let Some(sp) =
self.tcx.sess.parse_sess.ambiguous_block_expr_parse.borrow().get(&sp)
{
self.tcx.sess.parse_sess.expr_parentheses_needed(&mut err, *sp);
} else {
match actual.kind() {
Uint(_) if op == hir::UnOp::Neg => {
err.note("unsigned values cannot be negated");

if let hir::ExprKind::Unary(
_,
hir::Expr {
kind:
hir::ExprKind::Lit(Spanned {
node: ast::LitKind::Int(1, _),
..
}),
..
},
) = ex.kind
{
err.span_suggestion(
ex.span,
&format!(
"you may have meant the maximum value of `{}`",
actual
),
format!("{}::MAX", actual),
Applicability::MaybeIncorrect,
);
}
}
Str | Never | Char | Tuple(_) | Array(_, _) => {}
Ref(_, ref lty, _) if *lty.kind() == Str => {}
_ => {
let missing_trait = match op {
hir::UnOp::Neg => "std::ops::Neg",
hir::UnOp::Not => "std::ops::Not",
hir::UnOp::Deref => "std::ops::UnDerf",
};
suggest_impl_missing(&mut err, operand_ty, &missing_trait);
}
}
Str | Never | Char | Tuple(_) | Array(_, _) => {}
Ref(_, ref lty, _) if *lty.kind() == Str => {}
_ => {
let missing_trait = match op {
hir::UnOp::Neg => "std::ops::Neg",
hir::UnOp::Not => "std::ops::Not",
hir::UnOp::Deref => "std::ops::UnDerf",
};
suggest_impl_missing(&mut err, operand_ty, &missing_trait);
}
}
err.emit();
Expand Down
5 changes: 5 additions & 0 deletions src/test/ui/parser/expr-as-stmt.fixed
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ fn moo(x: u32) -> bool {
}) > 0 //~ ERROR expected expression
}

fn qux() -> u32 {
({2}) - 2 //~ ERROR cannot apply unary operator `-` to type `u32`
//~^ ERROR mismatched types
}

fn main() {}
5 changes: 5 additions & 0 deletions src/test/ui/parser/expr-as-stmt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,9 @@ fn moo(x: u32) -> bool {
} > 0 //~ ERROR expected expression
}

fn qux() -> u32 {
{2} - 2 //~ ERROR cannot apply unary operator `-` to type `u32`
//~^ ERROR mismatched types
}

fn main() {}
26 changes: 24 additions & 2 deletions src/test/ui/parser/expr-as-stmt.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,29 @@ help: parentheses are required to parse this as an expression
LL | ({ 3 }) * 3
| + +

error: aborting due to 9 previous errors
error[E0308]: mismatched types
--> $DIR/expr-as-stmt.rs:36:6
|
LL | {2} - 2
| ^ expected `()`, found integer
|
help: you might have meant to return this value
|
LL | {return 2;} - 2
| ++++++ +

error[E0600]: cannot apply unary operator `-` to type `u32`
--> $DIR/expr-as-stmt.rs:36:9
|
LL | {2} - 2
| ^^^ cannot apply unary operator `-`
|
help: parentheses are required to parse this as an expression
|
LL | ({2}) - 2
| + +

error: aborting due to 11 previous errors

Some errors have detailed explanations: E0308, E0614.
Some errors have detailed explanations: E0308, E0600, E0614.
For more information about an error, try `rustc --explain E0308`.

0 comments on commit d6ce326

Please sign in to comment.