diff options
| author | Guillaume Gomez <guillaume1.gomez@gmail.com> | 2021-02-20 20:36:57 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-02-20 20:36:57 +0100 |
| commit | 39af0257411b89c93d8cdffeb26a8d58db72efa7 (patch) | |
| tree | 3b324a493d0109463dee035c1e3ac65758d5720c | |
| parent | d38f6e82a4c1aac312b30b2566827bd19a0fb412 (diff) | |
| parent | 9ef67e09a4c2fdfd528ac174e3aec2fe0e97f347 (diff) | |
| download | rust-39af0257411b89c93d8cdffeb26a8d58db72efa7.tar.gz rust-39af0257411b89c93d8cdffeb26a8d58db72efa7.zip | |
Rollup merge of #81991 - osa1:issue81839, r=estebank
Fix panic in 'remove semicolon' when types are not local It's not possible to check if removing a semicolon fixes the type error when checking match arms and one or both of the last arm's and the current arm's return types are imported "opaque" types. In these cases we don't generate a "consider removing semicolon" suggestions. Fixes #81839 --- I'm not sure how to add a test for this. I think the test would need at least two crates. Do we have any existing tests that do this so that I can take a look?
| -rw-r--r-- | compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs | 17 | ||||
| -rw-r--r-- | src/test/ui/suggestions/auxiliary/issue-81839.rs | 9 | ||||
| -rw-r--r-- | src/test/ui/suggestions/issue-81839.rs | 17 | ||||
| -rw-r--r-- | src/test/ui/suggestions/issue-81839.stderr | 27 | ||||
| -rw-r--r-- | src/test/ui/suggestions/match-prev-arm-needing-semi.stderr | 9 |
5 files changed, 71 insertions, 8 deletions
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 7f27325f7f9..f5e9cc1efcc 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -1074,13 +1074,26 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; let last_expr_ty = self.node_ty(last_expr.hir_id); let needs_box = match (last_expr_ty.kind(), expected_ty.kind()) { + (ty::Opaque(last_def_id, _), ty::Opaque(exp_def_id, _)) + if last_def_id == exp_def_id => + { + StatementAsExpression::CorrectType + } (ty::Opaque(last_def_id, last_bounds), ty::Opaque(exp_def_id, exp_bounds)) => { debug!( "both opaque, likely future {:?} {:?} {:?} {:?}", last_def_id, last_bounds, exp_def_id, exp_bounds ); - let last_hir_id = self.tcx.hir().local_def_id_to_hir_id(last_def_id.expect_local()); - let exp_hir_id = self.tcx.hir().local_def_id_to_hir_id(exp_def_id.expect_local()); + + let (last_local_id, exp_local_id) = + match (last_def_id.as_local(), exp_def_id.as_local()) { + (Some(last_hir_id), Some(exp_hir_id)) => (last_hir_id, exp_hir_id), + (_, _) => return None, + }; + + let last_hir_id = self.tcx.hir().local_def_id_to_hir_id(last_local_id); + let exp_hir_id = self.tcx.hir().local_def_id_to_hir_id(exp_local_id); + match ( &self.tcx.hir().expect_item(last_hir_id).kind, &self.tcx.hir().expect_item(exp_hir_id).kind, diff --git a/src/test/ui/suggestions/auxiliary/issue-81839.rs b/src/test/ui/suggestions/auxiliary/issue-81839.rs new file mode 100644 index 00000000000..5683c45adf2 --- /dev/null +++ b/src/test/ui/suggestions/auxiliary/issue-81839.rs @@ -0,0 +1,9 @@ +// edition:2018 + +pub struct Test {} + +impl Test { + pub async fn answer_str(&self, _s: &str) -> Test { + Test {} + } +} diff --git a/src/test/ui/suggestions/issue-81839.rs b/src/test/ui/suggestions/issue-81839.rs new file mode 100644 index 00000000000..0b9b7aefe73 --- /dev/null +++ b/src/test/ui/suggestions/issue-81839.rs @@ -0,0 +1,17 @@ +// aux-build:issue-81839.rs +// edition:2018 + +extern crate issue_81839; + +async fn test(ans: &str, num: i32, cx: &issue_81839::Test) -> u32 { + match num { + 1 => { + cx.answer_str("hi"); + } + _ => cx.answer_str("hi"), //~ `match` arms have incompatible types + } + + 1 +} + +fn main() {} diff --git a/src/test/ui/suggestions/issue-81839.stderr b/src/test/ui/suggestions/issue-81839.stderr new file mode 100644 index 00000000000..1a289d39e44 --- /dev/null +++ b/src/test/ui/suggestions/issue-81839.stderr @@ -0,0 +1,27 @@ +error[E0308]: `match` arms have incompatible types + --> $DIR/issue-81839.rs:11:14 + | +LL | / match num { +LL | | 1 => { +LL | | cx.answer_str("hi"); + | | -------------------- + | | | | + | | | help: consider removing this semicolon + | | this is found to be of type `()` +LL | | } +LL | | _ => cx.answer_str("hi"), + | | ^^^^^^^^^^^^^^^^^^^ expected `()`, found opaque type +LL | | } + | |_____- `match` arms have incompatible types + | + ::: $DIR/auxiliary/issue-81839.rs:6:49 + | +LL | pub async fn answer_str(&self, _s: &str) -> Test { + | ---- the `Output` of this `async fn`'s found opaque type + | + = note: expected type `()` + found opaque type `impl Future` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr index e9803a78f94..fae0c498b44 100644 --- a/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr +++ b/src/test/ui/suggestions/match-prev-arm-needing-semi.stderr @@ -24,13 +24,10 @@ help: consider `await`ing on the `Future` | LL | false => async_dummy().await, | ^^^^^^ -help: consider removing this semicolon and boxing the expressions - | -LL | Box::new(async_dummy()) -LL | -LL | } -LL | false => Box::new(async_dummy()), +help: consider removing this semicolon | +LL | async_dummy() + | -- error[E0308]: `match` arms have incompatible types --> $DIR/match-prev-arm-needing-semi.rs:39:18 |
