mirror of
https://github.com/rust-lang/rust.git
synced 2025-06-05 03:38:29 +00:00
Rollup merge of #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 #139142
This commit is contained in:
commit
b17948ad52
@ -294,7 +294,7 @@ impl DefKind {
|
|||||||
DefKind::GlobalAsm => DefPathData::GlobalAsm,
|
DefKind::GlobalAsm => DefPathData::GlobalAsm,
|
||||||
DefKind::Impl { .. } => DefPathData::Impl,
|
DefKind::Impl { .. } => DefPathData::Impl,
|
||||||
DefKind::Closure => DefPathData::Closure,
|
DefKind::Closure => DefPathData::Closure,
|
||||||
DefKind::SyntheticCoroutineBody => DefPathData::Closure,
|
DefKind::SyntheticCoroutineBody => DefPathData::SyntheticCoroutineBody,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -291,6 +291,8 @@ pub enum DefPathData {
|
|||||||
/// An existential `impl Trait` type node.
|
/// An existential `impl Trait` type node.
|
||||||
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
|
/// Argument position `impl Trait` have a `TypeNs` with their pretty-printed name.
|
||||||
OpaqueTy,
|
OpaqueTy,
|
||||||
|
/// A synthetic body for a coroutine's by-move body.
|
||||||
|
SyntheticCoroutineBody,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Definitions {
|
impl Definitions {
|
||||||
@ -415,8 +417,16 @@ impl DefPathData {
|
|||||||
|
|
||||||
ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
|
ValueNs(name) | MacroNs(name) | LifetimeNs(name) => Some(name),
|
||||||
|
|
||||||
Impl | ForeignMod | CrateRoot | Use | GlobalAsm | Closure | Ctor | AnonConst
|
Impl
|
||||||
| OpaqueTy => None,
|
| ForeignMod
|
||||||
|
| CrateRoot
|
||||||
|
| Use
|
||||||
|
| GlobalAsm
|
||||||
|
| Closure
|
||||||
|
| Ctor
|
||||||
|
| AnonConst
|
||||||
|
| OpaqueTy
|
||||||
|
| SyntheticCoroutineBody => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -441,6 +451,7 @@ impl DefPathData {
|
|||||||
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
|
Ctor => DefPathDataName::Anon { namespace: sym::constructor },
|
||||||
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
|
AnonConst => DefPathDataName::Anon { namespace: sym::constant },
|
||||||
OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
|
OpaqueTy => DefPathDataName::Anon { namespace: sym::opaque },
|
||||||
|
SyntheticCoroutineBody => DefPathDataName::Anon { namespace: sym::synthetic },
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1930,10 +1930,10 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||||||
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
|
// As a consequence, this LocalDefId is always re-created before it is needed by the incr.
|
||||||
// comp. engine itself.
|
// comp. engine itself.
|
||||||
//
|
//
|
||||||
// This call also writes to the value of `source_span` and `expn_that_defined` queries.
|
// This call also writes to the value of the `source_span` query.
|
||||||
// This is fine because:
|
// This is fine because:
|
||||||
// - those queries are `eval_always` so we won't miss their result changing;
|
// - that query is `eval_always` so we won't miss its result changing;
|
||||||
// - this write will have happened before these queries are called.
|
// - this write will have happened before that query is called.
|
||||||
let def_id = self.untracked.definitions.write().create_def(parent, data);
|
let def_id = self.untracked.definitions.write().create_def(parent, data);
|
||||||
|
|
||||||
// This function modifies `self.definitions` using a side-effect.
|
// This function modifies `self.definitions` using a side-effect.
|
||||||
|
@ -139,8 +139,7 @@ pub trait Printer<'tcx>: Sized {
|
|||||||
|
|
||||||
match key.disambiguated_data.data {
|
match key.disambiguated_data.data {
|
||||||
DefPathData::Closure => {
|
DefPathData::Closure => {
|
||||||
// FIXME(async_closures): This is somewhat ugly.
|
// We need to additionally print the `kind` field of a coroutine if
|
||||||
// We need to additionally print the `kind` field of a closure if
|
|
||||||
// it is desugared from a coroutine-closure.
|
// it is desugared from a coroutine-closure.
|
||||||
if let Some(hir::CoroutineKind::Desugared(
|
if let Some(hir::CoroutineKind::Desugared(
|
||||||
_,
|
_,
|
||||||
@ -156,6 +155,10 @@ pub trait Printer<'tcx>: Sized {
|
|||||||
// Closures' own generics are only captures, don't print them.
|
// Closures' own generics are only captures, don't print them.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
DefPathData::SyntheticCoroutineBody => {
|
||||||
|
// Synthetic coroutine bodies have no distinct generics, since like
|
||||||
|
// closures they're all just internal state of the coroutine.
|
||||||
|
}
|
||||||
// This covers both `DefKind::AnonConst` and `DefKind::InlineConst`.
|
// This covers both `DefKind::AnonConst` and `DefKind::InlineConst`.
|
||||||
// Anon consts doesn't have their own generics, and inline consts' own
|
// Anon consts doesn't have their own generics, and inline consts' own
|
||||||
// generics are their inferred types, so don't print them.
|
// generics are their inferred types, so don't print them.
|
||||||
|
@ -66,6 +66,7 @@ pub struct MarkFrame<'a> {
|
|||||||
parent: Option<&'a MarkFrame<'a>>,
|
parent: Option<&'a MarkFrame<'a>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
pub(super) enum DepNodeColor {
|
pub(super) enum DepNodeColor {
|
||||||
Red,
|
Red,
|
||||||
Green(DepNodeIndex),
|
Green(DepNodeIndex),
|
||||||
@ -909,7 +910,7 @@ impl<D: Deps> DepGraphData<D> {
|
|||||||
self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node, frame);
|
self.try_mark_previous_green(qcx, parent_dep_node_index, dep_dep_node, frame);
|
||||||
|
|
||||||
if node_index.is_some() {
|
if node_index.is_some() {
|
||||||
debug!("managed to MARK dependency {dep_dep_node:?} as green",);
|
debug!("managed to MARK dependency {dep_dep_node:?} as green");
|
||||||
return Some(());
|
return Some(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -930,7 +931,7 @@ impl<D: Deps> DepGraphData<D> {
|
|||||||
return Some(());
|
return Some(());
|
||||||
}
|
}
|
||||||
Some(DepNodeColor::Red) => {
|
Some(DepNodeColor::Red) => {
|
||||||
debug!("dependency {dep_dep_node:?} was red after forcing",);
|
debug!("dependency {dep_dep_node:?} was red after forcing");
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
None => {}
|
None => {}
|
||||||
@ -950,7 +951,7 @@ impl<D: Deps> DepGraphData<D> {
|
|||||||
// invalid state will not be persisted to the
|
// invalid state will not be persisted to the
|
||||||
// incremental compilation cache because of
|
// incremental compilation cache because of
|
||||||
// compilation errors being present.
|
// compilation errors being present.
|
||||||
debug!("dependency {dep_dep_node:?} resulted in compilation error",);
|
debug!("dependency {dep_dep_node:?} resulted in compilation error");
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -716,6 +716,7 @@ fn encode_ty_name(tcx: TyCtxt<'_>, def_id: DefId) -> String {
|
|||||||
hir::definitions::DefPathData::Ctor => "c",
|
hir::definitions::DefPathData::Ctor => "c",
|
||||||
hir::definitions::DefPathData::AnonConst => "k",
|
hir::definitions::DefPathData::AnonConst => "k",
|
||||||
hir::definitions::DefPathData::OpaqueTy => "i",
|
hir::definitions::DefPathData::OpaqueTy => "i",
|
||||||
|
hir::definitions::DefPathData::SyntheticCoroutineBody => "s",
|
||||||
hir::definitions::DefPathData::CrateRoot
|
hir::definitions::DefPathData::CrateRoot
|
||||||
| hir::definitions::DefPathData::Use
|
| hir::definitions::DefPathData::Use
|
||||||
| hir::definitions::DefPathData::GlobalAsm
|
| hir::definitions::DefPathData::GlobalAsm
|
||||||
|
@ -28,7 +28,10 @@ pub(super) fn mangle<'tcx>(
|
|||||||
loop {
|
loop {
|
||||||
let key = tcx.def_key(ty_def_id);
|
let key = tcx.def_key(ty_def_id);
|
||||||
match key.disambiguated_data.data {
|
match key.disambiguated_data.data {
|
||||||
DefPathData::TypeNs(_) | DefPathData::ValueNs(_) | DefPathData::Closure => {
|
DefPathData::TypeNs(_)
|
||||||
|
| DefPathData::ValueNs(_)
|
||||||
|
| DefPathData::Closure
|
||||||
|
| DefPathData::SyntheticCoroutineBody => {
|
||||||
instance_ty = tcx.type_of(ty_def_id).instantiate_identity();
|
instance_ty = tcx.type_of(ty_def_id).instantiate_identity();
|
||||||
debug!(?instance_ty);
|
debug!(?instance_ty);
|
||||||
break;
|
break;
|
||||||
|
@ -850,6 +850,7 @@ impl<'tcx> Printer<'tcx> for SymbolMangler<'tcx> {
|
|||||||
DefPathData::Ctor => 'c',
|
DefPathData::Ctor => 'c',
|
||||||
DefPathData::AnonConst => 'k',
|
DefPathData::AnonConst => 'k',
|
||||||
DefPathData::OpaqueTy => 'i',
|
DefPathData::OpaqueTy => 'i',
|
||||||
|
DefPathData::SyntheticCoroutineBody => 's',
|
||||||
|
|
||||||
// These should never show up as `path_append` arguments.
|
// These should never show up as `path_append` arguments.
|
||||||
DefPathData::CrateRoot
|
DefPathData::CrateRoot
|
||||||
|
@ -38,6 +38,15 @@ Number of file 0 mappings: 1
|
|||||||
- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
|
- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
|
||||||
Highest counter ID seen: c0
|
Highest counter ID seen: c0
|
||||||
|
|
||||||
|
Function name: async_closure::main::{closure#0}
|
||||||
|
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24]
|
||||||
|
Number of files: 1
|
||||||
|
- file 0 => global file 1
|
||||||
|
Number of expressions: 0
|
||||||
|
Number of file 0 mappings: 1
|
||||||
|
- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
|
||||||
|
Highest counter ID seen: c0
|
||||||
|
|
||||||
Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
|
Function name: async_closure::main::{closure#0}::{closure#0}::<i16>
|
||||||
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
|
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 22, 00, 24]
|
||||||
Number of files: 1
|
Number of files: 1
|
||||||
@ -47,12 +56,3 @@ Number of file 0 mappings: 1
|
|||||||
- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
|
- Code(Counter(0)) at (prev + 11, 34) to (start + 0, 36)
|
||||||
Highest counter ID seen: c0
|
Highest counter ID seen: c0
|
||||||
|
|
||||||
Function name: async_closure::main::{closure#0}::{closure#1}::<i32>
|
|
||||||
Raw bytes (9): 0x[01, 01, 00, 01, 01, 0b, 23, 00, 24]
|
|
||||||
Number of files: 1
|
|
||||||
- file 0 => global file 1
|
|
||||||
Number of expressions: 0
|
|
||||||
Number of file 0 mappings: 1
|
|
||||||
- Code(Counter(0)) at (prev + 11, 35) to (start + 0, 36)
|
|
||||||
Highest counter ID seen: c0
|
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
| async_closure::main::{closure#0}:
|
| async_closure::main::{closure#0}:
|
||||||
| LL| 1| let async_closure = async || {};
|
| LL| 1| let async_closure = async || {};
|
||||||
------------------
|
------------------
|
||||||
| async_closure::main::{closure#0}::{closure#1}::<i32>:
|
| async_closure::main::{closure#0}:
|
||||||
| LL| 1| let async_closure = async || {};
|
| LL| 1| let async_closure = async || {};
|
||||||
------------------
|
------------------
|
||||||
LL| 1| executor::block_on(async_closure());
|
LL| 1| executor::block_on(async_closure());
|
||||||
|
@ -0,0 +1,15 @@
|
|||||||
|
//@ revisions: rpass1 rpass2
|
||||||
|
//@ edition: 2024
|
||||||
|
|
||||||
|
#![allow(unused)]
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
#[cfg(rpass1)]
|
||||||
|
async || {};
|
||||||
|
|
||||||
|
#[cfg(rpass2)]
|
||||||
|
|| {
|
||||||
|
|| ();
|
||||||
|
|| ();
|
||||||
|
};
|
||||||
|
}
|
@ -1,6 +1,6 @@
|
|||||||
// MIR for `foo::{closure#0}::{closure#1}` after built
|
// MIR for `foo::{closure#0}::{synthetic#0}` after built
|
||||||
|
|
||||||
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) -> ()
|
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) -> ()
|
||||||
yields ()
|
yields ()
|
||||||
{
|
{
|
||||||
debug _task_context => _2;
|
debug _task_context => _2;
|
@ -7,7 +7,7 @@ enum Foo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir
|
// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#0}.built.after.mir
|
||||||
// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{closure#1}.built.after.mir
|
// EMIT_MIR async_closure_fake_read_for_by_move.foo-{closure#0}-{synthetic#0}.built.after.mir
|
||||||
fn foo(f: &Foo) {
|
fn foo(f: &Foo) {
|
||||||
let x = async move || match f {
|
let x = async move || match f {
|
||||||
Foo::Bar if true => {}
|
Foo::Bar if true => {}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// MIR for `main::{closure#0}::{closure#0}::{closure#1}` after built
|
// MIR for `main::{closure#0}::{closure#0}::{synthetic#0}` after built
|
||||||
|
|
||||||
fn main::{closure#0}::{closure#0}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
|
fn main::{closure#0}::{closure#0}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:53:53: 56:10}, _2: ResumeTy) -> ()
|
||||||
yields ()
|
yields ()
|
||||||
{
|
{
|
||||||
debug _task_context => _2;
|
debug _task_context => _2;
|
@ -1,6 +1,6 @@
|
|||||||
// MIR for `main::{closure#0}::{closure#1}::{closure#1}` after built
|
// MIR for `main::{closure#0}::{closure#1}::{synthetic#0}` after built
|
||||||
|
|
||||||
fn main::{closure#0}::{closure#1}::{closure#1}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
|
fn main::{closure#0}::{closure#1}::{synthetic#0}(_1: {async closure body@$DIR/async_closure_shims.rs:62:48: 65:10}, _2: ResumeTy) -> ()
|
||||||
yields ()
|
yields ()
|
||||||
{
|
{
|
||||||
debug _task_context => _2;
|
debug _task_context => _2;
|
@ -42,11 +42,11 @@ async fn call_normal_mut<F: Future<Output = ()>>(f: &mut impl FnMut(i32) -> F) {
|
|||||||
|
|
||||||
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir
|
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}.coroutine_closure_by_move.0.mir
|
||||||
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir
|
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#0}.built.after.mir
|
||||||
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{closure#1}.built.after.mir
|
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#0}-{synthetic#0}.built.after.mir
|
||||||
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir
|
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_ref.0.mir
|
||||||
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir
|
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}.coroutine_closure_by_move.0.mir
|
||||||
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir
|
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#0}.built.after.mir
|
||||||
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{closure#1}.built.after.mir
|
// EMIT_MIR async_closure_shims.main-{closure#0}-{closure#1}-{synthetic#0}.built.after.mir
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
block_on(async {
|
block_on(async {
|
||||||
let b = 2i32;
|
let b = 2i32;
|
||||||
|
@ -56,7 +56,7 @@ fn foo::{closure#0}::{closure#0}(_1: Pin<&mut {async closure body@$DIR/async-clo
|
|||||||
unreachable;
|
unreachable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn foo::{closure#0}::{closure#1}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
|
fn foo::{closure#0}::{synthetic#0}(_1: Pin<&mut {async closure body@$DIR/async-closure.rs:9:22: 11:6}>, _2: &mut Context<'_>) -> Poll<()> {
|
||||||
let mut _0: Poll<()>;
|
let mut _0: Poll<()>;
|
||||||
let _3: i32;
|
let _3: i32;
|
||||||
let mut _4: &i32;
|
let mut _4: &i32;
|
||||||
|
Loading…
Reference in New Issue
Block a user