mirror of https://github.com/golang/go.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 <mdempsky@google.com>
This commit is contained in:
parent
b21743c6d0
commit
e54662dc85
|
|
@ -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"
|
||||
|
|
|
|||
Loading…
Reference in New Issue