Skip to content

Commit

Permalink
fix ambiguous embed struct reference
Browse files Browse the repository at this point in the history
  • Loading branch information
antonmedv committed May 10, 2020
1 parent f006ea4 commit 337130d
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 4 deletions.
3 changes: 3 additions & 0 deletions checker/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
2 changes: 1 addition & 1 deletion checker/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Expand Down
11 changes: 8 additions & 3 deletions conf/types_table.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
}
}
}

Expand Down
30 changes: 30 additions & 0 deletions expr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
//
Expand Down

0 comments on commit 337130d

Please sign in to comment.