diff options
| author | Dylan DPC <99973273+Dylan-DPC@users.noreply.github.com> | 2022-07-31 17:36:44 +0530 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-07-31 17:36:44 +0530 |
| commit | 990bce4da0a02a15a11abb22b00aacc5d329ce42 (patch) | |
| tree | de2f60a8feb60d9b1a34b944b6fb872c6cead674 | |
| parent | 8b2637fd3ba839a614d578da9cad3c5897ca5aff (diff) | |
| parent | f6908be329d2be65b4de0f36393b98757c13ecad (diff) | |
| download | rust-990bce4da0a02a15a11abb22b00aacc5d329ce42.tar.gz rust-990bce4da0a02a15a11abb22b00aacc5d329ce42.zip | |
Rollup merge of #99974 - TaKO8Ki:suggest-removing-semicolon-and-boxing-the-expressions, r=compiler-errors
Suggest removing a semicolon and boxing the expressions for if-else `InferCtxt::suggest_remove_semi_or_return_binding` was not working well, so I fixed it and added a ui test.
| -rw-r--r-- | compiler/rustc_infer/src/infer/error_reporting/mod.rs | 16 | ||||
| -rw-r--r-- | src/test/ui/suggestions/if-then-neeing-semi.rs | 70 | ||||
| -rw-r--r-- | src/test/ui/suggestions/if-then-neeing-semi.stderr | 130 |
3 files changed, 210 insertions, 6 deletions
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs index 39faed0bf36..20864c657ff 100644 --- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs +++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs @@ -712,7 +712,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { opt_suggest_box_span, }) => { let then_span = self.find_block_span_from_hir_id(then_id); - let else_span = self.find_block_span_from_hir_id(then_id); + let else_span = self.find_block_span_from_hir_id(else_id); err.span_label(then_span, "expected because of this"); if let Some(sp) = outer_span { err.span_label(sp, "`if` and `else` have incompatible types"); @@ -760,11 +760,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { second_ty: Ty<'tcx>, second_span: Span, ) { - let remove_semicolon = - [(first_id, second_ty), (second_id, first_ty)].into_iter().find_map(|(id, ty)| { - let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None }; - self.could_remove_semicolon(blk, ty) - }); + let remove_semicolon = [ + (first_id, self.resolve_vars_if_possible(second_ty)), + (second_id, self.resolve_vars_if_possible(first_ty)), + ] + .into_iter() + .find_map(|(id, ty)| { + let hir::Node::Block(blk) = self.tcx.hir().get(id?) else { return None }; + self.could_remove_semicolon(blk, ty) + }); match remove_semicolon { Some((sp, StatementAsExpression::NeedsBoxing)) => { err.multipart_suggestion( diff --git a/src/test/ui/suggestions/if-then-neeing-semi.rs b/src/test/ui/suggestions/if-then-neeing-semi.rs new file mode 100644 index 00000000000..b487f013d27 --- /dev/null +++ b/src/test/ui/suggestions/if-then-neeing-semi.rs @@ -0,0 +1,70 @@ +// edition:2018 + +fn dummy() -> i32 { + 42 +} + +fn extra_semicolon() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + dummy(); //~ NOTE expected because of this + //~^ HELP consider removing this semicolon + } else { + dummy() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected `()`, found `i32` + }; +} + +async fn async_dummy() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE checked the `Output` of this `async fn`, expected opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +async fn async_dummy2() {} //~ NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE checked the `Output` of this `async fn`, found opaque type +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function +//~| NOTE while checking the return type of the `async fn` +//~| NOTE in this expansion of desugaring of `async` block or function + +async fn async_extra_semicolon_same() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + async_dummy(); //~ NOTE expected because of this + //~^ HELP consider removing this semicolon + } else { + async_dummy() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected `()`, found opaque type + //~| NOTE expected unit type `()` + //~| HELP consider `await`ing on the `Future` + }; +} + +async fn async_extra_semicolon_different() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + async_dummy(); //~ NOTE expected because of this + //~^ HELP consider removing this semicolon + } else { + async_dummy2() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected `()`, found opaque type + //~| NOTE expected unit type `()` + //~| HELP consider `await`ing on the `Future` + }; +} + +async fn async_different_futures() { + let _ = if true { + //~^ NOTE `if` and `else` have incompatible types + async_dummy() //~ NOTE expected because of this + //~| HELP consider `await`ing on both `Future`s + } else { + async_dummy2() //~ ERROR `if` and `else` have incompatible types + //~^ NOTE expected opaque type, found a different opaque type + //~| NOTE expected opaque type `impl Future<Output = ()>` + //~| NOTE distinct uses of `impl Trait` result in different opaque types + }; +} + +fn main() {} diff --git a/src/test/ui/suggestions/if-then-neeing-semi.stderr b/src/test/ui/suggestions/if-then-neeing-semi.stderr new file mode 100644 index 00000000000..d7c5818abbd --- /dev/null +++ b/src/test/ui/suggestions/if-then-neeing-semi.stderr @@ -0,0 +1,130 @@ +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:37:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | async_dummy(); + | | -------------- expected because of this +LL | | +LL | | } else { +LL | | async_dummy() + | | ^^^^^^^^^^^^^ expected `()`, found opaque type +... | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:18:24 + | +LL | async fn async_dummy() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future<Output = ()>` +help: consider `await`ing on the `Future` + | +LL | async_dummy().await + | ++++++ +help: consider removing this semicolon + | +LL - async_dummy(); +LL + async_dummy() + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:50:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | async_dummy(); + | | -------------- expected because of this +LL | | +LL | | } else { +LL | | async_dummy2() + | | ^^^^^^^^^^^^^^ expected `()`, found opaque type +... | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:24:25 + | +LL | async fn async_dummy2() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected unit type `()` + found opaque type `impl Future<Output = ()>` +help: consider `await`ing on the `Future` + | +LL | async_dummy2().await + | ++++++ +help: consider removing this semicolon and boxing the expressions + | +LL ~ Box::new(async_dummy()) +LL | +LL | } else { +LL ~ Box::new(async_dummy2()) + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:63:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | async_dummy() + | | ------------- expected because of this +LL | | +LL | | } else { +LL | | async_dummy2() + | | ^^^^^^^^^^^^^^ expected opaque type, found a different opaque type +... | +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + | +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:18:24 + | +LL | async fn async_dummy() {} + | ^ checked the `Output` of this `async fn`, expected opaque type +note: while checking the return type of the `async fn` + --> $DIR/if-then-neeing-semi.rs:24:25 + | +LL | async fn async_dummy2() {} + | ^ checked the `Output` of this `async fn`, found opaque type + = note: expected opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:18:24>) + found opaque type `impl Future<Output = ()>` (opaque type at <$DIR/if-then-neeing-semi.rs:24:25>) + = note: distinct uses of `impl Trait` result in different opaque types +help: consider `await`ing on both `Future`s + | +LL ~ async_dummy().await +LL | +LL | } else { +LL ~ async_dummy2().await + | + +error[E0308]: `if` and `else` have incompatible types + --> $DIR/if-then-neeing-semi.rs:13:9 + | +LL | let _ = if true { + | _____________- +LL | | +LL | | dummy(); + | | -------- + | | | | + | | | help: consider removing this semicolon + | | expected because of this +LL | | +LL | | } else { +LL | | dummy() + | | ^^^^^^^ expected `()`, found `i32` +LL | | +LL | | }; + | |_____- `if` and `else` have incompatible types + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0308`. |
