Auto merge of #117292 - estebank:issue-80446, r=davidtwco
Detect misparsed binop caused by missing semi When encountering ```rust foo() *bar = baz; ``` We currently emit potentially two errors, one for the return type of `foo` not being multiplicative by the type of `bar`, and another for `foo() * bar` not being assignable. We now check for this case and suggest adding a semicolon in the right place and emit only a single error. Fix #80446.
This commit is contained in:
commit
fb61292105
@ -959,12 +959,39 @@ pub(crate) fn check_lhs_assignable(
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
});
|
||||
self.check_for_missing_semi(lhs, &mut err);
|
||||
|
||||
adjust_err(&mut err);
|
||||
|
||||
err.emit();
|
||||
}
|
||||
|
||||
/// Check if the expression that could not be assigned to was a typoed expression that
|
||||
pub fn check_for_missing_semi(
|
||||
&self,
|
||||
expr: &'tcx hir::Expr<'tcx>,
|
||||
err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>,
|
||||
) -> bool {
|
||||
if let hir::ExprKind::Binary(binop, lhs, rhs) = expr.kind
|
||||
&& let hir::BinOpKind::Mul = binop.node
|
||||
&& self.tcx.sess.source_map().is_multiline(lhs.span.between(rhs.span))
|
||||
&& rhs.is_syntactic_place_expr()
|
||||
{
|
||||
// v missing semicolon here
|
||||
// foo()
|
||||
// *bar = baz;
|
||||
// (#80446).
|
||||
err.span_suggestion_verbose(
|
||||
lhs.span.shrink_to_hi(),
|
||||
"you might have meant to write a semicolon here",
|
||||
";".to_string(),
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
// Check if an expression `original_expr_id` comes from the condition of a while loop,
|
||||
/// as opposed from the body of a while loop, which we can naively check by iterating
|
||||
/// parents until we find a loop...
|
||||
|
@ -379,6 +379,13 @@ fn check_overloaded_binop(
|
||||
(err, output_def_id)
|
||||
}
|
||||
};
|
||||
if self.check_for_missing_semi(expr, &mut err)
|
||||
&& let hir::Node::Expr(expr) = self.tcx.hir().get_parent(expr.hir_id)
|
||||
&& let hir::ExprKind::Assign(..) = expr.kind
|
||||
{
|
||||
// We defer to the later error produced by `check_lhs_assignable`.
|
||||
err.delay_as_bug();
|
||||
}
|
||||
|
||||
let suggest_deref_binop =
|
||||
|err: &mut DiagnosticBuilder<'_, _>, lhs_deref_ty: Ty<'tcx>| {
|
||||
|
10
tests/ui/binop/false-binop-caused-by-missing-semi.fixed
Normal file
10
tests/ui/binop/false-binop-caused-by-missing-semi.fixed
Normal file
@ -0,0 +1,10 @@
|
||||
// run-rustfix
|
||||
fn foo() {}
|
||||
fn main() {
|
||||
let mut y = 42;
|
||||
let x = &mut y;
|
||||
foo();
|
||||
*x = 0; //~ ERROR invalid left-hand side of assignment
|
||||
let _ = x;
|
||||
println!("{y}");
|
||||
}
|
10
tests/ui/binop/false-binop-caused-by-missing-semi.rs
Normal file
10
tests/ui/binop/false-binop-caused-by-missing-semi.rs
Normal file
@ -0,0 +1,10 @@
|
||||
// run-rustfix
|
||||
fn foo() {}
|
||||
fn main() {
|
||||
let mut y = 42;
|
||||
let x = &mut y;
|
||||
foo()
|
||||
*x = 0; //~ ERROR invalid left-hand side of assignment
|
||||
let _ = x;
|
||||
println!("{y}");
|
||||
}
|
17
tests/ui/binop/false-binop-caused-by-missing-semi.stderr
Normal file
17
tests/ui/binop/false-binop-caused-by-missing-semi.stderr
Normal file
@ -0,0 +1,17 @@
|
||||
error[E0070]: invalid left-hand side of assignment
|
||||
--> $DIR/false-binop-caused-by-missing-semi.rs:7:8
|
||||
|
|
||||
LL | / foo()
|
||||
LL | | *x = 0;
|
||||
| | - ^
|
||||
| |______|
|
||||
| cannot assign to this expression
|
||||
|
|
||||
help: you might have meant to write a semicolon here
|
||||
|
|
||||
LL | foo();
|
||||
| +
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0070`.
|
Loading…
Reference in New Issue
Block a user