Splat expressions require some odd gymnastics to evaluate, since they are similar to a for expression but with an anonymous iterator symbol.
That anonymous iterator is handled internally via a special expression node type whose value changes dynamically (per EvalContext) during evaluation. Due to how the internals work here, the current implementation cannot safely support concurrent evaluation of the same splat expression from two callers with separate EvalContexts: a map is modified concurrently, which can cause a crash.
As a general rule HCL is not expected to be concurrency-safe in most cases -- that's the caller's responsibility -- but for splat expressions in particular this implementation detail is pretty hard for the caller to properly manage, so we should make an exception here and make AnonSymbolExpr (the expression node that represents the anonymous iterator) use a mutex to allow concurrent evaluations of the same splat expression.
Splat expressions require some odd gymnastics to evaluate, since they are similar to a
for
expression but with an anonymous iterator symbol.That anonymous iterator is handled internally via a special expression node type whose value changes dynamically (per
EvalContext
) during evaluation. Due to how the internals work here, the current implementation cannot safely support concurrent evaluation of the same splat expression from two callers with separateEvalContext
s: a map is modified concurrently, which can cause a crash.As a general rule HCL is not expected to be concurrency-safe in most cases -- that's the caller's responsibility -- but for splat expressions in particular this implementation detail is pretty hard for the caller to properly manage, so we should make an exception here and make
AnonSymbolExpr
(the expression node that represents the anonymous iterator) use a mutex to allow concurrent evaluations of the same splat expression.