Commit e54662dc authored by Robert Griesemer's avatar Robert Griesemer

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/33358Reviewed-by: default avatarMatthew Dempsky <mdempsky@google.com>
parent b21743c6
......@@ -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)
}
......
......@@ -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"
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment