Skip to content

Commit e54662d

Browse files
committed
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 <[email protected]>
1 parent b21743c commit e54662d

File tree

2 files changed

+42
-12
lines changed

2 files changed

+42
-12
lines changed

src/go/types/expr.go

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1015,32 +1015,38 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
10151015
}
10161016

10171017
case *ast.CompositeLit:
1018-
typ := hint
1019-
openArray := false
1020-
if e.Type != nil {
1018+
var typ, base Type
1019+
1020+
switch {
1021+
case e.Type != nil:
1022+
// composite literal type present - use it
10211023
// [...]T array types may only appear with composite literals.
10221024
// Check for them here so we don't have to handle ... in general.
1023-
typ = nil
10241025
if atyp, _ := e.Type.(*ast.ArrayType); atyp != nil && atyp.Len != nil {
10251026
if ellip, _ := atyp.Len.(*ast.Ellipsis); ellip != nil && ellip.Elt == nil {
10261027
// We have an "open" [...]T array type.
10271028
// Create a new ArrayType with unknown length (-1)
10281029
// and finish setting it up after analyzing the literal.
10291030
typ = &Array{len: -1, elem: check.typ(atyp.Elt)}
1030-
openArray = true
1031+
base = typ
1032+
break
10311033
}
10321034
}
1033-
if typ == nil {
1034-
typ = check.typ(e.Type)
1035-
}
1036-
}
1037-
if typ == nil {
1035+
typ = check.typ(e.Type)
1036+
base = typ
1037+
1038+
case hint != nil:
1039+
// no composite literal type present - use hint (element type of enclosing type)
1040+
typ = hint
1041+
base, _ = deref(typ.Underlying()) // *T implies &T{}
1042+
1043+
default:
10381044
// TODO(gri) provide better error messages depending on context
10391045
check.error(e.Pos(), "missing type in composite literal")
10401046
goto Error
10411047
}
10421048

1043-
switch typ, _ := deref(typ); utyp := typ.Underlying().(type) {
1049+
switch utyp := base.Underlying().(type) {
10441050
case *Struct:
10451051
if len(e.Elts) == 0 {
10461052
break
@@ -1109,7 +1115,7 @@ func (check *Checker) exprInternal(x *operand, e ast.Expr, hint Type) exprKind {
11091115
// If we have an "open" [...]T array, set the length now that we know it
11101116
// and record the type for [...] (usually done by check.typExpr which is
11111117
// not called for [...]).
1112-
if openArray {
1118+
if utyp.len < 0 {
11131119
utyp.len = n
11141120
check.recordTypeAndValue(e.Type, typexpr, utyp, nil)
11151121
}

src/go/types/testdata/expr3.src

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,22 @@ func slice_literals() {
324324

325325
// recursively so
326326
_ = [][]T{{}, []T{{}}, {{1, 2, 3}}}
327+
328+
// issue 17954
329+
type T0 *struct { s string }
330+
_ = []T0{{}}
331+
_ = []T0{{"foo"}}
332+
333+
type T1 *struct{ int }
334+
_ = []T1{}
335+
_ = []T1{{0}, {1}, {2}}
336+
337+
type T2 T1
338+
_ = []T2{}
339+
_ = []T2{{0}, {1}, {2}}
340+
341+
_ = map[T0]T2{}
342+
_ = map[T0]T2{{}: {}}
327343
}
328344

329345
const index2 int = 2
@@ -393,6 +409,14 @@ func map_literals() {
393409
type Point struct { x, y float32 }
394410
_ = map[string]Point{"orig": {0, 0}}
395411
_ = map[*Point]string{{0, 0}: "orig"}
412+
413+
// issue 17954
414+
type T0 *struct{ s string }
415+
type T1 *struct{ int }
416+
type T2 T1
417+
418+
_ = map[T0]T2{}
419+
_ = map[T0]T2{{}: {}}
396420
}
397421

398422
var key2 string = "bar"

0 commit comments

Comments
 (0)