Skip to content

Commit 49e73c3

Browse files
Don't do coroutine-closure-specific upvar analysis if tainted by errors
1 parent df7daa8 commit 49e73c3

File tree

4 files changed

+50
-3
lines changed

4 files changed

+50
-3
lines changed

compiler/rustc_hir_typeck/src/upvar.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, Pro
4343
use rustc_middle::mir::FakeReadCause;
4444
use rustc_middle::traits::ObligationCauseCode;
4545
use rustc_middle::ty::{
46-
self, ClosureSizeProfileData, Ty, TyCtxt, TypeckResults, UpvarArgs, UpvarCapture,
46+
self, ClosureSizeProfileData, Ty, TyCtxt, TypeVisitableExt as _, TypeckResults, UpvarArgs,
47+
UpvarCapture,
4748
};
4849
use rustc_session::lint;
4950
use rustc_span::sym;
@@ -191,6 +192,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
191192
);
192193
}
193194
};
195+
let args = self.resolve_vars_if_possible(args);
194196
let closure_def_id = closure_def_id.expect_local();
195197

196198
assert_eq!(self.tcx.hir().body_owner_def_id(body.id()), closure_def_id);
@@ -361,7 +363,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
361363
// For coroutine-closures, we additionally must compute the
362364
// `coroutine_captures_by_ref_ty` type, which is used to generate the by-ref
363365
// version of the coroutine-closure's output coroutine.
364-
if let UpvarArgs::CoroutineClosure(args) = args {
366+
if let UpvarArgs::CoroutineClosure(args) = args
367+
&& !args.references_error()
368+
{
365369
let closure_env_region: ty::Region<'_> = ty::Region::new_bound(
366370
self.tcx,
367371
ty::INNERMOST,

compiler/rustc_middle/src/ty/sty.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,7 @@ impl<'tcx> CoroutineArgs<'tcx> {
771771
}
772772
}
773773

774-
#[derive(Debug, Copy, Clone, HashStable)]
774+
#[derive(Debug, Copy, Clone, HashStable, TypeFoldable, TypeVisitable)]
775775
pub enum UpvarArgs<'tcx> {
776776
Closure(GenericArgsRef<'tcx>),
777777
Coroutine(GenericArgsRef<'tcx>),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
//@ edition: 2021
2+
3+
#![feature(async_closure)]
4+
5+
struct DropMe;
6+
7+
trait Impossible {}
8+
fn trait_error<T: Impossible>() {}
9+
10+
pub fn main() {
11+
let b = DropMe;
12+
let async_closure = async move || {
13+
// Type error here taints the environment. This causes us to fallback all
14+
// variables to `Error`. This means that when we compute the upvars for the
15+
// *outer* coroutine-closure, we don't actually see any upvars since `MemCategorization`
16+
// and `ExprUseVisitor`` will bail early when it sees error. This means
17+
// that our underlying assumption that the parent and child captures are
18+
// compatible ends up being broken, previously leading to an ICE.
19+
trait_error::<()>();
20+
//~^ ERROR the trait bound `(): Impossible` is not satisfied
21+
let _b = b;
22+
};
23+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
error[E0277]: the trait bound `(): Impossible` is not satisfied
2+
--> $DIR/dont-ice-when-body-tainted-by-errors.rs:19:23
3+
|
4+
LL | trait_error::<()>();
5+
| ^^ the trait `Impossible` is not implemented for `()`
6+
|
7+
help: this trait has no implementations, consider adding one
8+
--> $DIR/dont-ice-when-body-tainted-by-errors.rs:7:1
9+
|
10+
LL | trait Impossible {}
11+
| ^^^^^^^^^^^^^^^^
12+
note: required by a bound in `trait_error`
13+
--> $DIR/dont-ice-when-body-tainted-by-errors.rs:8:19
14+
|
15+
LL | fn trait_error<T: Impossible>() {}
16+
| ^^^^^^^^^^ required by this bound in `trait_error`
17+
18+
error: aborting due to 1 previous error
19+
20+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)