Home > Back-end >  nested lambdas cause compiler to run out of heap
nested lambdas cause compiler to run out of heap

Time:06-07

I'm writing some code which passes lambda functions to a suite of recursive functions. Some of these lambda functions are nested inside other lambda functions. I think I'm writing valid code but I'm getting a fatal error C1060: compiler is out of heap space error.

Here is a much cut down version of the code

struct Null
{
    template <typename SK>
    static void match(SK sk)
    {
    }
};

template <typename T>
struct Repetition
{
    template <typename SK>
    static void match(SK sk)
    {  // <--------------------------------- error message points to this line
        T::match([]() { match([]() {}); });
    }
};

int main()
{
    using Test = Repetition<Null>;
    Test::match([](){});
}

Now this minimal version doesn't make much sense but it has the same compiler error. I've indicated the line with the error above.

My question is, is this a compiler bug/limitation or is my code invalid in some way?

Compiler is Visual Studio 2022 compiling C 20.

Thanks

CodePudding user response:

Per [expr.prim.lambda.closure]

The type of a lambda-expression (which is also the type of the closure object) is a unique, unnamed non-union class type

To instantiate Repetition::match, the compiler must instantiate Null::match which requires an instantiation of Repetition::match... and so on. Each time the compiler recurses, []() {} is treated as a brand new type, ad infinitum.

To get it to stop recursing, replace your call with:

T::match(sk);

CodePudding user response:

While both VS2022 and gcc 11 and 12 just crash on this, clang does manage to give an error message:

<source>:15:25: fatal error: recursive template instantiation exceeded maximum depth of 1024
        T::match([]() { match([]() {}); });
                        ^
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: (skipping 1015 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:22:11: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:22:17)>' requested here
    Test::match([](){});
          ^
1 error generated.
ASM generation compiler returned: 1
<source>:15:25: fatal error: recursive template instantiation exceeded maximum depth of 1024
        T::match([]() { match([]() {}); });
                        ^
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: (skipping 1015 contexts in backtrace; use -ftemplate-backtrace-limit=0 to see all)
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:15:25: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:15:31)>' requested here
<source>:22:11: note: in instantiation of function template specialization 'Repetition<Null>::match<(lambda at <source>:22:17)>' requested here
    Test::match([](){});
          ^
1 error generated.
Execution build compiler returned: 1
  • Related