Skip to content

Commit b17948a

Browse files
authored
Rollup merge of rust-lang#139153 - compiler-errors:incr-comp-closure, r=oli-obk
Encode synthetic by-move coroutine body with a different `DefPathData` See the included test. In the first revision rpass1, we have an async closure `{closure#0}` which has a coroutine as a child `{closure#0}::{closure#0}`. We synthesize a by-move coroutine body, which is `{closure#0}::{closure#1}` which depends on the mir_built query, which depends on the typeck query. In the second revision rpass2, we've replaced the coroutine-closure by a closure with two children closure. Notably, the def path of the second child closure is the same as the synthetic def id from the last revision: `{closure#0}::{closure#1}`. When type-checking this closure, we end up trying to compute its def_span, which tries to fetch it from the incremental cache; this will try to force the dependencies from the last run, which ends up forcing the mir_built query, which ends up forcing the typeck query, which ends up with a query cycle. The problem here is that we really should never have used the same `DefPathData` for the synthetic by-move coroutine body, since it's not a closure. Changing the `DefPathData` will mean that we can see that the def ids are distinct, which means we won't try to look up the closure's def span from the incremental cache, which will properly skip replaying the node's dependencies and avoid a query cycle. Fixes rust-lang#139142
2 parents ac05597 + 897acc3 commit b17948a

17 files changed

+64
-29
lines changed

Diff for: compiler/rustc_hir/src/def.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ impl DefKind {
294294
DefKind::GlobalAsm => DefPathData::GlobalAsm,
295295
DefKind::Impl { .. } => DefPathData::Impl,
296296
DefKind::Closure => DefPathData::Closure,
297-
DefKind::SyntheticCoroutineBody => DefPathData::Closure,
297+
DefKind::SyntheticCoroutineBody => DefPathData::SyntheticCoroutineBody,
298298
}
299299
}
300300

Diff for: compiler/rustc_hir/src/definitions.rs

+13-2
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,8 @@ pub enum DefPathData {
291291
/// An existential `impl Trait` type node.
292292
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
293293
OpaqueTy,
294+
/// A synthetic body for a coroutine's by-move body.
295+
SyntheticCoroutineBody,
294296
}
295297

296298
impl Definitions {
@@ -415,8 +417,16 @@ impl DefPathData {
415417

416418
ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
417419

418-
Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst
419-
| OpaqueTy => None,
420+
Impl
421+
| ForeignMod
422+
| CrateRoot
423+
| Use
424+
| GlobalAsm
425+
| Closure
426+
| Ctor
427+
| AnonConst
428+
| OpaqueTy
429+
| SyntheticCoroutineBody => None,
420430
}
421431
}
422432

@@ -441,6 +451,7 @@ impl DefPathData {
441451
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
442452
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
443453
OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
454+
SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic },
444455
}
445456
}
446457
}

Diff for: compiler/rustc_middle/src/ty/context.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1930,10 +1930,10 @@ impl<'tcx> TyCtxt<'tcx> {
19301930
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
19311931
// comp. engine itself.
19321932
//
1933-
// This call also writes to the value of `source_span` and `expn_that_defined` queries.
1933+
// This call also writes to the value of the `source_span` query.
19341934
// This is fine because:
1935-
// - those queries are `eval_always` so we won't miss their result changing;
1936-
// - this write will have happened before these queries are called.
1935+
// - that query is `eval_always` so we won't miss its result changing;
1936+
// - this write will have happened before that query is called.
19371937
let def_id = self.untracked.definitions.write().create_def(parent, data);
19381938

19391939
// This function modifies `self.definitions` using a side-effect.

Diff for: compiler/rustc_middle/src/ty/print/mod.rs

+5-2
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,7 @@ pub trait Printer<'tcx>: Sized {
139139

140140
match key.disambiguated_data.data {
141141
DefPathData::Closure => {
142-
// FIXME(async_closures): This is somewhat ugly.
143-
// We need to additionally print the `kind` field of a closure if
142+
// We need to additionally print the `kind` field of a coroutine if
144143
// it is desugared from a coroutine-closure.
145144
if let Some(hir::CoroutineKind::Desugared(
146145
_,
@@ -156,6 +155,10 @@ pub trait Printer<'tcx>: Sized {
156155
// Closures' own generics are only captures, don't print them.
157156
}
158157
}
158+
DefPathData::SyntheticCoroutineBody => {
159+
// Synthetic coroutine bodies have no distinct generics, since like
160+
// closures they're all just internal state of the coroutine.
161+
}
159162
// This covers both `DefKind::AnonConst` and `DefKind::InlineConst`.
160163
// Anon consts doesn't have their own generics, and inline consts' own
161164
// generics are their inferred types, so don't print them.

Diff for: compiler/rustc_query_system/src/dep_graph/graph.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ pub struct MarkFrame<'a> {
6666
parent: Option<&'a MarkFrame<'a>>,
6767
}
6868

69+
#[derive(Debug)]
6970
pub(super) enum DepNodeColor {
7071
Red,
7172
Green(DepNodeIndex),
@@ -909,7 +910,7 @@ impl<D: Deps> DepGraphData<D> {
909910
self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node, frame);
910911

911912
if node_index.is_some() {
912-
debug!("managed to MARK dependency {dep_dep_node:?} as green",);
913+
debug!("managed to MARK dependency {dep_dep_node:?} as green");
913914
return Some(());
914915
}
915916
}
@@ -930,7 +931,7 @@ impl<D: Deps> DepGraphData<D> {
930931
return Some(());
931932
}
932933
Some(DepNodeColor::Red) => {
933-
debug!("dependency {dep_dep_node:?} was red after forcing",);
934+
debug!("dependency {dep_dep_node:?} was red after forcing");
934935
return None;
935936
}
936937
None => {}
@@ -950,7 +951,7 @@ impl<D: Deps> DepGraphData<D> {
950951
// invalid state will not be persisted to the
951952
// incremental compilation cache because of
952953
// compilation errors being present.
953-
debug!("dependency {dep_dep_node:?} resulted in compilation error",);
954+
debug!("dependency {dep_dep_node:?} resulted in compilation error");
954955
return None;
955956
}
956957

Diff for: compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs

+1
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
716716
hir::definitions::DefPathData::Ctor => "c",
717717
hir::definitions::DefPathData::AnonConst => "k",
718718
hir::definitions::DefPathData::OpaqueTy => "i",
719+
hir::definitions::DefPathData::SyntheticCoroutineBody => "s",
719720
hir::definitions::DefPathData::CrateRoot
720721
| hir::definitions::DefPathData::Use
721722
| hir::definitions::DefPathData::GlobalAsm

Diff for: compiler/rustc_symbol_mangling/src/legacy.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,10 @@ pub(super) fn mangle<'tcx>(
2828
loop {
2929
let key = tcx.def_key(ty_def_id);
3030
match key.disambiguated_data.data {
31-
DefPathData::TypeNs(_) | DefPathData::ValueNs(_) | DefPathData::Closure => {
31+
DefPathData::TypeNs(_)
32+
| DefPathData::ValueNs(_)
33+
| DefPathData::Closure
34+
| DefPathData::SyntheticCoroutineBody => {
3235
instance_ty = tcx.type_of(ty_def_id).instantiate_identity();
3336
debug!(?instance_ty);
3437
break;

Diff for: compiler/rustc_symbol_mangling/src/v0.rs

+1
Original file line numberDiff line numberDiff line change
@@ -850,6 +850,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
850850
DefPathData::Ctor => 'c',
851851
DefPathData::AnonConst => 'k',
852852
DefPathData::OpaqueTy => 'i',
853+
DefPathData::SyntheticCoroutineBody => 's',
853854

854855
// These should never show up as `path_append` arguments.
855856
DefPathData::CrateRoot

Diff for: tests/coverage/async_closure.cov-map

+6-6
Original file line numberDiff line numberDiff line change
@@ -38,21 +38,21 @@ Number of file 0 mappings: 1
3838
- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
3939
Highest counter ID seen: c0
4040

41-
Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
42-
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
41+
Function name: async_closure::main::{closure#0}
42+
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24]
4343
Number of files: 1
4444
- file 0 => global file 1
4545
Number of expressions: 0
4646
Number of file 0 mappings: 1
47-
- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
47+
- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
4848
Highest counter ID seen: c0
4949

50-
Function name: async_closure::main::{closure#0}::{closure#1}::<i32>
51-
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24]
50+
Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
51+
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
5252
Number of files: 1
5353
- file 0 => global file 1
5454
Number of expressions: 0
5555
Number of file 0 mappings: 1
56-
- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
56+
- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
5757
Highest counter ID seen: c0
5858

Diff for: tests/coverage/async_closure.coverage

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
| async_closure::main::{closure#0}:
1515
| LL| 1| let async_closure = async || {};
1616
------------------
17-
| async_closure::main::{closure#0}::{closure#1}::<i32>:
17+
| async_closure::main::{closure#0}:
1818
| LL| 1| let async_closure = async || {};
1919
------------------
2020
LL| 1| executor::block_on(async_closure());
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
//@ revisions: rpass1 rpass2
2+
//@ edition: 2024
3+
4+
#![allow(unused)]
5+
6+
fn main() {
7+
#[cfg(rpass1)]
8+
async || {};
9+
10+
#[cfg(rpass2)]
11+
|| {
12+
|| ();
13+
|| ();
14+
};
15+
}

Diff for: tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir renamed to tests/mir-opt/async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// MIR for `foo::{closure#0}::{closure#1}` after built
1+
// MIR for `foo::{closure#0}::{synthetic#0}` after built
22

3-
fn foo::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> ()
3+
fn foo::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_fake_read_for_by_move.rs:12:27: 15:6}, _2: ResumeTy) -> ()
44
yields ()
55
{
66
debug _task_context => _2;

Diff for: tests/mir-opt/async_closure_fake_read_for_by_move.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ enum Foo {
77
}
88

99
// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir
10-
// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir
10+
// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir
1111
fn foo(f: &Foo) {
1212
let x = async move || match f {
1313
Foo::Bar if true => {}

Diff for: tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir renamed to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// MIR for `main::{closure#0}::{closure#0}::{closure#1}` after built
1+
// MIR for `main::{closure#0}::{closure#0}::{synthetic#0}` after built
22

3-
fn main::{closure#0}::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
3+
fn main::{closure#0}::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
44
yields ()
55
{
66
debug _task_context => _2;

Diff for: tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir renamed to tests/mir-opt/async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
// MIR for `main::{closure#0}::{closure#1}::{closure#1}` after built
1+
// MIR for `main::{closure#0}::{closure#1}::{synthetic#0}` after built
22

3-
fn main::{closure#0}::{closure#1}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
3+
fn main::{closure#0}::{closure#1}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
44
yields ()
55
{
66
debug _task_context => _2;

Diff for: tests/mir-opt/async_closure_shims.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -42,11 +42,11 @@ async fn call_normal_mut<F: Future<Output = ()>>(f: &mut impl FnMut(i32) -> F) {
4242

4343
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir
4444
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir
45-
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir
45+
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir
4646
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir
4747
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir
4848
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir
49-
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir
49+
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir
5050
pub fn main() {
5151
block_on(async {
5252
let b = 2i32;

Diff for: tests/ui/stable-mir-print/async-closure.stdout

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo
5656
unreachable;
5757
}
5858
}
59-
fn foo::{closure#0}::{closure#1}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
59+
fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
6060
let mut _0: Poll<()>;
6161
let _3: i32;
6262
let mut _4: &i32;

0 commit comments

Comments
 (0)