From: Robert Griesemer Date: Thu, 17 Nov 2016 21:35:59 +0000 (-0800) Subject: go/types: look at underlying type of element type of composite literals with elided... X-Git-Tag: go1.8beta1~107 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=e54662dc859f65f90eefede76a6134f8d892cc77;p=gostls13.git go/types: look at underlying type of element type of composite literals with elided types Match behavior of gc and gccgo. For #17954. Change-Id: I3f065e56d0a623bd7642c1438d0cab94d23fa2ae Reviewed-on: https://go-review.googlesource.com/33358 Reviewed-by: Matthew Dempsky --- diff --git a/src/go/types/expr.go b/src/go/types/expr.go index e1d92ee5ef..f76da17fe5 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -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) } diff --git a/src/go/types/testdata/expr3.src b/src/go/types/testdata/expr3.src index 53c03e72af..ab1a9f684b 100644 --- a/src/go/types/testdata/expr3.src +++ b/src/go/types/testdata/expr3.src @@ -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"