]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: look at underlying type of element type of composite literals with elided...
authorRobert Griesemer <gri@golang.org>
Thu, 17 Nov 2016 21:35:59 +0000 (13:35 -0800)
committerRobert Griesemer <gri@golang.org>
Fri, 18 Nov 2016 00:21:12 +0000 (00:21 +0000)
Match behavior of gc and gccgo.

For #17954.

Change-Id: I3f065e56d0a623bd7642c1438d0cab94d23fa2ae
Reviewed-on: https://go-review.googlesource.com/33358
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
src/go/types/expr.go
src/go/types/testdata/expr3.src

index e1d92ee5ef4f55c5602a300e03f79961135125d3..f76da17fe53360877a85afbc2c7eabd22b06b6be 100644 (file)
@@ -1015,32 +1015,38 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                }
 
        case *ast.CompositeLit:
-               typ := hint
-               openArray := false
-               if e.Type != nil {
+               var typ, base Type
+
+               switch {
+               case e.Type != nil:
+                       // composite literal type present - use it
                        // [...]T array types may only appear with composite literals.
                        // Check for them here so we don't have to handle ... in general.
-                       typ = nil
                        if atyp, _ := e.Type.(*ast.ArrayType); atyp != nil && atyp.Len != nil {
                                if ellip, _ := atyp.Len.(*ast.Ellipsis); ellip != nil && ellip.Elt == nil {
                                        // We have an "open" [...]T array type.
                                        // Create a new ArrayType with unknown length (-1)
                                        // and finish setting it up after analyzing the literal.
                                        typ = &Array{len: -1, elem: check.typ(atyp.Elt)}
-                                       openArray = true
+                                       base = typ
+                                       break
                                }
                        }
-                       if typ == nil {
-                               typ = check.typ(e.Type)
-                       }
-               }
-               if typ == nil {
+                       typ = check.typ(e.Type)
+                       base = typ
+
+               case hint != nil:
+                       // no composite literal type present - use hint (element type of enclosing type)
+                       typ = hint
+                       base, _ = deref(typ.Underlying()) // *T implies &T{}
+
+               default:
                        // TODO(gri) provide better error messages depending on context
                        check.error(e.Pos(), "missing type in composite literal")
                        goto Error
                }
 
-               switch typ, _ := deref(typ); utyp := typ.Underlying().(type) {
+               switch utyp := base.Underlying().(type) {
                case *Struct:
                        if len(e.Elts) == 0 {
                                break
@@ -1109,7 +1115,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
                        // 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 {
+                       if utyp.len < 0 {
                                utyp.len = n
                                check.recordTypeAndValue(e.Type, typexpr, utyp, nil)
                        }
index 53c03e72af7232df541b1db4e51dba460c986581..ab1a9f684b851b16666be81fc0f2c5adda4783f2 100644 (file)
@@ -324,6 +324,22 @@ func slice_literals() {
 
        // recursively so
        _ = [][]T{{}, []T{{}}, {{1, 2, 3}}}
+
+       // issue 17954
+       type T0 *struct { s string }
+       _ = []T0{{}}
+       _ = []T0{{"foo"}}
+
+       type T1 *struct{ int }
+       _ = []T1{}
+       _ = []T1{{0}, {1}, {2}}
+
+       type T2 T1
+       _ = []T2{}
+       _ = []T2{{0}, {1}, {2}}
+
+       _ = map[T0]T2{}
+       _ = map[T0]T2{{}: {}}
 }
 
 const index2 int = 2
@@ -393,6 +409,14 @@ func map_literals() {
        type Point struct { x, y float32 }
        _ = map[string]Point{"orig": {0, 0}}
        _ = map[*Point]string{{0, 0}: "orig"}
+
+       // issue 17954
+       type T0 *struct{ s string }
+       type T1 *struct{ int }
+       type T2 T1
+
+       _ = map[T0]T2{}
+       _ = map[T0]T2{{}: {}}
 }
 
 var key2 string = "bar"