diff --git a/compiler/semantic/expr.go b/compiler/semantic/expr.go index fd9ea551f0..68c21341eb 100644 --- a/compiler/semantic/expr.go +++ b/compiler/semantic/expr.go @@ -155,10 +155,15 @@ func (a *analyzer) semExpr(e ast.Expr) (dag.Expr, error) { Where: where, }, nil case *ast.RecordExpr: + fields := map[string]struct{}{} var out []dag.RecordElem for _, elem := range e.Elems { switch elem := elem.(type) { case *ast.Field: + if _, ok := fields[elem.Name]; ok { + return nil, fmt.Errorf("record expression: %w", &zed.DuplicateFieldError{Name: elem.Name}) + } + fields[elem.Name] = struct{}{} e, err := a.semExpr(elem.Value) if err != nil { return nil, err @@ -169,6 +174,10 @@ func (a *analyzer) semExpr(e ast.Expr) (dag.Expr, error) { Value: e, }) case *ast.ID: + if _, ok := fields[elem.Name]; ok { + return nil, fmt.Errorf("record expression: %w", &zed.DuplicateFieldError{Name: elem.Name}) + } + fields[elem.Name] = struct{}{} v, err := a.semID(elem) if err != nil { return nil, err diff --git a/compiler/ztests/record-dup-field.yaml b/compiler/ztests/record-dup-field.yaml new file mode 100644 index 0000000000..bd863558a0 --- /dev/null +++ b/compiler/ztests/record-dup-field.yaml @@ -0,0 +1,3 @@ +zed: yield {x:1,x:2} + +errorRE: 'record expression: duplicate field: "x"'