diff --git a/checker/checker.go b/checker/checker.go index c8d1cd0a1..ec66daf44 100644 --- a/checker/checker.go +++ b/checker/checker.go @@ -125,6 +125,9 @@ func (v *visitor) IdentifierNode(node *ast.IdentifierNode) reflect.Type { return interfaceType } if t, ok := v.types[node.Value]; ok { + if t.Ambiguous { + return v.error(node, "ambiguous identifier %v", node.Value) + } return t.Type } if !v.strict { diff --git a/checker/types.go b/checker/types.go index 387782067..756ed8f5d 100644 --- a/checker/types.go +++ b/checker/types.go @@ -209,7 +209,7 @@ func fieldType(ntype reflect.Type, name string) (reflect.Type, bool) { // First check all struct's fields. for i := 0; i < ntype.NumField(); i++ { f := ntype.Field(i) - if !f.Anonymous && f.Name == name { + if f.Name == name { return f.Type, true } } diff --git a/conf/types_table.go b/conf/types_table.go index 14433b50d..d5539da4a 100644 --- a/conf/types_table.go +++ b/conf/types_table.go @@ -3,8 +3,9 @@ package conf import "reflect" type Tag struct { - Type reflect.Type - Method bool + Type reflect.Type + Method bool + Ambiguous bool } type TypesTable map[string]Tag @@ -73,7 +74,11 @@ func FieldsFromStruct(t reflect.Type) TypesTable { if f.Anonymous { for name, typ := range FieldsFromStruct(f.Type) { - types[name] = typ + if _, ok := types[name]; ok { + types[name] = Tag{Ambiguous: true} + } else { + types[name] = typ + } } } diff --git a/expr_test.go b/expr_test.go index 9c7a38479..3394eb952 100644 --- a/expr_test.go +++ b/expr_test.go @@ -1093,6 +1093,36 @@ func TestEval_exposed_error(t *testing.T) { require.Equal(t, 1, fileError.Line) } +func TestIssue105(t *testing.T) { + type A struct { + Field string + } + type B struct { + Field int + } + type C struct { + A + B + } + type Env struct { + C + } + + code := ` + A.Field == '' && + C.A.Field == '' && + B.Field == 0 && + C.B.Field == 0 + ` + + _, err := expr.Compile(code, expr.Env(Env{})) + require.NoError(t, err) + + _, err = expr.Compile(`Field == ''`, expr.Env(Env{})) + require.Error(t, err) + require.Contains(t, err.Error(), "ambiguous identifier Field") +} + // // Mock types //