rebase: update K8s packages to v0.32.1

Update K8s packages in go.mod to v0.32.1

Signed-off-by: Praveen M <m.praveen@ibm.com>
This commit is contained in:
Praveen M
2025-01-16 09:41:46 +05:30
committed by mergify[bot]
parent 5aef21ea4e
commit 7eb99fc6c9
2442 changed files with 273386 additions and 47788 deletions

View File

@ -17,7 +17,6 @@ package interpreter
import (
"errors"
"fmt"
"sync"
"github.com/google/cel-go/common/types/ref"
)
@ -167,35 +166,3 @@ type partActivation struct {
func (a *partActivation) UnknownAttributePatterns() []*AttributePattern {
return a.unknowns
}
// varActivation represents a single mutable variable binding.
//
// This activation type should only be used within folds as the fold loop controls the object
// life-cycle.
type varActivation struct {
parent Activation
name string
val ref.Val
}
// Parent implements the Activation interface method.
func (v *varActivation) Parent() Activation {
return v.parent
}
// ResolveName implements the Activation interface method.
func (v *varActivation) ResolveName(name string) (any, bool) {
if name == v.name {
return v.val, true
}
return v.parent.ResolveName(name)
}
var (
// pool of var activations to reduce allocations during folds.
varActivationPool = &sync.Pool{
New: func() any {
return &varActivation{}
},
}
)

View File

@ -178,10 +178,8 @@ func numericValueEquals(value any, celValue ref.Val) bool {
// NewPartialAttributeFactory returns an AttributeFactory implementation capable of performing
// AttributePattern matches with PartialActivation inputs.
func NewPartialAttributeFactory(container *containers.Container,
adapter types.Adapter,
provider types.Provider) AttributeFactory {
fac := NewAttributeFactory(container, adapter, provider)
func NewPartialAttributeFactory(container *containers.Container, adapter types.Adapter, provider types.Provider, opts ...AttrFactoryOption) AttributeFactory {
fac := NewAttributeFactory(container, adapter, provider, opts...)
return &partialAttributeFactory{
AttributeFactory: fac,
container: container,

View File

@ -126,21 +126,39 @@ type NamespacedAttribute interface {
Qualifiers() []Qualifier
}
// AttrFactoryOption specifies a functional option for configuring an attribute factory.
type AttrFactoryOption func(*attrFactory) *attrFactory
// EnableErrorOnBadPresenceTest error generation when a presence test or optional field selection
// is performed on a primitive type.
func EnableErrorOnBadPresenceTest(value bool) AttrFactoryOption {
return func(fac *attrFactory) *attrFactory {
fac.errorOnBadPresenceTest = value
return fac
}
}
// NewAttributeFactory returns a default AttributeFactory which is produces Attribute values
// capable of resolving types by simple names and qualify the values using the supported qualifier
// types: bool, int, string, and uint.
func NewAttributeFactory(cont *containers.Container, a types.Adapter, p types.Provider) AttributeFactory {
return &attrFactory{
func NewAttributeFactory(cont *containers.Container, a types.Adapter, p types.Provider, opts ...AttrFactoryOption) AttributeFactory {
fac := &attrFactory{
container: cont,
adapter: a,
provider: p,
}
for _, o := range opts {
fac = o(fac)
}
return fac
}
type attrFactory struct {
container *containers.Container
adapter types.Adapter
provider types.Provider
errorOnBadPresenceTest bool
}
// AbsoluteAttribute refers to a variable value and an optional qualifier path.
@ -149,12 +167,13 @@ type attrFactory struct {
// resolution rules.
func (r *attrFactory) AbsoluteAttribute(id int64, names ...string) NamespacedAttribute {
return &absoluteAttribute{
id: id,
namespaceNames: names,
qualifiers: []Qualifier{},
adapter: r.adapter,
provider: r.provider,
fac: r,
id: id,
namespaceNames: names,
qualifiers: []Qualifier{},
adapter: r.adapter,
provider: r.provider,
fac: r,
errorOnBadPresenceTest: r.errorOnBadPresenceTest,
}
}
@ -188,11 +207,12 @@ func (r *attrFactory) MaybeAttribute(id int64, name string) Attribute {
// RelativeAttribute refers to an expression and an optional qualifier path.
func (r *attrFactory) RelativeAttribute(id int64, operand Interpretable) Attribute {
return &relativeAttribute{
id: id,
operand: operand,
qualifiers: []Qualifier{},
adapter: r.adapter,
fac: r,
id: id,
operand: operand,
qualifiers: []Qualifier{},
adapter: r.adapter,
fac: r,
errorOnBadPresenceTest: r.errorOnBadPresenceTest,
}
}
@ -214,7 +234,7 @@ func (r *attrFactory) NewQualifier(objType *types.Type, qualID int64, val any, o
}, nil
}
}
return newQualifier(r.adapter, qualID, val, opt)
return newQualifier(r.adapter, qualID, val, opt, r.errorOnBadPresenceTest)
}
type absoluteAttribute struct {
@ -226,6 +246,8 @@ type absoluteAttribute struct {
adapter types.Adapter
provider types.Provider
fac AttributeFactory
errorOnBadPresenceTest bool
}
// ID implements the Attribute interface method.
@ -514,6 +536,8 @@ type relativeAttribute struct {
qualifiers []Qualifier
adapter types.Adapter
fac AttributeFactory
errorOnBadPresenceTest bool
}
// ID is an implementation of the Attribute interface method.
@ -577,7 +601,7 @@ func (a *relativeAttribute) String() string {
return fmt.Sprintf("id: %v, operand: %v", a.id, a.operand)
}
func newQualifier(adapter types.Adapter, id int64, v any, opt bool) (Qualifier, error) {
func newQualifier(adapter types.Adapter, id int64, v any, opt, errorOnBadPresenceTest bool) (Qualifier, error) {
var qual Qualifier
switch val := v.(type) {
case Attribute:
@ -592,71 +616,138 @@ func newQualifier(adapter types.Adapter, id int64, v any, opt bool) (Qualifier,
}, nil
case string:
qual = &stringQualifier{
id: id,
value: val,
celValue: types.String(val),
adapter: adapter,
optional: opt,
id: id,
value: val,
celValue: types.String(val),
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case int:
qual = &intQualifier{
id: id, value: int64(val), celValue: types.Int(val), adapter: adapter, optional: opt,
id: id,
value: int64(val),
celValue: types.Int(val),
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case int32:
qual = &intQualifier{
id: id, value: int64(val), celValue: types.Int(val), adapter: adapter, optional: opt,
id: id,
value: int64(val),
celValue: types.Int(val),
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case int64:
qual = &intQualifier{
id: id, value: val, celValue: types.Int(val), adapter: adapter, optional: opt,
id: id,
value: val,
celValue: types.Int(val),
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case uint:
qual = &uintQualifier{
id: id, value: uint64(val), celValue: types.Uint(val), adapter: adapter, optional: opt,
id: id,
value: uint64(val),
celValue: types.Uint(val),
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case uint32:
qual = &uintQualifier{
id: id, value: uint64(val), celValue: types.Uint(val), adapter: adapter, optional: opt,
id: id,
value: uint64(val),
celValue: types.Uint(val),
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case uint64:
qual = &uintQualifier{
id: id, value: val, celValue: types.Uint(val), adapter: adapter, optional: opt,
id: id,
value: val,
celValue: types.Uint(val),
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case bool:
qual = &boolQualifier{
id: id, value: val, celValue: types.Bool(val), adapter: adapter, optional: opt,
id: id,
value: val,
celValue: types.Bool(val),
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case float32:
qual = &doubleQualifier{
id: id,
value: float64(val),
celValue: types.Double(val),
adapter: adapter,
optional: opt,
id: id,
value: float64(val),
celValue: types.Double(val),
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case float64:
qual = &doubleQualifier{
id: id, value: val, celValue: types.Double(val), adapter: adapter, optional: opt,
id: id,
value: val,
celValue: types.Double(val),
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case types.String:
qual = &stringQualifier{
id: id, value: string(val), celValue: val, adapter: adapter, optional: opt,
id: id,
value: string(val),
celValue: val,
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case types.Int:
qual = &intQualifier{
id: id, value: int64(val), celValue: val, adapter: adapter, optional: opt,
id: id,
value: int64(val),
celValue: val,
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case types.Uint:
qual = &uintQualifier{
id: id, value: uint64(val), celValue: val, adapter: adapter, optional: opt,
id: id,
value: uint64(val),
celValue: val,
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case types.Bool:
qual = &boolQualifier{
id: id, value: bool(val), celValue: val, adapter: adapter, optional: opt,
id: id,
value: bool(val),
celValue: val,
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case types.Double:
qual = &doubleQualifier{
id: id, value: float64(val), celValue: val, adapter: adapter, optional: opt,
id: id,
value: float64(val),
celValue: val,
adapter: adapter,
optional: opt,
errorOnBadPresenceTest: errorOnBadPresenceTest,
}
case *types.Unknown:
qual = &unknownQualifier{id: id, value: val}
@ -687,11 +778,12 @@ func (q *attrQualifier) IsOptional() bool {
}
type stringQualifier struct {
id int64
value string
celValue ref.Val
adapter types.Adapter
optional bool
id int64
value string
celValue ref.Val
adapter types.Adapter
optional bool
errorOnBadPresenceTest bool
}
// ID is an implementation of the Qualifier interface method.
@ -774,7 +866,7 @@ func (q *stringQualifier) qualifyInternal(vars Activation, obj any, presenceTest
return obj, true, nil
}
default:
return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly)
return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly, q.errorOnBadPresenceTest)
}
if presenceTest {
return nil, false, nil
@ -788,11 +880,12 @@ func (q *stringQualifier) Value() ref.Val {
}
type intQualifier struct {
id int64
value int64
celValue ref.Val
adapter types.Adapter
optional bool
id int64
value int64
celValue ref.Val
adapter types.Adapter
optional bool
errorOnBadPresenceTest bool
}
// ID is an implementation of the Qualifier interface method.
@ -898,7 +991,7 @@ func (q *intQualifier) qualifyInternal(vars Activation, obj any, presenceTest, p
return o[i], true, nil
}
default:
return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly)
return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly, q.errorOnBadPresenceTest)
}
if presenceTest {
return nil, false, nil
@ -915,11 +1008,12 @@ func (q *intQualifier) Value() ref.Val {
}
type uintQualifier struct {
id int64
value uint64
celValue ref.Val
adapter types.Adapter
optional bool
id int64
value uint64
celValue ref.Val
adapter types.Adapter
optional bool
errorOnBadPresenceTest bool
}
// ID is an implementation of the Qualifier interface method.
@ -966,7 +1060,7 @@ func (q *uintQualifier) qualifyInternal(vars Activation, obj any, presenceTest,
return obj, true, nil
}
default:
return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly)
return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly, q.errorOnBadPresenceTest)
}
if presenceTest {
return nil, false, nil
@ -980,11 +1074,12 @@ func (q *uintQualifier) Value() ref.Val {
}
type boolQualifier struct {
id int64
value bool
celValue ref.Val
adapter types.Adapter
optional bool
id int64
value bool
celValue ref.Val
adapter types.Adapter
optional bool
errorOnBadPresenceTest bool
}
// ID is an implementation of the Qualifier interface method.
@ -1017,7 +1112,7 @@ func (q *boolQualifier) qualifyInternal(vars Activation, obj any, presenceTest,
return obj, true, nil
}
default:
return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly)
return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly, q.errorOnBadPresenceTest)
}
if presenceTest {
return nil, false, nil
@ -1092,11 +1187,12 @@ func (q *fieldQualifier) Value() ref.Val {
// type may not be known ahead of time and may not conform to the standard types supported as valid
// protobuf map key types.
type doubleQualifier struct {
id int64
value float64
celValue ref.Val
adapter types.Adapter
optional bool
id int64
value float64
celValue ref.Val
adapter types.Adapter
optional bool
errorOnBadPresenceTest bool
}
// ID is an implementation of the Qualifier interface method.
@ -1120,7 +1216,7 @@ func (q *doubleQualifier) QualifyIfPresent(vars Activation, obj any, presenceOnl
}
func (q *doubleQualifier) qualifyInternal(vars Activation, obj any, presenceTest, presenceOnly bool) (any, bool, error) {
return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly)
return refQualify(q.adapter, obj, q.celValue, presenceTest, presenceOnly, q.errorOnBadPresenceTest)
}
// Value implements the ConstantQualifier interface
@ -1226,7 +1322,7 @@ func attrQualifyIfPresent(fac AttributeFactory, vars Activation, obj any, qualAt
// refQualify attempts to convert the value to a CEL value and then uses reflection methods to try and
// apply the qualifier with the option to presence test field accesses before retrieving field values.
func refQualify(adapter types.Adapter, obj any, idx ref.Val, presenceTest, presenceOnly bool) (ref.Val, bool, error) {
func refQualify(adapter types.Adapter, obj any, idx ref.Val, presenceTest, presenceOnly, errorOnBadPresenceTest bool) (ref.Val, bool, error) {
celVal := adapter.NativeToValue(obj)
switch v := celVal.(type) {
case *types.Unknown:
@ -1283,7 +1379,7 @@ func refQualify(adapter types.Adapter, obj any, idx ref.Val, presenceTest, prese
}
return val, true, nil
default:
if presenceTest {
if presenceTest && !errorOnBadPresenceTest {
return nil, false, nil
}
return nil, false, missingKey(idx)

View File

@ -16,6 +16,7 @@ package interpreter
import (
"fmt"
"sync"
"github.com/google/cel-go/common/functions"
"github.com/google/cel-go/common/operators"
@ -96,7 +97,7 @@ type InterpretableCall interface {
Args() []Interpretable
}
// InterpretableConstructor interface for inspecting Interpretable instructions that initialize a list, map
// InterpretableConstructor interface for inspecting Interpretable instructions that initialize a list, map
// or struct.
type InterpretableConstructor interface {
Interpretable
@ -720,24 +721,31 @@ func (o *evalObj) Eval(ctx Activation) ref.Val {
return types.LabelErrNode(o.id, o.provider.NewValue(o.typeName, fieldVals))
}
// InitVals implements the InterpretableConstructor interface method.
func (o *evalObj) InitVals() []Interpretable {
return o.vals
}
// Type implements the InterpretableConstructor interface method.
func (o *evalObj) Type() ref.Type {
return types.NewObjectTypeValue(o.typeName)
return types.NewObjectType(o.typeName)
}
type evalFold struct {
id int64
accuVar string
iterVar string
iterRange Interpretable
accu Interpretable
cond Interpretable
step Interpretable
result Interpretable
adapter types.Adapter
id int64
accuVar string
iterVar string
iterVar2 string
iterRange Interpretable
accu Interpretable
cond Interpretable
step Interpretable
result Interpretable
adapter types.Adapter
// note an exhaustive fold will ensure that all branches are evaluated
// when using mutable values, these branches will mutate the final result
// rather than make a throw-away computation.
exhaustive bool
interruptable bool
}
@ -749,64 +757,30 @@ func (fold *evalFold) ID() int64 {
// Eval implements the Interpretable interface method.
func (fold *evalFold) Eval(ctx Activation) ref.Val {
// Initialize the folder interface
f := newFolder(fold, ctx)
defer releaseFolder(f)
foldRange := fold.iterRange.Eval(ctx)
if fold.iterVar2 != "" {
var foldable traits.Foldable
switch r := foldRange.(type) {
case traits.Mapper:
foldable = types.ToFoldableMap(r)
case traits.Lister:
foldable = types.ToFoldableList(r)
default:
return types.NewErrWithNodeID(fold.ID(), "unsupported comprehension range type: %T", foldRange)
}
foldable.Fold(f)
return f.evalResult()
}
if !foldRange.Type().HasTrait(traits.IterableType) {
return types.ValOrErr(foldRange, "got '%T', expected iterable type", foldRange)
}
// Configure the fold activation with the accumulator initial value.
accuCtx := varActivationPool.Get().(*varActivation)
accuCtx.parent = ctx
accuCtx.name = fold.accuVar
accuCtx.val = fold.accu.Eval(ctx)
// If the accumulator starts as an empty list, then the comprehension will build a list
// so create a mutable list to optimize the cost of the inner loop.
l, ok := accuCtx.val.(traits.Lister)
buildingList := false
if !fold.exhaustive && ok && l.Size() == types.IntZero {
buildingList = true
accuCtx.val = types.NewMutableList(fold.adapter)
}
iterCtx := varActivationPool.Get().(*varActivation)
iterCtx.parent = accuCtx
iterCtx.name = fold.iterVar
interrupted := false
it := foldRange.(traits.Iterable).Iterator()
for it.HasNext() == types.True {
// Modify the iter var in the fold activation.
iterCtx.val = it.Next()
// Evaluate the condition, terminate the loop if false.
cond := fold.cond.Eval(iterCtx)
condBool, ok := cond.(types.Bool)
if !fold.exhaustive && ok && condBool != types.True {
break
}
// Evaluate the evaluation step into accu var.
accuCtx.val = fold.step.Eval(iterCtx)
if fold.interruptable {
if stop, found := ctx.ResolveName("#interrupted"); found && stop == true {
interrupted = true
break
}
}
}
varActivationPool.Put(iterCtx)
if interrupted {
varActivationPool.Put(accuCtx)
return types.NewErr("operation interrupted")
}
// Compute the result.
res := fold.result.Eval(accuCtx)
varActivationPool.Put(accuCtx)
// Convert a mutable list to an immutable one, if the comprehension has generated a list as a result.
if !types.IsUnknownOrError(res) && buildingList {
if _, ok := res.(traits.MutableLister); ok {
res = res.(traits.MutableLister).ToImmutableList()
}
}
return res
iterable := foldRange.(traits.Iterable)
return f.foldIterable(iterable)
}
// Optional Interpretable implementations that specialize, subsume, or extend the core evaluation
@ -1262,3 +1236,172 @@ func invalidOptionalEntryInit(field any, value ref.Val) ref.Val {
func invalidOptionalElementInit(value ref.Val) ref.Val {
return types.NewErr("cannot initialize optional list element from non-optional value %v", value)
}
// newFolder creates or initializes a pooled folder instance.
func newFolder(eval *evalFold, ctx Activation) *folder {
f := folderPool.Get().(*folder)
f.evalFold = eval
f.Activation = ctx
return f
}
// releaseFolder resets and releases a pooled folder instance.
func releaseFolder(f *folder) {
f.reset()
folderPool.Put(f)
}
// folder tracks the state associated with folding a list or map with a comprehension v2 style macro.
//
// The folder embeds an interpreter.Activation and Interpretable evalFold value as well as implements
// the traits.Folder interface methods.
//
// Instances of a folder are intended to be pooled to minimize allocation overhead with this temporary
// bookkeeping object which supports lazy evaluation of the accumulator init expression which is useful
// in preserving evaluation order semantics which might otherwise be disrupted through the use of
// cel.bind or cel.@block.
type folder struct {
*evalFold
Activation
// fold state objects.
accuVal ref.Val
iterVar1Val any
iterVar2Val any
// bookkeeping flags to modify Activation and fold behaviors.
initialized bool
mutableValue bool
interrupted bool
computeResult bool
}
func (f *folder) foldIterable(iterable traits.Iterable) ref.Val {
it := iterable.Iterator()
for it.HasNext() == types.True {
f.iterVar1Val = it.Next()
cond := f.cond.Eval(f)
condBool, ok := cond.(types.Bool)
if f.interrupted || (!f.exhaustive && ok && condBool != types.True) {
return f.evalResult()
}
// Update the accumulation value and check for eval interuption.
f.accuVal = f.step.Eval(f)
f.initialized = true
if f.interruptable && checkInterrupt(f.Activation) {
f.interrupted = true
return f.evalResult()
}
}
return f.evalResult()
}
// FoldEntry will either fold comprehension v1 style macros if iterVar2 is unset, or comprehension v2 style
// macros if both the iterVar and iterVar2 are set to non-empty strings.
func (f *folder) FoldEntry(key, val any) bool {
// Default to referencing both values.
f.iterVar1Val = key
f.iterVar2Val = val
// Terminate evaluation if evaluation is interrupted or the condition is not true and exhaustive
// eval is not enabled.
cond := f.cond.Eval(f)
condBool, ok := cond.(types.Bool)
if f.interrupted || (!f.exhaustive && ok && condBool != types.True) {
return false
}
// Update the accumulation value and check for eval interuption.
f.accuVal = f.step.Eval(f)
f.initialized = true
if f.interruptable && checkInterrupt(f.Activation) {
f.interrupted = true
return false
}
return true
}
// ResolveName overrides the default Activation lookup to perform lazy initialization of the accumulator
// and specialized lookups of iteration values with consideration for whether the final result is being
// computed and the iteration variables should be ignored.
func (f *folder) ResolveName(name string) (any, bool) {
if name == f.accuVar {
if !f.initialized {
f.initialized = true
initVal := f.accu.Eval(f.Activation)
if !f.exhaustive {
if l, isList := initVal.(traits.Lister); isList && l.Size() == types.IntZero {
initVal = types.NewMutableList(f.adapter)
f.mutableValue = true
}
if m, isMap := initVal.(traits.Mapper); isMap && m.Size() == types.IntZero {
initVal = types.NewMutableMap(f.adapter, map[ref.Val]ref.Val{})
f.mutableValue = true
}
}
f.accuVal = initVal
}
return f.accuVal, true
}
if !f.computeResult {
if name == f.iterVar {
f.iterVar1Val = f.adapter.NativeToValue(f.iterVar1Val)
return f.iterVar1Val, true
}
if name == f.iterVar2 {
f.iterVar2Val = f.adapter.NativeToValue(f.iterVar2Val)
return f.iterVar2Val, true
}
}
return f.Activation.ResolveName(name)
}
// evalResult computes the final result of the fold after all entries have been folded and accumulated.
func (f *folder) evalResult() ref.Val {
f.computeResult = true
if f.interrupted {
return types.NewErr("operation interrupted")
}
res := f.result.Eval(f)
// Convert a mutable list or map to an immutable one if the comprehension has generated a list or
// map as a result.
if !types.IsUnknownOrError(res) && f.mutableValue {
if _, ok := res.(traits.MutableLister); ok {
res = res.(traits.MutableLister).ToImmutableList()
}
if _, ok := res.(traits.MutableMapper); ok {
res = res.(traits.MutableMapper).ToImmutableMap()
}
}
return res
}
// reset clears any state associated with folder evaluation.
func (f *folder) reset() {
f.evalFold = nil
f.Activation = nil
f.accuVal = nil
f.iterVar1Val = nil
f.iterVar2Val = nil
f.initialized = false
f.mutableValue = false
f.interrupted = false
f.computeResult = false
}
func checkInterrupt(a Activation) bool {
stop, found := a.ResolveName("#interrupted")
return found && stop == true
}
var (
// pool of var folders to reduce allocations during folds.
folderPool = &sync.Pool{
New: func() any {
return &folder{}
},
}
)

View File

@ -603,6 +603,7 @@ func (p *planner) planComprehension(expr ast.Expr) (Interpretable, error) {
accuVar: fold.AccuVar(),
accu: accu,
iterVar: fold.IterVar(),
iterVar2: fold.IterVar2(),
iterRange: iterRange,
cond: cond,
step: step,