blob: be46deec04801c1a67178ce60607d7c91c7621e2 [file] [edit]
// Copyright 2026 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
//go:build go1.28
package main
// Test composite literals whose type is inferred from
// the assignment context, introduced in go1.28.
// See golang/go#12854 and golang/go#82039.
type T struct{ x, y int }
func val(t T) int { return t.x + t.y }
func ptr(p *T) int { return p.x + p.y }
func retVal() T { return {1, 2} }
func retPtr() *T { return {3, 4} }
func slice(s []int) int { return len(s) }
func retTwo() (T, *T) { return {1, 2}, {3, 4} }
func retGeneric[P *T]() P { return {5, 6} }
func argGeneric[P *T](p P) int { return (*T)(p).x + (*T)(p).y }
type S struct {
V T
P *T
}
// Pointers to arrays.
func ptrArray(p *[3]int) int { return p[0] + p[1] + p[2] }
func retPtrArray() *[3]int { return {1, 2, 3} }
// Pointers to slices and maps (rarely useful, but legal).
func ptrSlice(p *[]int) int { return len(*p) }
func ptrMap(p *map[string]int) int { return (*p)["a"] }
func retPtrSlice() *[]int { return {1, 2, 3} }
func retPtrMap() *map[string]int { return {"a": 7} }
func main() {
if got := val({1, 2}); got != 3 {
panic(got)
}
if got := ptr({3, 4}); got != 7 {
panic(got)
}
if got := retVal(); got != (T{1, 2}) {
panic(got)
}
if got := retPtr(); *got != (T{3, 4}) {
panic(got)
}
if got := slice({1, 2, 3}); got != 3 {
panic(got)
}
// Multi-value return.
if v, p := retTwo(); v != (T{1, 2}) || *p != (T{3, 4}) {
panic("retTwo")
}
// Type parameter whose core type is *T.
if got := retGeneric[*T](); *got != (T{5, 6}) {
panic(got)
}
if got := argGeneric[*T]({7, 8}); got != 15 {
panic(got)
}
// Assignments and declarations.
var p *T = {5, 6}
if p.y != 6 {
panic(p)
}
p = {7, 8}
if p.y != 8 {
panic(p)
}
// Distinct allocations.
if retPtr() == retPtr() {
panic("retPtr aliases")
}
// Conversion.
q := (*T)({9, 10})
if q.x != 9 {
panic(q)
}
// Channel send.
ch := make(chan *T, 1)
ch <- {11, 12}
if r := <-ch; r.y != 12 {
panic(r)
}
// Map key and value.
m := map[T]*T{}
m[{1, 1}] = {2, 2}
if r := m[T{1, 1}]; r == nil || r.x != 2 {
panic(r)
}
// Struct fields.
s := S{V: {1, 2}, P: {3, 4}}
if s.V.y != 2 || s.P.y != 4 {
panic(s)
}
s2 := S{{5, 6}, {7, 8}}
if s2.V.y != 6 || s2.P.y != 8 {
panic(s2)
}
// Reassigning a pointer variable from a literal that reads
// through it allocates a new variable; the old one is unchanged.
old := p
p = {p.y, p.x}
if p.x != 8 || p.y != 7 || old.x != 7 || old.y != 8 {
panic("swap *T")
}
// Pointers to arrays.
if got := ptrArray({1, 2, 3}); got != 6 {
panic(got)
}
if got := ptrArray({2: 5}); got != 5 {
panic(got)
}
if got := retPtrArray(); *got != [3]int{1, 2, 3} {
panic(got)
}
if retPtrArray() == retPtrArray() {
panic("retPtrArray aliases")
}
var pa *[3]int = {4, 5, 6}
olda := pa
pa = {pa[2], pa[1], pa[0]}
if *pa != [3]int{6, 5, 4} || *olda != [3]int{4, 5, 6} {
panic("swap *[3]int")
}
nestedArr := []*[2]int{{1, 2}, {3, 4}}
if nestedArr[1][1] != 4 {
panic(nestedArr[1][1])
}
cha := make(chan *[2]int, 1)
cha <- {7, 8}
if r := <-cha; r[1] != 8 {
panic(r[1])
}
// Pointers to slices and maps.
if got := ptrSlice({1, 2}); got != 2 {
panic(got)
}
if got := ptrMap({"a": 5}); got != 5 {
panic(got)
}
if got := len(*retPtrSlice()); got != 3 {
panic(got)
}
if got := (*retPtrMap())["a"]; got != 7 {
panic(got)
}
var ps *[]int = {4}
if (*ps)[0] != 4 {
panic((*ps)[0])
}
nested := []*[]int{{1}, {2, 3}}
if got := len(*nested[1]); got != 2 {
panic(got)
}
nm := map[*map[int]int]bool{{1: 2}: true}
for k := range nm {
if got := (*k)[1]; got != 2 {
panic(got)
}
}
}