aboutsummaryrefslogtreecommitdiff
path: root/src/pkg/exp
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2012-12-28 10:40:36 -0800
committerRobert Griesemer <gri@golang.org>2012-12-28 10:40:36 -0800
commitd0428379e79d8a3a868fda9509963563e73e10b2 (patch)
tree79deaa0cfe027532765e56689f52299f18102080 /src/pkg/exp
parenteb43ce2d7711ad963de4860b70495a7aba3271c5 (diff)
downloadgo-d0428379e79d8a3a868fda9509963563e73e10b2.tar.xz
exp/types: resolve composite literal keys
The parser/resolver cannot accurately resolve composite literal keys that are identifiers; it needs type information. Instead, try to resolve them but leave final judgement to the type checker. R=adonovan CC=golang-dev https://golang.org/cl/6994047
Diffstat (limited to 'src/pkg/exp')
-rw-r--r--src/pkg/exp/types/check.go2
-rw-r--r--src/pkg/exp/types/expr.go23
-rw-r--r--src/pkg/exp/types/testdata/expr3.src18
3 files changed, 34 insertions, 9 deletions
diff --git a/src/pkg/exp/types/check.go b/src/pkg/exp/types/check.go
index 3708a0af62..db02e03cd7 100644
--- a/src/pkg/exp/types/check.go
+++ b/src/pkg/exp/types/check.go
@@ -23,6 +23,7 @@ type checker struct {
files []*ast.File
// lazily initialized
+ pkgscope *ast.Scope
firsterr error
initexprs map[*ast.ValueSpec][]ast.Expr // "inherited" initialization expressions for constant declarations
funclist []function // list of functions/methods with correct signatures and non-empty bodies
@@ -406,6 +407,7 @@ func check(ctxt *Context, fset *token.FileSet, files map[string]*ast.File) (pkg
check.err(err)
}
}
+ check.pkgscope = pkg.Scope
// determine missing constant initialization expressions
// and associate methods with types
diff --git a/src/pkg/exp/types/expr.go b/src/pkg/exp/types/expr.go
index 6e31323cb6..bf3be532a3 100644
--- a/src/pkg/exp/types/expr.go
+++ b/src/pkg/exp/types/expr.go
@@ -507,8 +507,19 @@ func (check *checker) index(index ast.Expr, length int64, iota int) int64 {
return i
}
+// compositeLitKey resolves unresolved composite literal keys.
+// For details, see comment in go/parser/parser.go, method parseElement.
+func (check *checker) compositeLitKey(key ast.Expr) {
+ if ident, ok := key.(*ast.Ident); ok && ident.Obj == nil {
+ ident.Obj = check.pkgscope.Lookup(ident.Name)
+ if ident.Obj == nil {
+ check.errorf(ident.Pos(), "undeclared name: %s", ident.Name)
+ }
+ }
+}
+
// indexElts checks the elements (elts) of an array or slice composite literal
-// against the literals element type (typ), and the element indices against
+// against the literal's element type (typ), and the element indices against
// the literal length if known (length >= 0). It returns the length of the
// literal (maximum index value + 1).
//
@@ -520,6 +531,7 @@ func (check *checker) indexedElts(elts []ast.Expr, typ Type, length int64, iota
validIndex := false
eval := e
if kv, _ := e.(*ast.KeyValueExpr); kv != nil {
+ check.compositeLitKey(kv.Key)
if i := check.index(kv.Key, length, iota); i >= 0 {
index = i
validIndex = true
@@ -714,14 +726,6 @@ func (check *checker) rawExpr(x *operand, e ast.Expr, hint Type, iota int, cycle
}
case *ast.CompositeLit:
- // TODO(gri) Known bug: The parser doesn't resolve composite literal keys
- // because it cannot know the type of the literal and therefore
- // cannot know if a key is a struct field or not. Consequently,
- // if a key is an identifier, it is unresolved and thus has no
- // ast.Objects associated with it. At the moment, the respective
- // error message is not issued because the type-checker doesn't
- // resolve the identifier, and because it assumes that the parser
- // did the resolution.
typ := hint
openArray := false
if e.Type != nil {
@@ -827,6 +831,7 @@ func (check *checker) rawExpr(x *operand, e ast.Expr, hint Type, iota int, cycle
check.errorf(e.Pos(), "missing key in map literal")
continue
}
+ check.compositeLitKey(kv.Key)
check.expr(x, kv.Key, nil, iota)
if !x.isAssignable(utyp.Key) {
check.errorf(x.pos(), "cannot use %s as %s key in map literal", x, utyp.Key)
diff --git a/src/pkg/exp/types/testdata/expr3.src b/src/pkg/exp/types/testdata/expr3.src
index 35905c4972..519e3f567a 100644
--- a/src/pkg/exp/types/testdata/expr3.src
+++ b/src/pkg/exp/types/testdata/expr3.src
@@ -246,8 +246,17 @@ func slice_literals() {
_ = S0{2.0}
_ = S0{2.1 /* ERROR "cannot use" */ }
_ = S0{"foo" /* ERROR "cannot use" */ }
+
+ // indices must be resolved correctly
+ // (for details, see comment in go/parser/parser.go, method parseElement)
+ index1 := 1
+ _ = S0{index1: 1}
+ _ = S0{index2: 2}
+ _ = S0{index3 /* ERROR "undeclared name" */ : 3}
}
+var index2 int = 2
+
func map_literals() {
type M0 map[string]int
@@ -256,8 +265,17 @@ func map_literals() {
_ = M0{1 /* ERROR "cannot use .* as string key" */ : 2}
_ = M0{"foo": "bar" /* ERROR "cannot use .* as int value" */ }
_ = M0{"foo": 1, "bar": 2, "foo" /* ERROR "duplicate key" */ : 3 }
+
+ // map keys must be resolved correctly
+ // (for detials, see comment in go/parser/parser.go, method parseElement)
+ key1 := "foo"
+ _ = M0{key1: 1}
+ _ = M0{key2: 2}
+ _ = M0{key3 /* ERROR "undeclared name" */ : 2}
}
+var key2 string = "bar"
+
type I interface {
m()
}