A map literal that contains duplicate keys is evaluated without error; the last value silently wins, instead of failing as the spec requires.
{1: "a", 1: "b"} // -> {1: "b"}, no error
{"k": "x", "k": "y"} // -> {"k": "y"}, no error
{1: "a", 1: "c", 1: "d"} // -> {1: "d"}, no error
The language spec ("Aggregate Values" in langdef) states: "It is an error to have duplicate keys or field names." These expressions should fail with an evaluation error.
This is also inconsistent within cel-go itself. The comprehension path reports the same collision:
{"a": 1, "b": 1}.transformMapEntry(k, v, {v: k})
// error: insert failed: key 1 already exists
mutableMap.Insert (common/types/map.go) detects existing keys using CEL equality, but the map-literal evaluation path (evalMap.Exec in interpreter/interpretable.go) writes into a plain Go map[ref.Val]ref.Val and never checks for duplicates.
Keys are not necessarily constant — they can be computed at runtime (e.g. {("rol" + "e"): "admin", "role": "guest"} evaluates to {"role": "guest"}), so the duplicate is not always visible in the source text or to the type checker.
For comparison, cel-cpp and cel-java both reject duplicate keys (cel-cpp returns a DuplicateKeyError unconditionally; cel-java enables errorOnDuplicateMapKeys by default), so the same expression behaves differently across implementations.
Suggested fix: detect duplicate keys in the map-literal evaluation path using CEL equality, the same way mutableMap.Insert already does, and return an evaluation error.
A map literal that contains duplicate keys is evaluated without error; the last value silently wins, instead of failing as the spec requires.
The language spec ("Aggregate Values" in langdef) states: "It is an error to have duplicate keys or field names." These expressions should fail with an evaluation error.
This is also inconsistent within cel-go itself. The comprehension path reports the same collision:
mutableMap.Insert(common/types/map.go) detects existing keys using CEL equality, but the map-literal evaluation path (evalMap.Execin interpreter/interpretable.go) writes into a plain Gomap[ref.Val]ref.Valand never checks for duplicates.Keys are not necessarily constant — they can be computed at runtime (e.g.
{("rol" + "e"): "admin", "role": "guest"}evaluates to{"role": "guest"}), so the duplicate is not always visible in the source text or to the type checker.For comparison, cel-cpp and cel-java both reject duplicate keys (cel-cpp returns a DuplicateKeyError unconditionally; cel-java enables errorOnDuplicateMapKeys by default), so the same expression behaves differently across implementations.
Suggested fix: detect duplicate keys in the map-literal evaluation path using CEL equality, the same way
mutableMap.Insertalready does, and return an evaluation error.