Don't ICE when generating Fn shim for async closure with borrowck error

This commit is contained in:
Michael Goulet 2024-09-15 16:07:08 -04:00
parent 13b5a4e43b
commit 57a7e514a4
3 changed files with 37 additions and 6 deletions

View File

@ -1070,19 +1070,26 @@ fn build_construct_coroutine_by_move_shim<'tcx>(
let locals = local_decls_for_sig(&sig, span);
let mut fields = vec![];
// Move all of the closure args.
for idx in 1..sig.inputs().len() {
fields.push(Operand::Move(Local::from_usize(idx + 1).into()));
}
for (idx, ty) in args.as_coroutine_closure().upvar_tys().iter().enumerate() {
if receiver_by_ref {
// The only situation where it's possible is when we capture immuatable references,
// since those don't need to be reborrowed with the closure's env lifetime. Since
// references are always `Copy`, just emit a copy.
assert_matches!(
ty.kind(),
ty::Ref(_, _, hir::Mutability::Not),
"field should be captured by immutable ref if we have an `Fn` instance"
);
if !matches!(ty.kind(), ty::Ref(_, _, hir::Mutability::Not)) {
// This copy is only sound if it's a `&T`. This may be
// reachable e.g. when eagerly computing the `Fn` instance
// of an async closure that doesn't borrowck.
tcx.dcx().delayed_bug(format!(
"field should be captured by immutable ref if we have \
an `Fn` instance, but it was: {ty}"
));
}
fields.push(Operand::Copy(tcx.mk_place_field(
self_local,
FieldIdx::from_usize(idx),

View File

@ -1,4 +1,3 @@
//@ known-bug: rust-lang/rust#129262
//@ compile-flags: -Zvalidate-mir --edition=2018 --crate-type=lib -Copt-level=3
#![feature(async_closure)]
@ -11,6 +10,7 @@ fn needs_fn_mut<T>(mut x: impl FnMut() -> T) {
fn hello(x: Ty) {
needs_fn_mut(async || {
//~^ ERROR cannot move out of `x`
x.hello();
});
}

View File

@ -0,0 +1,24 @@
error[E0507]: cannot move out of `x` which is behind a mutable reference
--> $DIR/closure-shim-borrowck-error.rs:12:18
|
LL | needs_fn_mut(async || {
| ^^^^^^^^ `x` is moved here
LL |
LL | x.hello();
| -
| |
| variable moved due to use in coroutine
| move occurs because `x` has type `Ty`, which does not implement the `Copy` trait
|
note: if `Ty` implemented `Clone`, you could clone the value
--> $DIR/closure-shim-borrowck-error.rs:18:1
|
LL | x.hello();
| - you could clone this value
...
LL | struct Ty;
| ^^^^^^^^^ consider implementing `Clone` for this type
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0507`.