google / cel-go

Fast, portable, non-Turing complete expression evaluation with gradual typing (Go)
https://cel.dev
Apache License 2.0
2.3k stars 224 forks source link

Variable Keys in Struct Literals #867

Closed Alucard17 closed 11 months ago

Alucard17 commented 11 months ago

I have encountered unexpected behavior with optional fields in struct literals while using CEL . The issue revolves around how keys are interpreted in struct literals, specifically with respect to optional fields.

env, err := cel.NewEnv(
cel.Variable("name", cel.StringType),
cel.Variable("group", cel.StringType),
)
ast, issues := env.Compile(`{name: 1}`)
if issues != nil && issues.Err() != nil {
log.Fatalf("type-check error: %s", issues.Err())
}
prg, err := env.Program(ast)
if err != nil {
log.Fatalf("program construction error: %s", err)
}
out, _, err := prg.Eval(map[string]interface{}{
"name": "/groups/acme.co/documents/secret-stuff",
"group": "acme.co"})
fmt.Println(out)

I get following output

{/groups/acme.co/documents/secret-stuff: 1}
  1. {name: 1}: In this case, the key name is treated as an identifier, leading to its resolution from the environment variable. The resulting output is {/groups/acme.co/documents/secret-stuff: 1}.
  2. {[name]: 1}: returns {[/groups/acme.co/documents/secret-stuff]: 1}.
  3. {["name"]: 1}: In this example, ["name"] is explicitly quoted, indicating a constant string key. This results in {[name]: 1}, it surrounds the key with square brackets.

The behavior raises concerns about ambiguity when wanting to use a variable as a key. While CEL treats unquoted keys as identifiers and quoted keys as constant strings, it might be beneficial to have clearer guidelines or options for handling such scenarios.