Add cache to FoldEscapingRegions
This commit is contained in:
parent
01a26c026d
commit
d7a6fdc71f
5 changed files with 144 additions and 1 deletions
|
@ -3,9 +3,10 @@ use std::ops::ControlFlow;
|
||||||
use derive_where::derive_where;
|
use derive_where::derive_where;
|
||||||
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
use rustc_type_ir_macros::{Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic};
|
||||||
|
|
||||||
|
use crate::data_structures::DelayedMap;
|
||||||
use crate::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable, shift_region};
|
use crate::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable, shift_region};
|
||||||
use crate::inherent::*;
|
use crate::inherent::*;
|
||||||
use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitor};
|
use crate::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
|
||||||
use crate::{self as ty, Interner};
|
use crate::{self as ty, Interner};
|
||||||
|
|
||||||
/// A closure can be modeled as a struct that looks like:
|
/// A closure can be modeled as a struct that looks like:
|
||||||
|
@ -471,6 +472,7 @@ impl<I: Interner> CoroutineClosureSignature<I> {
|
||||||
interner: cx,
|
interner: cx,
|
||||||
region: env_region,
|
region: env_region,
|
||||||
debruijn: ty::INNERMOST,
|
debruijn: ty::INNERMOST,
|
||||||
|
cache: Default::default(),
|
||||||
});
|
});
|
||||||
Ty::new_tup_from_iter(
|
Ty::new_tup_from_iter(
|
||||||
cx,
|
cx,
|
||||||
|
@ -498,6 +500,10 @@ struct FoldEscapingRegions<I: Interner> {
|
||||||
interner: I,
|
interner: I,
|
||||||
debruijn: ty::DebruijnIndex,
|
debruijn: ty::DebruijnIndex,
|
||||||
region: I::Region,
|
region: I::Region,
|
||||||
|
|
||||||
|
// Depends on `debruijn` because we may have types with regions of different
|
||||||
|
// debruijn depths depending on the binders we've entered.
|
||||||
|
cache: DelayedMap<(ty::DebruijnIndex, I::Ty), I::Ty>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<I: Interner> TypeFolder<I> for FoldEscapingRegions<I> {
|
impl<I: Interner> TypeFolder<I> for FoldEscapingRegions<I> {
|
||||||
|
@ -505,6 +511,18 @@ impl<I: Interner> TypeFolder<I> for FoldEscapingRegions<I> {
|
||||||
self.interner
|
self.interner
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn fold_ty(&mut self, t: I::Ty) -> I::Ty {
|
||||||
|
if !t.has_vars_bound_at_or_above(self.debruijn) {
|
||||||
|
t
|
||||||
|
} else if let Some(&t) = self.cache.get(&(self.debruijn, t)) {
|
||||||
|
t
|
||||||
|
} else {
|
||||||
|
let res = t.super_fold_with(self);
|
||||||
|
assert!(self.cache.insert((self.debruijn, t), res));
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
|
fn fold_binder<T>(&mut self, t: ty::Binder<I, T>) -> ty::Binder<I, T>
|
||||||
where
|
where
|
||||||
T: TypeFoldable<I>,
|
T: TypeFoldable<I>,
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
//@ edition: 2021
|
||||||
|
//@ build-fail
|
||||||
|
|
||||||
|
// Regression test for <https://github.com/rust-lang/rust/issues/135780>.
|
||||||
|
|
||||||
|
use std::future::Future;
|
||||||
|
use std::ops::AsyncFn;
|
||||||
|
use std::pin::Pin;
|
||||||
|
|
||||||
|
fn recur<'l>(closure: &'l impl AsyncFn()) -> Pin<Box<dyn Future<Output = ()> + 'l>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
let _ = closure();
|
||||||
|
let _ = recur(&async || {
|
||||||
|
//~^ ERROR reached the recursion limit
|
||||||
|
let _ = closure();
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let closure = async || {};
|
||||||
|
let _ = recur(&closure);
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
error: reached the recursion limit while instantiating `recur::<{async closure@$DIR/post-mono-higher-ranked-hang-2.rs:13:24: 13:32}>`
|
||||||
|
--> $DIR/post-mono-higher-ranked-hang-2.rs:13:17
|
||||||
|
|
|
||||||
|
LL | let _ = recur(&async || {
|
||||||
|
| _________________^
|
||||||
|
LL | |
|
||||||
|
LL | | let _ = closure();
|
||||||
|
LL | | });
|
||||||
|
| |__________^
|
||||||
|
|
|
||||||
|
note: `recur` defined here
|
||||||
|
--> $DIR/post-mono-higher-ranked-hang-2.rs:10:1
|
||||||
|
|
|
||||||
|
LL | fn recur<'l>(closure: &'l impl AsyncFn()) -> Pin<Box<dyn Future<Output = ()> + 'l>> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
|
@ -0,0 +1,63 @@
|
||||||
|
//@ build-fail
|
||||||
|
//@ aux-build:block-on.rs
|
||||||
|
//@ edition:2021
|
||||||
|
|
||||||
|
// Regression test for <https://github.com/rust-lang/rust/issues/135780>.
|
||||||
|
|
||||||
|
extern crate block_on;
|
||||||
|
|
||||||
|
use std::future::Future;
|
||||||
|
use std::ops::AsyncFnMut;
|
||||||
|
use std::pin::{Pin, pin};
|
||||||
|
use std::task::*;
|
||||||
|
|
||||||
|
trait Db {}
|
||||||
|
|
||||||
|
impl Db for () {}
|
||||||
|
|
||||||
|
struct Env<'db> {
|
||||||
|
db: &'db (),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
enum SymPerm<'db> {
|
||||||
|
Dummy(&'db ()),
|
||||||
|
Apply(Box<SymPerm<'db>>, Box<SymPerm<'db>>),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ToChain<'env, 'db> {
|
||||||
|
db: &'db dyn crate::Db,
|
||||||
|
env: &'env Env<'db>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'env, 'db> ToChain<'env, 'db> {
|
||||||
|
fn perm_pairs<'l>(
|
||||||
|
&'l self,
|
||||||
|
perm: &'l SymPerm<'db>,
|
||||||
|
yield_chain: &'l mut impl AsyncFnMut(&SymPerm<'db>),
|
||||||
|
) -> Pin<Box<dyn std::future::Future<Output = ()> + 'l>> {
|
||||||
|
Box::pin(async move {
|
||||||
|
match perm {
|
||||||
|
SymPerm::Dummy(_) => yield_chain(perm).await,
|
||||||
|
SymPerm::Apply(l, r) => {
|
||||||
|
self.perm_pairs(l, &mut async move |left_pair| {
|
||||||
|
//~^ ERROR reached the recursion limit while instantiating
|
||||||
|
self.perm_pairs(r, yield_chain).await
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
block_on::block_on(async {
|
||||||
|
let pair = SymPerm::Apply(Box::new(SymPerm::Dummy(&())), Box::new(SymPerm::Dummy(&())));
|
||||||
|
ToChain { db: &(), env: &Env { db: &() } }
|
||||||
|
.perm_pairs(&pair, &mut async |p| {
|
||||||
|
eprintln!("{p:?}");
|
||||||
|
})
|
||||||
|
.await;
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
error: reached the recursion limit while instantiating `ToChain::<'_, '_>::perm_pairs::<{async closure@$DIR/post-mono-higher-ranked-hang.rs:43:45: 43:67}>`
|
||||||
|
--> $DIR/post-mono-higher-ranked-hang.rs:43:21
|
||||||
|
|
|
||||||
|
LL | / self.perm_pairs(l, &mut async move |left_pair| {
|
||||||
|
LL | |
|
||||||
|
LL | | self.perm_pairs(r, yield_chain).await
|
||||||
|
LL | | })
|
||||||
|
| |______________________^
|
||||||
|
|
|
||||||
|
note: `ToChain::<'env, 'db>::perm_pairs` defined here
|
||||||
|
--> $DIR/post-mono-higher-ranked-hang.rs:34:5
|
||||||
|
|
|
||||||
|
LL | / fn perm_pairs<'l>(
|
||||||
|
LL | | &'l self,
|
||||||
|
LL | | perm: &'l SymPerm<'db>,
|
||||||
|
LL | | yield_chain: &'l mut impl AsyncFnMut(&SymPerm<'db>),
|
||||||
|
LL | | ) -> Pin<Box<dyn std::future::Future<Output = ()> + 'l>> {
|
||||||
|
| |____________________________________________________________^
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue