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:
|
case *ast.CompositeLit:
|
||||||
typ := hint
|
var typ, base Type
|
||||||
openArray := false
|
|
||||||
if e.Type != nil {
|
switch {
|
||||||
|
case e.Type != nil:
|
||||||
|
// composite literal type present - use it
|
||||||
// [...]T array types may only appear with composite literals.
|
// [...]T array types may only appear with composite literals.
|
||||||
// Check for them here so we don't have to handle ... in general.
|
// 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 atyp, _ := e.Type.(*ast.ArrayType); atyp != nil && atyp.Len != nil {
|
||||||
if ellip, _ := atyp.Len.(*ast.Ellipsis); ellip != nil && ellip.Elt == nil {
|
if ellip, _ := atyp.Len.(*ast.Ellipsis); ellip != nil && ellip.Elt == nil {
|
||||||
// We have an "open" [...]T array type.
|
// We have an "open" [...]T array type.
|
||||||
// Create a new ArrayType with unknown length (-1)
|
// Create a new ArrayType with unknown length (-1)
|
||||||
// and finish setting it up after analyzing the literal.
|
// and finish setting it up after analyzing the literal.
|
||||||
typ = &Array{len: -1, elem: check.typ(atyp.Elt)}
|
typ = &Array{len: -1, elem: check.typ(atyp.Elt)}
|
||||||
openArray = true
|
base = typ
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if typ == nil {
|
typ = check.typ(e.Type)
|
||||||
typ = check.typ(e.Type)
|
base = typ
|
||||||
}
|
|
||||||
}
|
case hint != nil:
|
||||||
if typ == 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
|
// TODO(gri) provide better error messages depending on context
|
||||||
check.error(e.Pos(), "missing type in composite literal")
|
check.error(e.Pos(), "missing type in composite literal")
|
||||||
goto Error
|
goto Error
|
||||||
}
|
}
|
||||||
|
|
||||||
switch typ, _ := deref(typ); utyp := typ.Underlying().(type) {
|
switch utyp := base.Underlying().(type) {
|
||||||
case *Struct:
|
case *Struct:
|
||||||
if len(e.Elts) == 0 {
|
if len(e.Elts) == 0 {
|
||||||
break
|
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
|
// 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
|
// and record the type for [...] (usually done by check.typExpr which is
|
||||||
// not called for [...]).
|
// not called for [...]).
|
||||||
if openArray {
|
if utyp.len < 0 {
|
||||||
utyp.len = n
|
utyp.len = n
|
||||||
check.recordTypeAndValue(e.Type, typexpr, utyp, nil)
|
check.recordTypeAndValue(e.Type, typexpr, utyp, nil)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -324,6 +324,22 @@ func slice_literals() {
|
||||||
|
|
||||||
// recursively so
|
// recursively so
|
||||||
_ = [][]T{{}, []T{{}}, {{1, 2, 3}}}
|
_ = [][]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
|
const index2 int = 2
|
||||||
|
|
@ -393,6 +409,14 @@ func map_literals() {
|
||||||
type Point struct { x, y float32 }
|
type Point struct { x, y float32 }
|
||||||
_ = map[string]Point{"orig": {0, 0}}
|
_ = map[string]Point{"orig": {0, 0}}
|
||||||
_ = map[*Point]string{{0, 0}: "orig"}
|
_ = 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"
|
var key2 string = "bar"
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue