Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

For [E0308]: mismatched types, when expr is in an arm's body, not add semicolon ';' at the end of it. #126455

Merged
merged 1 commit into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 51 additions & 9 deletions compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,8 @@ use rustc_middle::lint::in_external_macro;
use rustc_middle::middle::stability::EvalResult;
use rustc_middle::span_bug;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{
self, suggest_constraining_type_params, Article, Binder, IsSuggestable, Ty, TypeVisitableExt,
Upcast,
};
use rustc_middle::ty::{self, suggest_constraining_type_params, Article, Binder};
use rustc_middle::ty::{IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Upcast};
use rustc_session::errors::ExprParenthesesNeeded;
use rustc_span::source_map::Spanned;
use rustc_span::symbol::{sym, Ident};
Expand Down Expand Up @@ -1125,12 +1123,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.tcx.hir().span_with_body(self.tcx.local_def_id_to_hir_id(fn_id)),
)
{
err.multipart_suggestion(
// When the expr is in a match arm's body, we shouldn't add semicolon ';' at the end.
// For example:
// fn mismatch_types() -> i32 {
// match 1 {
// x => dbg!(x),
// }
// todo!()
// }
// -------------^^^^^^^-
// Don't add semicolon `;` at the end of `dbg!(x)` expr
fn is_in_arm<'tcx>(expr: &'tcx hir::Expr<'tcx>, tcx: TyCtxt<'tcx>) -> bool {
for (_, node) in tcx.hir().parent_iter(expr.hir_id) {
match node {
hir::Node::Block(block) => {
if let Some(ret) = block.expr
&& ret.hir_id == expr.hir_id
{
continue;
}
}
hir::Node::Arm(arm) => {
if let hir::ExprKind::Block(block, _) = arm.body.kind
&& let Some(ret) = block.expr
&& ret.hir_id == expr.hir_id
{
return true;
}
}
hir::Node::Expr(e) if let hir::ExprKind::Block(block, _) = e.kind => {
if let Some(ret) = block.expr
&& ret.hir_id == expr.hir_id
{
continue;
}
}
_ => {
return false;
}
}
}

false
}
let mut suggs = vec![(span.shrink_to_lo(), "return ".to_string())];
if !is_in_arm(expr, self.tcx) {
suggs.push((span.shrink_to_hi(), ";".to_string()));
}
err.multipart_suggestion_verbose(
"you might have meant to return this value",
vec![
(span.shrink_to_lo(), "return ".to_string()),
(span.shrink_to_hi(), ";".to_string()),
],
suggs,
Applicability::MaybeIncorrect,
);
}
Expand Down
34 changes: 34 additions & 0 deletions tests/ui/mismatched_types/mismatched-types-issue-126222.fixed
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//@ run-rustfix
#![allow(unreachable_code, dead_code)]

fn main() {
fn mismatch_types1() -> i32 {
match 1 {
x => return dbg!(x), //~ ERROR mismatched types
}
todo!()
}

fn mismatch_types2() -> i32 {
match 2 {
x => {
return dbg!(x) //~ ERROR mismatched types
}
}
todo!()
}

fn mismatch_types3() -> i32 {
match 1 {
_ => return dbg!(1) //~ ERROR mismatched types
}
todo!()
}

fn mismatch_types4() -> i32 {
match 1 {
_ => {return dbg!(1)} //~ ERROR mismatched types
}
todo!()
}
}
34 changes: 34 additions & 0 deletions tests/ui/mismatched_types/mismatched-types-issue-126222.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
//@ run-rustfix
#![allow(unreachable_code, dead_code)]

fn main() {
fn mismatch_types1() -> i32 {
match 1 {
x => dbg!(x), //~ ERROR mismatched types
}
todo!()
}

fn mismatch_types2() -> i32 {
match 2 {
x => {
dbg!(x) //~ ERROR mismatched types
}
}
todo!()
}

fn mismatch_types3() -> i32 {
match 1 {
_ => dbg!(1) //~ ERROR mismatched types
}
todo!()
}

fn mismatch_types4() -> i32 {
match 1 {
_ => {dbg!(1)} //~ ERROR mismatched types
}
todo!()
}
}
51 changes: 51 additions & 0 deletions tests/ui/mismatched_types/mismatched-types-issue-126222.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
error[E0308]: mismatched types
--> $DIR/mismatched-types-issue-126222.rs:7:18
|
LL | x => dbg!(x),
| ^^^^^^^ expected `()`, found integer
|
= note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
help: you might have meant to return this value
|
LL | x => return dbg!(x),
| ++++++

error[E0308]: mismatched types
--> $DIR/mismatched-types-issue-126222.rs:15:17
|
LL | dbg!(x)
| ^^^^^^^ expected `()`, found integer
|
= note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
help: you might have meant to return this value
|
LL | return dbg!(x)
| ++++++
Comment on lines +20 to +23
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm somewhat surprised: shouldn't these suggestions include a trailing ;?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm assuming this is because dbg expands to a block expression, right?

Copy link
Contributor Author

@surechen surechen Jun 23, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm somewhat surprised: shouldn't these suggestions include a trailing ;?

Thank you.
Here I think because in the return expression after match arm the "; " is unnecessary, and the diagnostic suggestion may make error expr like "return something; ,", so in this case, I recommend using the return something without semicolon ;.
For me, it's not necessary to add ';' here whether it's expanded into a block expr or not. I'm not sure if I'm thinking about this fully. Please help me give an accurate judgement.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is idiomatic for statements like return to be ended with a ;, regardless of whether it is valid code or not. That being said, it doesn't matter as much, as long as the suggestions produce valid code.


error[E0308]: mismatched types
--> $DIR/mismatched-types-issue-126222.rs:23:18
|
LL | _ => dbg!(1)
| ^^^^^^^ expected `()`, found integer
|
= note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
help: you might have meant to return this value
|
LL | _ => return dbg!(1)
| ++++++

error[E0308]: mismatched types
--> $DIR/mismatched-types-issue-126222.rs:30:19
|
LL | _ => {dbg!(1)}
| ^^^^^^^ expected `()`, found integer
|
= note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info)
help: you might have meant to return this value
|
LL | _ => {return dbg!(1)}
| ++++++

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0308`.
Loading