Skip to content

NativeTypes doesn't use baseAdapter when it should #1343

@gudvinr

Description

@gudvinr

Describe the bug
A clear and concise description of what the bug is.

To Reproduce
Check which components this affects:

  • parser
  • checker
  • interpreter

Sample expression and input that reproduces the issue:

x == "abc"

Test setup:

//
// setup [ref.Val] wrapper
//

type bogus struct {
    bogus string
}

var BogusType = cel.OpaqueType("bogus.Wrapper")

type wrapper bogus

var _ ref.Val = wrapper{}

func (w wrapper) ConvertToNative(reflect.Type) (any, error)
func (w wrapper) ConvertToType(ref.Type) ref.Val
func (w wrapper) Equal(ref.Val) ref.Val

func (w wrapper) Type() ref.Type { return BogusType }
func (w wrapper) Value() any { return bogus(w) }

//
// setup [types.Adapter]
//

type bogusAdapter struct {
    baseAdapter types.Adapter
}

func (ba *bogusAdapter) NativeToValue(value any) ref.Val {
    switch v := value.(type) {
    case wrapper: return v
    case bogus: return wrapper(v)
    }

    return ba.baseAdapter.NativeToValue(value)
}

func bogusAdapterOption(env *cel.Env) (*cel.Env, error) {
    adapter := bogusAdapter{baseAdapter: env.CELTypeAdapter()},
    return env.Extend(cel.CustomTypeAdapter(&adapter))
}

//
// setup CEL environment
//

env := cel.Env(
    bogusAdapterOption,
    ext.NativeTypes(...),
)

Expected behavior

I am not sure what'd be the solution though. This very well may be the intended behaviour but took me a while to get to the bottom of it. But it doesn't seem like it. ext.NativeTypes accepts reflect.Type and proto descriptors which are getting registered explicitly to nativeTypeProvider. So my assumption was that only registered types will be converted through NativeToValue

Additional context

nativeTypeProvider treats all structures as native types and uses newNativeObject. Thus bogusAdapter.NativeTypes not being called at all.

If you define type as type wrapper string then it should (I think) fall to baseAdapter which makes this even more confusing.

When you swap EnvOption order, it does work.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions