Open AngelicosPhosphoros opened 1 week ago
Minimized:
fn recurse(_: impl Fn()) {
if false {
recurse(|| {});
}
}
fn main() {
recurse(|| {});
}
Workaround:
pub enum ObjectOrVec {
Object(u8),
V(Vec<ObjectOrVec>),
}
fn make_f(v: &mut Vec<ObjectOrVec>) -> impl FnMut(ObjectOrVec) + '_ {
move |x| v.push(x)
}
pub fn gen(gen_random_num: fn() -> u8) -> ObjectOrVec {
use ObjectOrVec::*;
fn gen_recursively(
gen_random_num: fn() -> u8,
recurses: usize,
mut visitor: impl FnMut(ObjectOrVec),
) {
match gen_random_num() {
1 if recurses > 0 => {
let mut v = Vec::new();
gen_recursively(gen_random_num, recurses - 1, make_f(&mut v));
visitor(V(v));
}
n => visitor(Object(gen_random_num())),
}
}
let mut v = Vec::new();
gen_recursively(gen_random_num, 3, |x| v.push(x));
V(v)
}
Apparently closure inside a generic function is implemented as an associated type of the function, and it's not checking whether the closure actually used the generic parameter. The end result is that the compiler is trying to instantiate gen_recursively::<{closure}>
and gen_recursively::<gen_recursively::<{closure}>::{closure}>
and so on without realizing they are actually the same.
Duplicate of #77664
I tried this code:
I expected to see this happen: Code compiles and generates 2 versions of function
gen
.Instead, this happened: compiler errors by reaching recursion limit. Increasing recursion limit causes stack overflow.
Error message:
Link to playground: https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=571ea952b43ae93438a8f4bf9c2b0ec3
Meta
rustc --version --verbose
: