diff --git a/checker/checker_test.go b/checker/checker_test.go index 602fe4b7..17ec886e 100644 --- a/checker/checker_test.go +++ b/checker/checker_test.go @@ -1090,9 +1090,11 @@ func TestCheck_types(t *testing.T) { err string }{ {`unknown`, noerr}, + {`[unknown + 42, another_unknown + "foo"]`, noerr}, {`foo.bar.baz > 0`, `invalid operation: > (mismatched types string and int)`}, {`foo.unknown.baz`, `unknown field unknown (1:5)`}, {`foo.bar.unknown`, noerr}, + {`foo.bar.unknown + 42`, `invalid operation: + (mismatched types string and int)`}, {`[foo] | map(.unknown)`, `unknown field unknown`}, {`[foo] | map(.bar) | filter(.baz)`, `predicate should return boolean (got string)`}, {`arr | filter(.value > 0)`, `invalid operation: > (mismatched types string and int)`}, diff --git a/checker/nature/nature.go b/checker/nature/nature.go index a385521c..2b09353b 100644 --- a/checker/nature/nature.go +++ b/checker/nature/nature.go @@ -12,16 +12,17 @@ var ( ) type Nature struct { - Type reflect.Type // Type of the value. If nil, then value is unknown. - Func *builtin.Function // Used to pass function type from callee to CallNode. - ArrayOf *Nature // Elem nature of array type (usually Type is []any, but ArrayOf can be any nature). - PredicateOut *Nature // Out nature of predicate. - Fields map[string]Nature // Fields of map type. - Strict bool // If map is types.StrictMap. - Nil bool // If value is nil. - Method bool // If value retrieved from method. Usually used to determine amount of in arguments. - MethodIndex int // Index of method in type. - FieldIndex []int // Index of field in type. + Type reflect.Type // Type of the value. If nil, then value is unknown. + Func *builtin.Function // Used to pass function type from callee to CallNode. + ArrayOf *Nature // Elem nature of array type (usually Type is []any, but ArrayOf can be any nature). + PredicateOut *Nature // Out nature of predicate. + Fields map[string]Nature // Fields of map type. + DefaultMapValue *Nature // Default value of map type. + Strict bool // If map is types.StrictMap. + Nil bool // If value is nil. + Method bool // If value retrieved from method. Usually used to determine amount of in arguments. + MethodIndex int // Index of method in type. + FieldIndex []int // Index of field in type. } func (n Nature) String() string { @@ -54,7 +55,12 @@ func (n Nature) Key() Nature { func (n Nature) Elem() Nature { switch n.Kind() { - case reflect.Map, reflect.Ptr: + case reflect.Ptr: + return Nature{Type: n.Type.Elem()} + case reflect.Map: + if n.DefaultMapValue != nil { + return *n.DefaultMapValue + } return Nature{Type: n.Type.Elem()} case reflect.Array, reflect.Slice: if n.ArrayOf != nil { diff --git a/types/types.go b/types/types.go index d10d2fbc..bb1cbe5f 100644 --- a/types/types.go +++ b/types/types.go @@ -108,6 +108,8 @@ func (m Map) Nature() Nature { for k, v := range m { if k == Extra { nt.Strict = false + natureOfDefaultValue := v.Nature() + nt.DefaultMapValue = &natureOfDefaultValue continue } nt.Fields[k] = v.Nature()