Skip to content

Commit

Permalink
Fix generated code for huge const collections.
Browse files Browse the repository at this point in the history
When unrolling constructors of collections we previously would always
capture explicitly so that container elements could reference other
variables in the scope. This breaks for `const` variables which are
emitted at non-local scope (into a namespace); the lambda performing the
initialization would also be a non-local and non-local lambdas are not
allowed to capture anything (they do not live in a scope after all).

This means that we cannot capture for such lambdas at all which seems to
be an issue -- after all with that it seems impossible to support
constructors of collections which reference other `const`s. Fortunately
C++ lambdas at non-local scope implicitly capture other non-locals
already and they do not need to be captured explictly. This allows for a
rather simple fix.

Closes #1760.
  • Loading branch information
bbannier committed Jun 12, 2024
1 parent e2ab699 commit 4078611
Showing 1 changed file with 22 additions and 4 deletions.
26 changes: 22 additions & 4 deletions hilti/toolchain/src/compiler/codegen/ctors.cc
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,13 @@ struct Visitor : hilti::visitor::PreOrder {
}),
" ");

result = fmt("[&]() { auto __xs = ::hilti::rt::Map<%s, %s>(); %s return __xs; }()", k, v, elems);
// If we are at block scope capture other variables so they can be
// used in the ctr. Outside of block scope we are emitting a
// non-local `const` (into a namespace) which can reference only
// other `const` variables which since they are non-locals as well
// can be referenced without capturing.
auto captures = cg->cxxBlock() == nullptr ? "" : "&";
result = fmt("[%s]() { auto __xs = ::hilti::rt::Map<%s, %s>(); %s return __xs; }()", captures, k, v, elems);
}

else
Expand Down Expand Up @@ -199,7 +205,13 @@ struct Visitor : hilti::visitor::PreOrder {
[this](const auto& e) { return fmt("__xs.insert(%s);", cg->compile(e)); }),
" ");

result = fmt("[&]() { auto __xs = ::hilti::rt::Set<%s>(); %s return __xs; }()", k, elems);
// If we are at block scope capture other variables so they can be
// used in the ctr. Outside of block scope we are emitting a
// non-local `const` (into a namespace) which can reference only
// other `const` variables which since they are non-locals as well
// can be referenced without capturing.
auto captures = cg->cxxBlock() == nullptr ? "" : "&";
result = fmt("[%s]() { auto __xs = ::hilti::rt::Set<%s>(); %s return __xs; }()", captures, k, elems);
}

else
Expand Down Expand Up @@ -287,8 +299,14 @@ struct Visitor : hilti::visitor::PreOrder {
}),
" ");

result = fmt("[&]() { auto __xs = ::hilti::rt::Vector<%s%s>(); __xs.reserve(%d); %s return __xs; }()", x,
allocator, size, elems);
// If we are at block scope capture other variables so they can be
// used in the ctr. Outside of block scope we are emitting a
// non-local `const` (into a namespace) which can reference only
// other `const` variables which since they are non-locals as well
// can be referenced without capturing.
auto captures = cg->cxxBlock() == nullptr ? "" : "&";
result = fmt("[%s]() { auto __xs = ::hilti::rt::Vector<%s%s>(); __xs.reserve(%d); %s return __xs; }()",
captures, x, allocator, size, elems);
}

else
Expand Down

0 comments on commit 4078611

Please sign in to comment.