From e7618756c067081c4d347b1ad5f500af0bb534a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 12 Oct 2023 22:20:17 +0000 Subject: [PATCH] On type error involving closure, avoid ICE When we encounter a type error involving a closure, we try to typeck prior closure invocations to see if they influenced the current expected type. When trying to do so, ensure that the closure was defined in our current scope. Fix #116658. --- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 3 +- ...ype-mismatch-closure-from-another-scope.rs | 23 ++++++++++ ...mismatch-closure-from-another-scope.stderr | 44 +++++++++++++++++++ 3 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 tests/ui/unboxed-closures/unboxed-closures-type-mismatch-closure-from-another-scope.rs create mode 100644 tests/ui/unboxed-closures/unboxed-closures-type-mismatch-closure-from-another-scope.stderr diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 9b7f8f8031036..c762e68448051 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -2036,7 +2036,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let typeck = self.typeck_results.borrow(); for (rcvr, args) in call_finder.calls { - if let Some(rcvr_ty) = typeck.node_type_opt(rcvr.hir_id) + if rcvr.hir_id.owner == typeck.hir_owner + && let Some(rcvr_ty) = typeck.node_type_opt(rcvr.hir_id) && let ty::Closure(call_def_id, _) = rcvr_ty.kind() && def_id == *call_def_id && let Some(idx) = expected_idx diff --git a/tests/ui/unboxed-closures/unboxed-closures-type-mismatch-closure-from-another-scope.rs b/tests/ui/unboxed-closures/unboxed-closures-type-mismatch-closure-from-another-scope.rs new file mode 100644 index 0000000000000..157383fede11f --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-type-mismatch-closure-from-another-scope.rs @@ -0,0 +1,23 @@ +fn test() { + let x = match **x { //~ ERROR + Some(&a) if { panic!() } => {} + }; + let mut p = &x; + + { + let mut closure = expect_sig(|p, y| *p = y); + closure(&mut p, &y); //~ ERROR + //~^ ERROR + } + + deref(p); //~ ERROR +} + +fn expect_sig(f: F) -> F +where + F: FnMut(&mut &i32, &i32), +{ + f +} + +fn main() {} diff --git a/tests/ui/unboxed-closures/unboxed-closures-type-mismatch-closure-from-another-scope.stderr b/tests/ui/unboxed-closures/unboxed-closures-type-mismatch-closure-from-another-scope.stderr new file mode 100644 index 0000000000000..1470c32d7de90 --- /dev/null +++ b/tests/ui/unboxed-closures/unboxed-closures-type-mismatch-closure-from-another-scope.stderr @@ -0,0 +1,44 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/unboxed-closures-type-mismatch-closure-from-another-scope.rs:2:21 + | +LL | let x = match **x { + | ^ not found in this scope + +error[E0425]: cannot find value `y` in this scope + --> $DIR/unboxed-closures-type-mismatch-closure-from-another-scope.rs:9:26 + | +LL | closure(&mut p, &y); + | ^ help: a local variable with a similar name exists: `p` + +error[E0308]: mismatched types + --> $DIR/unboxed-closures-type-mismatch-closure-from-another-scope.rs:9:17 + | +LL | closure(&mut p, &y); + | ------- ^^^^^^ expected `&mut &i32`, found `&mut &()` + | | + | arguments to this function are incorrect + | + = note: expected mutable reference `&mut &i32` + found mutable reference `&mut &()` +note: closure parameter defined here + --> $DIR/unboxed-closures-type-mismatch-closure-from-another-scope.rs:8:39 + | +LL | let mut closure = expect_sig(|p, y| *p = y); + | ^ + +error[E0425]: cannot find function `deref` in this scope + --> $DIR/unboxed-closures-type-mismatch-closure-from-another-scope.rs:13:5 + | +LL | deref(p); + | ^^^^^ not found in this scope + | +help: use the `.` operator to call the method `Deref::deref` on `&&()` + | +LL - deref(p); +LL + p.deref(); + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0308, E0425. +For more information about an error, try `rustc --explain E0308`.