Skip to content

Commit

Permalink
Don't ICE when generating Fn shim for async closure with borrowck error
Browse files Browse the repository at this point in the history
  • Loading branch information
compiler-errors committed Sep 16, 2024
1 parent 13b5a4e commit 57a7e51
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 6 deletions.
17 changes: 12 additions & 5 deletions compiler/rustc_mir_transform/src/shim.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
Original file line number Diff line number Diff line change
@@ -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)]
Expand All @@ -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();
});
}
Expand Down
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 57a7e51

Please sign in to comment.