about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-02-09 14:41:51 +0100
committerGitHub <noreply@github.com>2024-02-09 14:41:51 +0100
commit116efb5bb10ba6264e4b6e2ee65427103f6c365a (patch)
tree544de019c4634161f946075f8d95bb2b587f1bdc
parent475c47a3c14d6c09486509029e288daced2bed86 (diff)
parente32c1ddc5274636c03697f180224f4fa6721f200 (diff)
downloadrust-116efb5bb10ba6264e4b6e2ee65427103f6c365a.tar.gz
rust-116efb5bb10ba6264e4b6e2ee65427103f6c365a.zip
Rollup merge of #120817 - compiler-errors:more-mir-errors, r=oli-obk
Fix more `ty::Error` ICEs in MIR passes

Fixes #120791 - Add a check for `ty::Error` in the `ByMove` coroutine pass
Fixes #120816 - Add a check for `ty::Error` in the MIR validator

Also a drive-by fix for a FIXME I had asked oli to add

r? oli-obk
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs36
-rw-r--r--compiler/rustc_mir_transform/src/coroutine/by_move_body.rs7
-rw-r--r--tests/ui/async-await/async-closures/tainted-body.rs13
-rw-r--r--tests/ui/async-await/async-closures/tainted-body.stderr9
-rw-r--r--tests/ui/mir/validate/error-body.rs9
-rw-r--r--tests/ui/mir/validate/error-body.stderr9
7 files changed, 73 insertions, 12 deletions
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index c4542aaa7b2..3b7b502d3d0 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -60,6 +60,8 @@ impl<'tcx> MirPass<'tcx> for Validator {
                 ty::Closure(..) => Abi::RustCall,
                 ty::CoroutineClosure(..) => Abi::RustCall,
                 ty::Coroutine(..) => Abi::Rust,
+                // No need to do MIR validation on error bodies
+                ty::Error(_) => return,
                 _ => {
                     span_bug!(body.span, "unexpected body ty: {:?} phase {:?}", body_ty, mir_phase)
                 }
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index c24f2e9f53a..2b1a9fef360 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -675,16 +675,32 @@ fn construct_error(tcx: TyCtxt<'_>, def_id: LocalDefId, guar: ErrorGuaranteed) -
                         ))),
                     )
                 }
-                ty::CoroutineClosure(did, _args) => {
-                    // FIXME(async_closures): Recover the proper error signature
-                    let inputs = tcx
-                        .closure_user_provided_sig(did.expect_local())
-                        .value
-                        .skip_binder()
-                        .inputs();
-
-                    let err = Ty::new_error(tcx, guar);
-                    (inputs.iter().map(|_| err).collect(), err, None)
+                ty::CoroutineClosure(did, args) => {
+                    let args = args.as_coroutine_closure();
+                    let sig = tcx.liberate_late_bound_regions(
+                        def_id.to_def_id(),
+                        args.coroutine_closure_sig(),
+                    );
+                    let self_ty = match args.kind() {
+                        ty::ClosureKind::Fn => {
+                            Ty::new_imm_ref(tcx, tcx.lifetimes.re_erased, closure_ty)
+                        }
+                        ty::ClosureKind::FnMut => {
+                            Ty::new_mut_ref(tcx, tcx.lifetimes.re_erased, closure_ty)
+                        }
+                        ty::ClosureKind::FnOnce => closure_ty,
+                    };
+                    (
+                        [self_ty].into_iter().chain(sig.tupled_inputs_ty.tuple_fields()).collect(),
+                        sig.to_coroutine(
+                            tcx,
+                            args.parent_args(),
+                            args.kind_ty(),
+                            tcx.coroutine_for_closure(*did),
+                            Ty::new_error(tcx, guar),
+                        ),
+                        None,
+                    )
                 }
                 ty::Error(_) => (vec![closure_ty, closure_ty], closure_ty, None),
                 kind => {
diff --git a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
index fcd4715b9e8..e40f4520671 100644
--- a/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
+++ b/compiler/rustc_mir_transform/src/coroutine/by_move_body.rs
@@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxIndexSet;
 use rustc_hir as hir;
 use rustc_middle::mir::visit::MutVisitor;
 use rustc_middle::mir::{self, dump_mir, MirPass};
-use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt};
+use rustc_middle::ty::{self, InstanceDef, Ty, TyCtxt, TypeVisitableExt};
 use rustc_target::abi::FieldIdx;
 
 pub struct ByMoveBody;
@@ -23,7 +23,10 @@ impl<'tcx> MirPass<'tcx> for ByMoveBody {
             return;
         };
         let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty;
-        let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!() };
+        if coroutine_ty.references_error() {
+            return;
+        }
+        let ty::Coroutine(_, args) = *coroutine_ty.kind() else { bug!("{body:#?}") };
 
         let coroutine_kind = args.as_coroutine().kind_ty().to_opt_closure_kind().unwrap();
         if coroutine_kind == ty::ClosureKind::FnOnce {
diff --git a/tests/ui/async-await/async-closures/tainted-body.rs b/tests/ui/async-await/async-closures/tainted-body.rs
new file mode 100644
index 00000000000..62c28e7e585
--- /dev/null
+++ b/tests/ui/async-await/async-closures/tainted-body.rs
@@ -0,0 +1,13 @@
+// edition:2021
+
+#![feature(async_closure)]
+
+// Don't ICE in ByMove shim builder when MIR body is tainted by writeback errors
+
+fn main() {
+    let _ = async || {
+        used_fn();
+        //~^ ERROR cannot find function `used_fn` in this scope
+        0
+    };
+}
diff --git a/tests/ui/async-await/async-closures/tainted-body.stderr b/tests/ui/async-await/async-closures/tainted-body.stderr
new file mode 100644
index 00000000000..b06a896b81f
--- /dev/null
+++ b/tests/ui/async-await/async-closures/tainted-body.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `used_fn` in this scope
+  --> $DIR/tainted-body.rs:9:9
+   |
+LL |         used_fn();
+   |         ^^^^^^^ not found in this scope
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0425`.
diff --git a/tests/ui/mir/validate/error-body.rs b/tests/ui/mir/validate/error-body.rs
new file mode 100644
index 00000000000..5b2fbb0b046
--- /dev/null
+++ b/tests/ui/mir/validate/error-body.rs
@@ -0,0 +1,9 @@
+// compile-flags: -Zvalidate-mir
+
+fn _test() {
+    let x = || 45;
+    missing();
+    //~^ ERROR cannot find function `missing` in this scope
+}
+
+fn main() {}
diff --git a/tests/ui/mir/validate/error-body.stderr b/tests/ui/mir/validate/error-body.stderr
new file mode 100644
index 00000000000..1dfeaf0b7e2
--- /dev/null
+++ b/tests/ui/mir/validate/error-body.stderr
@@ -0,0 +1,9 @@
+error[E0425]: cannot find function `missing` in this scope
+  --> $DIR/error-body.rs:5:5
+   |
+LL |     missing();
+   |     ^^^^^^^ not found in this scope
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0425`.