]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: set Info.Types.Type for array composite literals of the form [...]T
authorRobert Griesemer <gri@golang.org>
Thu, 18 Aug 2016 00:05:31 +0000 (17:05 -0700)
committerRobert Griesemer <gri@golang.org>
Thu, 18 Aug 2016 17:11:03 +0000 (17:11 +0000)
Fixes #14092.

Change-Id: I00692f60a416348e38cab256b94fda07e334d258
Reviewed-on: https://go-review.googlesource.com/27316
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/go/types/api_test.go
src/go/types/expr.go

index 1084de316443b7a18cf7ed9ed70eabcd214c4626..e011e6daef4a241a54fe8bea562908068064b607 100644 (file)
@@ -1140,3 +1140,56 @@ func TestIssue15305(t *testing.T) {
        }
        t.Errorf("CallExpr has no type")
 }
+
+// TestCompositeLitTypes verifies that Info.Types registers the correct
+// types for composite literal expressions and composite literal type
+// expressions.
+func TestCompositeLitTypes(t *testing.T) {
+       for _, test := range []struct {
+               lit, typ string
+       }{
+               {`[16]byte{}`, `[16]byte`},
+               {`[...]byte{}`, `[0]byte`},                // test for issue #14092
+               {`[...]int{1, 2, 3}`, `[3]int`},           // test for issue #14092
+               {`[...]int{90: 0, 98: 1, 2}`, `[100]int`}, // test for issue #14092
+               {`[]int{}`, `[]int`},
+               {`map[string]bool{"foo": true}`, `map[string]bool`},
+               {`struct{}{}`, `struct{}`},
+               {`struct{x, y int; z complex128}{}`, `struct{x int; y int; z complex128}`},
+       } {
+               fset := token.NewFileSet()
+               f, err := parser.ParseFile(fset, test.lit, "package p; var _ = "+test.lit, 0)
+               if err != nil {
+                       t.Fatalf("%s: %v", test.lit, err)
+               }
+
+               info := &Info{
+                       Types: make(map[ast.Expr]TypeAndValue),
+               }
+               if _, err = new(Config).Check("p", fset, []*ast.File{f}, info); err != nil {
+                       t.Fatalf("%s: %v", test.lit, err)
+               }
+
+               cmptype := func(x ast.Expr, want string) {
+                       tv, ok := info.Types[x]
+                       if !ok {
+                               t.Errorf("%s: no Types entry found", test.lit)
+                               return
+                       }
+                       if tv.Type == nil {
+                               t.Errorf("%s: type is nil", test.lit)
+                               return
+                       }
+                       if got := tv.Type.String(); got != want {
+                               t.Errorf("%s: got %v, want %s", test.lit, got, want)
+                       }
+               }
+
+               // test type of composite literal expression
+               rhs := f.Decls[0].(*ast.GenDecl).Specs[0].(*ast.ValueSpec).Values[0]
+               cmptype(rhs, test.typ)
+
+               // test type of composite literal type expression
+               cmptype(rhs.(*ast.CompositeLit).Type, test.typ)
+       }
+}
index 4430c45d140fbc0cdb680f73e49b6a27f6adcf05..634c568e2c7440303be48036dfa750f9df2a51a1 100644 (file)
@@ -1106,9 +1106,12 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
 
                case *Array:
                        n := check.indexedElts(e.Elts, utyp.elem, utyp.len)
-                       // if we have an "open" [...]T array, set the length now that we know it
+                       // If we have an "open" [...]T array, set the length now that we know it
+                       // and record the type for [...] (usually done by check.typExpr which is
+                       // not called for [...]).
                        if openArray {
                                utyp.len = n
+                               check.recordTypeAndValue(e.Type, typexpr, utyp, nil)
                        }
 
                case *Slice: