Initial commit: Go 1.23 release state

This commit is contained in:
Vorapol Rinsatitnon
2024-09-21 23:49:08 +10:00
commit 17cd57a668
13231 changed files with 3114330 additions and 0 deletions

94
test/typeparam/absdiff.go Normal file
View File

@@ -0,0 +1,94 @@
// run
// Copyright 2020 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.
package main
type Numeric interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64 |
~complex64 | ~complex128
}
// numericAbs matches numeric types with an Abs method.
type numericAbs[T any] interface {
Numeric
Abs() T
}
// AbsDifference computes the absolute value of the difference of
// a and b, where the absolute value is determined by the Abs method.
func absDifference[T numericAbs[T]](a, b T) T {
d := a - b
return d.Abs()
}
// orderedNumeric matches numeric types that support the < operator.
type orderedNumeric interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64
}
// Complex matches the two complex types, which do not have a < operator.
type Complex interface {
~complex64 | ~complex128
}
// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639).
// // orderedAbs is a helper type that defines an Abs method for
// // ordered numeric types.
// type orderedAbs[T orderedNumeric] T
//
// func (a orderedAbs[T]) Abs() orderedAbs[T] {
// if a < 0 {
// return -a
// }
// return a
// }
//
// // complexAbs is a helper type that defines an Abs method for
// // complex types.
// type complexAbs[T Complex] T
//
// func (a complexAbs[T]) Abs() complexAbs[T] {
// r := float64(real(a))
// i := float64(imag(a))
// d := math.Sqrt(r*r + i*i)
// return complexAbs[T](complex(d, 0))
// }
//
// // OrderedAbsDifference returns the absolute value of the difference
// // between a and b, where a and b are of an ordered type.
// func orderedAbsDifference[T orderedNumeric](a, b T) T {
// return T(absDifference(orderedAbs[T](a), orderedAbs[T](b)))
// }
//
// // ComplexAbsDifference returns the absolute value of the difference
// // between a and b, where a and b are of a complex type.
// func complexAbsDifference[T Complex](a, b T) T {
// return T(absDifference(complexAbs[T](a), complexAbs[T](b)))
// }
func main() {
// // For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639).
// if got, want := orderedAbsDifference(1.0, -2.0), 3.0; got != want {
// panic(fmt.Sprintf("got = %v, want = %v", got, want))
// }
// if got, want := orderedAbsDifference(-1.0, 2.0), 3.0; got != want {
// panic(fmt.Sprintf("got = %v, want = %v", got, want))
// }
// if got, want := orderedAbsDifference(-20, 15), 35; got != want {
// panic(fmt.Sprintf("got = %v, want = %v", got, want))
// }
//
// if got, want := complexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want {
// panic(fmt.Sprintf("got = %v, want = %v", got, want))
// }
// if got, want := complexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want {
// panic(fmt.Sprintf("got = %v, want = %v", got, want))
// }
}

135
test/typeparam/absdiff2.go Normal file
View File

@@ -0,0 +1,135 @@
// run
// Copyright 2022 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.
// absdiff example in which an Abs method is attached to a generic type, which is a
// structure with a single field that may be a list of possible basic types.
package main
import (
"fmt"
"math"
)
type Numeric interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64 |
~complex64 | ~complex128
}
// numericAbs matches a struct containing a numeric type that has an Abs method.
type numericAbs[T Numeric] interface {
~struct{ Value_ T }
Abs() T
Value() T
}
// absDifference computes the absolute value of the difference of
// a and b, where the absolute value is determined by the Abs method.
func absDifference[T Numeric, U numericAbs[T]](a, b U) T {
d := a.Value() - b.Value()
dt := U{Value_: d}
return dt.Abs()
}
// orderedNumeric matches numeric types that support the < operator.
type orderedNumeric interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64
}
// Complex matches the two complex types, which do not have a < operator.
type Complex interface {
~complex64 | ~complex128
}
// orderedAbs is a helper type that defines an Abs method for
// a struct containing an ordered numeric type.
type orderedAbs[T orderedNumeric] struct {
Value_ T
}
func (a orderedAbs[T]) Abs() T {
if a.Value_ < 0 {
return -a.Value_
}
return a.Value_
}
// Field accesses through type parameters are disabled
// until we have a more thorough understanding of the
// implications on the spec. See issue #51576.
// Use accessor method instead.
func (a orderedAbs[T]) Value() T {
return a.Value_
}
// complexAbs is a helper type that defines an Abs method for
// a struct containing a complex type.
type complexAbs[T Complex] struct {
Value_ T
}
func realimag(x any) (re, im float64) {
switch z := x.(type) {
case complex64:
re = float64(real(z))
im = float64(imag(z))
case complex128:
re = real(z)
im = imag(z)
default:
panic("unknown complex type")
}
return
}
func (a complexAbs[T]) Abs() T {
// TODO use direct conversion instead of realimag once #50937 is fixed
r, i := realimag(a.Value_)
// r := float64(real(a.Value))
// i := float64(imag(a.Value))
d := math.Sqrt(r*r + i*i)
return T(complex(d, 0))
}
func (a complexAbs[T]) Value() T {
return a.Value_
}
// OrderedAbsDifference returns the absolute value of the difference
// between a and b, where a and b are of an ordered type.
func OrderedAbsDifference[T orderedNumeric](a, b T) T {
return absDifference(orderedAbs[T]{a}, orderedAbs[T]{b})
}
// ComplexAbsDifference returns the absolute value of the difference
// between a and b, where a and b are of a complex type.
func ComplexAbsDifference[T Complex](a, b T) T {
return absDifference(complexAbs[T]{a}, complexAbs[T]{b})
}
func main() {
if got, want := OrderedAbsDifference(1.0, -2.0), 3.0; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
if got, want := OrderedAbsDifference(-1.0, 2.0), 3.0; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
if got, want := OrderedAbsDifference(-20, 15), 35; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
if got, want := ComplexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
if got, want := ComplexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
}

View File

@@ -0,0 +1,98 @@
// run
// Copyright 2022 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.
// absdiff example using a function argument rather than attaching an
// Abs method to a structure containing base types.
package main
import (
"fmt"
"math"
)
type Numeric interface {
OrderedNumeric | Complex
}
// absDifference computes the absolute value of the difference of
// a and b, where the absolute value is determined by the abs function.
func absDifference[T Numeric](a, b T, abs func(a T) T) T {
return abs(a - b)
}
// OrderedNumeric matches numeric types that support the < operator.
type OrderedNumeric interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64
}
func Abs[T OrderedNumeric](a T) T {
if a < 0 {
return -a
}
return a
}
// Complex matches the two complex types, which do not have a < operator.
type Complex interface {
~complex64 | ~complex128
}
func realimag(x any) (re, im float64) {
switch z := x.(type) {
case complex64:
re = float64(real(z))
im = float64(imag(z))
case complex128:
re = real(z)
im = imag(z)
default:
panic("unknown complex type")
}
return
}
func ComplexAbs[T Complex](a T) T {
// TODO use direct conversion instead of realimag once #50937 is fixed
r, i := realimag(a)
// r := float64(real(a))
// i := float64(imag(a))
d := math.Sqrt(r*r + i*i)
return T(complex(d, 0))
}
// OrderedAbsDifference returns the absolute value of the difference
// between a and b, where a and b are of an ordered type.
func OrderedAbsDifference[T OrderedNumeric](a, b T) T {
return absDifference(a, b, Abs[T])
}
// ComplexAbsDifference returns the absolute value of the difference
// between a and b, where a and b are of a complex type.
func ComplexAbsDifference[T Complex](a, b T) T {
return absDifference(a, b, ComplexAbs[T])
}
func main() {
if got, want := OrderedAbsDifference(1.0, -2.0), 3.0; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
if got, want := OrderedAbsDifference(-1.0, 2.0), 3.0; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
if got, want := OrderedAbsDifference(-20, 15), 35; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
if got, want := ComplexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
if got, want := ComplexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
}

View File

@@ -0,0 +1,72 @@
// Copyright 2021 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.
package a
type Numeric interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64 |
~complex64 | ~complex128
}
// numericAbs matches numeric types with an Abs method.
type numericAbs[T any] interface {
Numeric
Abs() T
}
// AbsDifference computes the absolute value of the difference of
// a and b, where the absolute value is determined by the Abs method.
func absDifference[T numericAbs[T]](a, b T) T {
d := a - b
return d.Abs()
}
// orderedNumeric matches numeric types that support the < operator.
type orderedNumeric interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64
}
// Complex matches the two complex types, which do not have a < operator.
type Complex interface {
~complex64 | ~complex128
}
// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639).
// // orderedAbs is a helper type that defines an Abs method for
// // ordered numeric types.
// type orderedAbs[T orderedNumeric] T
//
// func (a orderedAbs[T]) Abs() orderedAbs[T] {
// if a < 0 {
// return -a
// }
// return a
// }
//
// // complexAbs is a helper type that defines an Abs method for
// // complex types.
// type complexAbs[T Complex] T
//
// func (a complexAbs[T]) Abs() complexAbs[T] {
// r := float64(real(a))
// i := float64(imag(a))
// d := math.Sqrt(r*r + i*i)
// return complexAbs[T](complex(d, 0))
// }
//
// // OrderedAbsDifference returns the absolute value of the difference
// // between a and b, where a and b are of an ordered type.
// func OrderedAbsDifference[T orderedNumeric](a, b T) T {
// return T(absDifference(orderedAbs[T](a), orderedAbs[T](b)))
// }
//
// // ComplexAbsDifference returns the absolute value of the difference
// // between a and b, where a and b are of a complex type.
// func ComplexAbsDifference[T Complex](a, b T) T {
// return T(absDifference(complexAbs[T](a), complexAbs[T](b)))
// }

View File

@@ -0,0 +1,25 @@
// Copyright 2021 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.
package main
func main() {
// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639).
// if got, want := a.OrderedAbsDifference(1.0, -2.0), 3.0; got != want {
// panic(fmt.Sprintf("got = %v, want = %v", got, want))
// }
// if got, want := a.OrderedAbsDifference(-1.0, 2.0), 3.0; got != want {
// panic(fmt.Sprintf("got = %v, want = %v", got, want))
// }
// if got, want := a.OrderedAbsDifference(-20, 15), 35; got != want {
// panic(fmt.Sprintf("got = %v, want = %v", got, want))
// }
//
// if got, want := a.ComplexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want {
// panic(fmt.Sprintf("got = %v, want = %v", got, want))
// }
// if got, want := a.ComplexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want {
// panic(fmt.Sprintf("got = %v, want = %v", got, want))
// }
}

View File

@@ -0,0 +1,7 @@
// rundir
// Copyright 2021 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.
package ignored

View File

@@ -0,0 +1,110 @@
// Copyright 2022 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.
package a
import (
"math"
)
type Numeric interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64 |
~complex64 | ~complex128
}
// numericAbs matches a struct containing a numeric type that has an Abs method.
type numericAbs[T Numeric] interface {
~struct{ Value_ T }
Abs() T
Value() T
}
// absDifference computes the absolute value of the difference of
// a and b, where the absolute value is determined by the Abs method.
func absDifference[T Numeric, U numericAbs[T]](a, b U) T {
d := a.Value() - b.Value()
dt := U{Value_: d}
return dt.Abs()
}
// orderedNumeric matches numeric types that support the < operator.
type orderedNumeric interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
~float32 | ~float64
}
// Complex matches the two complex types, which do not have a < operator.
type Complex interface {
~complex64 | ~complex128
}
// orderedAbs is a helper type that defines an Abs method for
// a struct containing an ordered numeric type.
type orderedAbs[T orderedNumeric] struct {
Value_ T
}
func (a orderedAbs[T]) Abs() T {
if a.Value_ < 0 {
return -a.Value_
}
return a.Value_
}
// Field accesses through type parameters are disabled
// until we have a more thorough understanding of the
// implications on the spec. See issue #51576.
// Use accessor method instead.
func (a orderedAbs[T]) Value() T {
return a.Value_
}
// complexAbs is a helper type that defines an Abs method for
// a struct containing a complex type.
type complexAbs[T Complex] struct {
Value_ T
}
func realimag(x any) (re, im float64) {
switch z := x.(type) {
case complex64:
re = float64(real(z))
im = float64(imag(z))
case complex128:
re = real(z)
im = imag(z)
default:
panic("unknown complex type")
}
return
}
func (a complexAbs[T]) Abs() T {
// TODO use direct conversion instead of realimag once #50937 is fixed
r, i := realimag(a.Value_)
// r := float64(real(a.Value))
// i := float64(imag(a.Value))
d := math.Sqrt(r*r + i*i)
return T(complex(d, 0))
}
func (a complexAbs[T]) Value() T {
return a.Value_
}
// OrderedAbsDifference returns the absolute value of the difference
// between a and b, where a and b are of an ordered type.
func OrderedAbsDifference[T orderedNumeric](a, b T) T {
return absDifference(orderedAbs[T]{a}, orderedAbs[T]{b})
}
// ComplexAbsDifference returns the absolute value of the difference
// between a and b, where a and b are of a complex type.
func ComplexAbsDifference[T Complex](a, b T) T {
return absDifference(complexAbs[T]{a}, complexAbs[T]{b})
}

View File

@@ -0,0 +1,29 @@
// Copyright 2021 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.
package main
import (
"./a"
"fmt"
)
func main() {
if got, want := a.OrderedAbsDifference(1.0, -2.0), 3.0; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
if got, want := a.OrderedAbsDifference(-1.0, 2.0), 3.0; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
if got, want := a.OrderedAbsDifference(-20, 15), 35; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
if got, want := a.ComplexAbsDifference(5.0+2.0i, 2.0-2.0i), 5+0i; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
if got, want := a.ComplexAbsDifference(2.0-2.0i, 5.0+2.0i), 5+0i; got != want {
panic(fmt.Sprintf("got = %v, want = %v", got, want))
}
}

View File

@@ -0,0 +1,7 @@
// rundir
// Copyright 2021 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.
package ignored

29
test/typeparam/adder.go Normal file
View File

@@ -0,0 +1,29 @@
// run
// Copyright 2021 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.
package main
import (
"fmt"
)
type AddType interface {
int | int64 | string
}
// Add can add numbers or strings
func Add[T AddType](a, b T) T {
return a + b
}
func main() {
if got, want := Add(5, 3), 8; got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
if got, want := Add("ab", "cd"), "abcd"; got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
}

View File

@@ -0,0 +1,9 @@
// Copyright 2020 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.
package a
type Rimp[T any] struct {
F T
}

View File

@@ -0,0 +1,41 @@
// Copyright 2020 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.
package main
import "./a"
type R[T any] struct {
F T
}
// type S = R // disallowed for now
type Sint = R[int]
// type Simp = a.Rimp // disallowed for now
// type SimpString Simp[string] // disallowed for now
type SimpString a.Rimp[string]
func main() {
// var s S[int] // disallowed for now
var s R[int]
if s.F != 0 {
panic(s.F)
}
var s2 Sint
if s2.F != 0 {
panic(s2.F)
}
// var s3 Simp[string] // disallowed for now
var s3 a.Rimp[string]
if s3.F != "" {
panic(s3.F)
}
var s4 SimpString
if s4.F != "" {
panic(s4.F)
}
}

View File

@@ -0,0 +1,7 @@
// rundir
// Copyright 2021 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.
package ignored

31
test/typeparam/append.go Normal file
View File

@@ -0,0 +1,31 @@
// run
// Copyright 2021 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.
package main
type Recv <-chan int
type sliceOf[E any] interface {
~[]E
}
func _Append[S sliceOf[T], T any](s S, t ...T) S {
return append(s, t...)
}
func main() {
recv := make(Recv)
a := _Append([]Recv{recv}, recv)
if len(a) != 2 || a[0] != recv || a[1] != recv {
panic(a)
}
recv2 := make(chan<- int)
a2 := _Append([]chan<- int{recv2}, recv2)
if len(a2) != 2 || a2[0] != recv2 || a2[1] != recv2 {
panic(a)
}
}

View File

@@ -0,0 +1,108 @@
// run
// Copyright 2021 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.
// This test illustrates how a type bound method (String below) can be implemented
// either by a concrete type (myint below) or an instantiated generic type
// (StringInt[myint] below).
package main
import (
"fmt"
"reflect"
"strconv"
)
type myint int
//go:noinline
func (m myint) String() string {
return strconv.Itoa(int(m))
}
type Stringer interface {
String() string
}
func stringify[T Stringer](s []T) (ret []string) {
for _, v := range s {
// Test normal bounds method call on type param
x1 := v.String()
// Test converting type param to its bound interface first
v1 := Stringer(v)
x2 := v1.String()
// Test method expression with type param type
f1 := T.String
x3 := f1(v)
// Test creating and calling closure equivalent to the method expression
f2 := func(v1 T) string {
return Stringer(v1).String()
}
x4 := f2(v)
if x1 != x2 || x2 != x3 || x3 != x4 {
panic(fmt.Sprintf("Mismatched values %v, %v, %v, %v\n", x1, x2, x3, x4))
}
ret = append(ret, v.String())
}
return ret
}
type Ints interface {
~int32 | ~int
}
// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639).
// type StringInt[T Ints] T
//
// //go:noinline
// func (m StringInt[T]) String() string {
// return strconv.Itoa(int(m))
// }
type StringStruct[T Ints] struct {
f T
}
func (m StringStruct[T]) String() string {
return strconv.Itoa(int(m.f))
}
func main() {
x := []myint{myint(1), myint(2), myint(3)}
// stringify on a normal type, whose bound method is associated with the base type.
got := stringify(x)
want := []string{"1", "2", "3"}
if !reflect.DeepEqual(got, want) {
panic(fmt.Sprintf("got %s, want %s", got, want))
}
// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639).
// x2 := []StringInt[myint]{StringInt[myint](5), StringInt[myint](7), StringInt[myint](6)}
//
// // stringify on an instantiated type, whose bound method is associated with
// // the generic type StringInt[T], which maps directly to T.
// got2 := stringify(x2)
// want2 := []string{"5", "7", "6"}
// if !reflect.DeepEqual(got2, want2) {
// panic(fmt.Sprintf("got %s, want %s", got2, want2))
// }
// stringify on an instantiated type, whose bound method is associated with
// the generic type StringStruct[T], which maps to a struct containing T.
x3 := []StringStruct[myint]{StringStruct[myint]{f: 11}, StringStruct[myint]{f: 10}, StringStruct[myint]{f: 9}}
got3 := stringify(x3)
want3 := []string{"11", "10", "9"}
if !reflect.DeepEqual(got3, want3) {
panic(fmt.Sprintf("got %s, want %s", got3, want3))
}
}

112
test/typeparam/builtins.go Normal file
View File

@@ -0,0 +1,112 @@
// compile
// Copyright 2020 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.
// This file tests built-in calls on generic types.
// derived and expanded from cmd/compile/internal/types2/testdata/check/builtins.go2
package builtins
// close
type C0 interface{ int }
type C1 interface{ chan int }
type C2 interface{ chan int | <-chan int }
type C3 interface{ chan int | chan float32 }
type C4 interface{ chan int | chan<- int }
type C5[T any] interface{ ~chan T | chan<- T }
func f1[T C1](ch T) {
close(ch)
}
func f2[T C3](ch T) {
close(ch)
}
func f3[T C4](ch T) {
close(ch)
}
func f4[T C5[X], X any](ch T) {
close(ch)
}
// delete
type M0 interface{ int }
type M1 interface{ map[string]int }
type M2 interface {
map[string]int | map[string]float64
}
type M3 interface{ map[string]int | map[rune]int }
type M4[K comparable, V any] interface{ map[K]V | map[rune]V }
func g1[T M1](m T) {
delete(m, "foo")
}
func g2[T M2](m T) {
delete(m, "foo")
}
func g3[T M4[rune, V], V any](m T) {
delete(m, 'k')
}
// make
func m1[
S1 interface{ []int },
S2 interface{ []int | chan int },
M1 interface{ map[string]int },
M2 interface{ map[string]int | chan int },
C1 interface{ chan int },
C2 interface{ chan int | chan string },
]() {
type m1S0 []int
type m1M0 map[string]int
type m1C0 chan int
_ = make([]int, 10)
_ = make(m1S0, 10)
_ = make(S1, 10)
_ = make(S1, 10, 20)
_ = make(map[string]int)
_ = make(m1M0)
_ = make(M1)
_ = make(M1, 10)
_ = make(chan int)
_ = make(m1C0)
_ = make(C1)
_ = make(C1, 10)
}
// len/cap
type Slice[T any] interface {
[]T
}
func c1[T any, S Slice[T]]() {
x := make(S, 5, 10)
_ = len(x)
_ = cap(x)
}
// append
func a1[T any, S Slice[T]]() {
x := make(S, 5)
y := make(S, 2)
var z T
_ = append(x, y...)
_ = append(x, z)
}

413
test/typeparam/chans.go Normal file
View File

@@ -0,0 +1,413 @@
// run
// Copyright 2021 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.
// Package chans provides utility functions for working with channels.
package main
import (
"context"
"fmt"
"runtime"
"sort"
"sync"
"time"
)
// _Equal reports whether two slices are equal: the same length and all
// elements equal. All floating point NaNs are considered equal.
func _SliceEqual[Elem comparable](s1, s2 []Elem) bool {
if len(s1) != len(s2) {
return false
}
for i, v1 := range s1 {
v2 := s2[i]
if v1 != v2 {
isNaN := func(f Elem) bool { return f != f }
if !isNaN(v1) || !isNaN(v2) {
return false
}
}
}
return true
}
// _ReadAll reads from c until the channel is closed or the context is
// canceled, returning all the values read.
func _ReadAll[Elem any](ctx context.Context, c <-chan Elem) []Elem {
var r []Elem
for {
select {
case <-ctx.Done():
return r
case v, ok := <-c:
if !ok {
return r
}
r = append(r, v)
}
}
}
// _Merge merges two channels into a single channel.
// This will leave a goroutine running until either both channels are closed
// or the context is canceled, at which point the returned channel is closed.
func _Merge[Elem any](ctx context.Context, c1, c2 <-chan Elem) <-chan Elem {
r := make(chan Elem)
go func(ctx context.Context, c1, c2 <-chan Elem, r chan<- Elem) {
defer close(r)
for c1 != nil || c2 != nil {
select {
case <-ctx.Done():
return
case v1, ok := <-c1:
if ok {
r <- v1
} else {
c1 = nil
}
case v2, ok := <-c2:
if ok {
r <- v2
} else {
c2 = nil
}
}
}
}(ctx, c1, c2, r)
return r
}
// _Filter calls f on each value read from c. If f returns true the value
// is sent on the returned channel. This will leave a goroutine running
// until c is closed or the context is canceled, at which point the
// returned channel is closed.
func _Filter[Elem any](ctx context.Context, c <-chan Elem, f func(Elem) bool) <-chan Elem {
r := make(chan Elem)
go func(ctx context.Context, c <-chan Elem, f func(Elem) bool, r chan<- Elem) {
defer close(r)
for {
select {
case <-ctx.Done():
return
case v, ok := <-c:
if !ok {
return
}
if f(v) {
r <- v
}
}
}
}(ctx, c, f, r)
return r
}
// _Sink returns a channel that discards all values sent to it.
// This will leave a goroutine running until the context is canceled
// or the returned channel is closed.
func _Sink[Elem any](ctx context.Context) chan<- Elem {
r := make(chan Elem)
go func(ctx context.Context, r <-chan Elem) {
for {
select {
case <-ctx.Done():
return
case _, ok := <-r:
if !ok {
return
}
}
}
}(ctx, r)
return r
}
// An Exclusive is a value that may only be used by a single goroutine
// at a time. This is implemented using channels rather than a mutex.
type _Exclusive[Val any] struct {
c chan Val
}
// _MakeExclusive makes an initialized exclusive value.
func _MakeExclusive[Val any](initial Val) *_Exclusive[Val] {
r := &_Exclusive[Val]{
c: make(chan Val, 1),
}
r.c <- initial
return r
}
// _Acquire acquires the exclusive value for private use.
// It must be released using the Release method.
func (e *_Exclusive[Val]) Acquire() Val {
return <-e.c
}
// TryAcquire attempts to acquire the value. The ok result reports whether
// the value was acquired. If the value is acquired, it must be released
// using the Release method.
func (e *_Exclusive[Val]) TryAcquire() (v Val, ok bool) {
select {
case r := <-e.c:
return r, true
default:
return v, false
}
}
// Release updates and releases the value.
// This method panics if the value has not been acquired.
func (e *_Exclusive[Val]) Release(v Val) {
select {
case e.c <- v:
default:
panic("_Exclusive Release without Acquire")
}
}
// Ranger returns a Sender and a Receiver. The Receiver provides a
// Next method to retrieve values. The Sender provides a Send method
// to send values and a Close method to stop sending values. The Next
// method indicates when the Sender has been closed, and the Send
// method indicates when the Receiver has been freed.
//
// This is a convenient way to exit a goroutine sending values when
// the receiver stops reading them.
func _Ranger[Elem any]() (*_Sender[Elem], *_Receiver[Elem]) {
c := make(chan Elem)
d := make(chan struct{})
s := &_Sender[Elem]{
values: c,
done: d,
}
r := &_Receiver[Elem]{
values: c,
done: d,
}
runtime.SetFinalizer(r, (*_Receiver[Elem]).finalize)
return s, r
}
// A _Sender is used to send values to a Receiver.
type _Sender[Elem any] struct {
values chan<- Elem
done <-chan struct{}
}
// Send sends a value to the receiver. It reports whether the value was sent.
// The value will not be sent if the context is closed or the receiver
// is freed.
func (s *_Sender[Elem]) Send(ctx context.Context, v Elem) bool {
select {
case <-ctx.Done():
return false
case s.values <- v:
return true
case <-s.done:
return false
}
}
// Close tells the receiver that no more values will arrive.
// After Close is called, the _Sender may no longer be used.
func (s *_Sender[Elem]) Close() {
close(s.values)
}
// A _Receiver receives values from a _Sender.
type _Receiver[Elem any] struct {
values <-chan Elem
done chan<- struct{}
}
// Next returns the next value from the channel. The bool result indicates
// whether the value is valid.
func (r *_Receiver[Elem]) Next(ctx context.Context) (v Elem, ok bool) {
select {
case <-ctx.Done():
case v, ok = <-r.values:
}
return v, ok
}
// finalize is a finalizer for the receiver.
func (r *_Receiver[Elem]) finalize() {
close(r.done)
}
func TestReadAll() {
c := make(chan int)
go func() {
c <- 4
c <- 2
c <- 5
close(c)
}()
got := _ReadAll(context.Background(), c)
want := []int{4, 2, 5}
if !_SliceEqual(got, want) {
panic(fmt.Sprintf("_ReadAll returned %v, want %v", got, want))
}
}
func TestMerge() {
c1 := make(chan int)
c2 := make(chan int)
go func() {
c1 <- 1
c1 <- 3
c1 <- 5
close(c1)
}()
go func() {
c2 <- 2
c2 <- 4
c2 <- 6
close(c2)
}()
ctx := context.Background()
got := _ReadAll(ctx, _Merge(ctx, c1, c2))
sort.Ints(got)
want := []int{1, 2, 3, 4, 5, 6}
if !_SliceEqual(got, want) {
panic(fmt.Sprintf("_Merge returned %v, want %v", got, want))
}
}
func TestFilter() {
c := make(chan int)
go func() {
c <- 1
c <- 2
c <- 3
close(c)
}()
even := func(i int) bool { return i%2 == 0 }
ctx := context.Background()
got := _ReadAll(ctx, _Filter(ctx, c, even))
want := []int{2}
if !_SliceEqual(got, want) {
panic(fmt.Sprintf("_Filter returned %v, want %v", got, want))
}
}
func TestSink() {
c := _Sink[int](context.Background())
after := time.NewTimer(time.Minute)
defer after.Stop()
send := func(v int) {
select {
case c <- v:
case <-after.C:
panic("timed out sending to _Sink")
}
}
send(1)
send(2)
send(3)
close(c)
}
func TestExclusive() {
val := 0
ex := _MakeExclusive(&val)
var wg sync.WaitGroup
f := func() {
defer wg.Done()
for i := 0; i < 10; i++ {
p := ex.Acquire()
(*p)++
ex.Release(p)
}
}
wg.Add(2)
go f()
go f()
wg.Wait()
if val != 20 {
panic(fmt.Sprintf("after Acquire/Release loop got %d, want 20", val))
}
}
func TestExclusiveTry() {
s := ""
ex := _MakeExclusive(&s)
p, ok := ex.TryAcquire()
if !ok {
panic("TryAcquire failed")
}
*p = "a"
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
_, ok := ex.TryAcquire()
if ok {
panic(fmt.Sprintf("TryAcquire succeeded unexpectedly"))
}
}()
wg.Wait()
ex.Release(p)
p, ok = ex.TryAcquire()
if !ok {
panic(fmt.Sprintf("TryAcquire failed"))
}
}
func TestRanger() {
s, r := _Ranger[int]()
ctx := context.Background()
go func() {
// Receive one value then exit.
v, ok := r.Next(ctx)
if !ok {
panic(fmt.Sprintf("did not receive any values"))
} else if v != 1 {
panic(fmt.Sprintf("received %d, want 1", v))
}
}()
c1 := make(chan bool)
c2 := make(chan bool)
go func() {
defer close(c2)
if !s.Send(ctx, 1) {
panic(fmt.Sprintf("Send failed unexpectedly"))
}
close(c1)
if s.Send(ctx, 2) {
panic(fmt.Sprintf("Send succeeded unexpectedly"))
}
}()
<-c1
// Force a garbage collection to try to get the finalizers to run.
runtime.GC()
select {
case <-c2:
case <-time.After(time.Minute):
panic("_Ranger Send should have failed, but timed out")
}
}
func main() {
TestReadAll()
TestMerge()
TestFilter()
TestSink()
TestExclusive()
TestExclusiveTry()
TestRanger()
}

View File

@@ -0,0 +1,232 @@
// Copyright 2021 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.
package a
import (
"context"
"runtime"
)
// Equal reports whether two slices are equal: the same length and all
// elements equal. All floating point NaNs are considered equal.
func SliceEqual[Elem comparable](s1, s2 []Elem) bool {
if len(s1) != len(s2) {
return false
}
for i, v1 := range s1 {
v2 := s2[i]
if v1 != v2 {
isNaN := func(f Elem) bool { return f != f }
if !isNaN(v1) || !isNaN(v2) {
return false
}
}
}
return true
}
// ReadAll reads from c until the channel is closed or the context is
// canceled, returning all the values read.
func ReadAll[Elem any](ctx context.Context, c <-chan Elem) []Elem {
var r []Elem
for {
select {
case <-ctx.Done():
return r
case v, ok := <-c:
if !ok {
return r
}
r = append(r, v)
}
}
}
// Merge merges two channels into a single channel.
// This will leave a goroutine running until either both channels are closed
// or the context is canceled, at which point the returned channel is closed.
func Merge[Elem any](ctx context.Context, c1, c2 <-chan Elem) <-chan Elem {
r := make(chan Elem)
go func(ctx context.Context, c1, c2 <-chan Elem, r chan<- Elem) {
defer close(r)
for c1 != nil || c2 != nil {
select {
case <-ctx.Done():
return
case v1, ok := <-c1:
if ok {
r <- v1
} else {
c1 = nil
}
case v2, ok := <-c2:
if ok {
r <- v2
} else {
c2 = nil
}
}
}
}(ctx, c1, c2, r)
return r
}
// Filter calls f on each value read from c. If f returns true the value
// is sent on the returned channel. This will leave a goroutine running
// until c is closed or the context is canceled, at which point the
// returned channel is closed.
func Filter[Elem any](ctx context.Context, c <-chan Elem, f func(Elem) bool) <-chan Elem {
r := make(chan Elem)
go func(ctx context.Context, c <-chan Elem, f func(Elem) bool, r chan<- Elem) {
defer close(r)
for {
select {
case <-ctx.Done():
return
case v, ok := <-c:
if !ok {
return
}
if f(v) {
r <- v
}
}
}
}(ctx, c, f, r)
return r
}
// Sink returns a channel that discards all values sent to it.
// This will leave a goroutine running until the context is canceled
// or the returned channel is closed.
func Sink[Elem any](ctx context.Context) chan<- Elem {
r := make(chan Elem)
go func(ctx context.Context, r <-chan Elem) {
for {
select {
case <-ctx.Done():
return
case _, ok := <-r:
if !ok {
return
}
}
}
}(ctx, r)
return r
}
// An Exclusive is a value that may only be used by a single goroutine
// at a time. This is implemented using channels rather than a mutex.
type Exclusive[Val any] struct {
c chan Val
}
// MakeExclusive makes an initialized exclusive value.
func MakeExclusive[Val any](initial Val) *Exclusive[Val] {
r := &Exclusive[Val]{
c: make(chan Val, 1),
}
r.c <- initial
return r
}
// Acquire acquires the exclusive value for private use.
// It must be released using the Release method.
func (e *Exclusive[Val]) Acquire() Val {
return <-e.c
}
// TryAcquire attempts to acquire the value. The ok result reports whether
// the value was acquired. If the value is acquired, it must be released
// using the Release method.
func (e *Exclusive[Val]) TryAcquire() (v Val, ok bool) {
select {
case r := <-e.c:
return r, true
default:
return v, false
}
}
// Release updates and releases the value.
// This method panics if the value has not been acquired.
func (e *Exclusive[Val]) Release(v Val) {
select {
case e.c <- v:
default:
panic("Exclusive Release without Acquire")
}
}
// Ranger returns a Sender and a Receiver. The Receiver provides a
// Next method to retrieve values. The Sender provides a Send method
// to send values and a Close method to stop sending values. The Next
// method indicates when the Sender has been closed, and the Send
// method indicates when the Receiver has been freed.
//
// This is a convenient way to exit a goroutine sending values when
// the receiver stops reading them.
func Ranger[Elem any]() (*Sender[Elem], *Receiver[Elem]) {
c := make(chan Elem)
d := make(chan struct{})
s := &Sender[Elem]{
values: c,
done: d,
}
r := &Receiver[Elem]{
values: c,
done: d,
}
runtime.SetFinalizer(r, (*Receiver[Elem]).finalize)
return s, r
}
// A Sender is used to send values to a Receiver.
type Sender[Elem any] struct {
values chan<- Elem
done <-chan struct{}
}
// Send sends a value to the receiver. It reports whether the value was sent.
// The value will not be sent if the context is closed or the receiver
// is freed.
func (s *Sender[Elem]) Send(ctx context.Context, v Elem) bool {
select {
case <-ctx.Done():
return false
case s.values <- v:
return true
case <-s.done:
return false
}
}
// Close tells the receiver that no more values will arrive.
// After Close is called, the Sender may no longer be used.
func (s *Sender[Elem]) Close() {
close(s.values)
}
// A Receiver receives values from a Sender.
type Receiver[Elem any] struct {
values <-chan Elem
done chan<- struct{}
}
// Next returns the next value from the channel. The bool result indicates
// whether the value is valid.
func (r *Receiver[Elem]) Next(ctx context.Context) (v Elem, ok bool) {
select {
case <-ctx.Done():
case v, ok = <-r.values:
}
return v, ok
}
// finalize is a finalizer for the receiver.
func (r *Receiver[Elem]) finalize() {
close(r.done)
}

View File

@@ -0,0 +1,189 @@
// Copyright 2021 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.
package main
import (
"./a"
"context"
"fmt"
"runtime"
"sort"
"sync"
"time"
)
func TestReadAll() {
c := make(chan int)
go func() {
c <- 4
c <- 2
c <- 5
close(c)
}()
got := a.ReadAll(context.Background(), c)
want := []int{4, 2, 5}
if !a.SliceEqual(got, want) {
panic(fmt.Sprintf("ReadAll returned %v, want %v", got, want))
}
}
func TestMerge() {
c1 := make(chan int)
c2 := make(chan int)
go func() {
c1 <- 1
c1 <- 3
c1 <- 5
close(c1)
}()
go func() {
c2 <- 2
c2 <- 4
c2 <- 6
close(c2)
}()
ctx := context.Background()
got := a.ReadAll(ctx, a.Merge(ctx, c1, c2))
sort.Ints(got)
want := []int{1, 2, 3, 4, 5, 6}
if !a.SliceEqual(got, want) {
panic(fmt.Sprintf("Merge returned %v, want %v", got, want))
}
}
func TestFilter() {
c := make(chan int)
go func() {
c <- 1
c <- 2
c <- 3
close(c)
}()
even := func(i int) bool { return i%2 == 0 }
ctx := context.Background()
got := a.ReadAll(ctx, a.Filter(ctx, c, even))
want := []int{2}
if !a.SliceEqual(got, want) {
panic(fmt.Sprintf("Filter returned %v, want %v", got, want))
}
}
func TestSink() {
c := a.Sink[int](context.Background())
after := time.NewTimer(time.Minute)
defer after.Stop()
send := func(v int) {
select {
case c <- v:
case <-after.C:
panic("timed out sending to Sink")
}
}
send(1)
send(2)
send(3)
close(c)
}
func TestExclusive() {
val := 0
ex := a.MakeExclusive(&val)
var wg sync.WaitGroup
f := func() {
defer wg.Done()
for i := 0; i < 10; i++ {
p := ex.Acquire()
(*p)++
ex.Release(p)
}
}
wg.Add(2)
go f()
go f()
wg.Wait()
if val != 20 {
panic(fmt.Sprintf("after Acquire/Release loop got %d, want 20", val))
}
}
func TestExclusiveTry() {
s := ""
ex := a.MakeExclusive(&s)
p, ok := ex.TryAcquire()
if !ok {
panic("TryAcquire failed")
}
*p = "a"
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
_, ok := ex.TryAcquire()
if ok {
panic(fmt.Sprintf("TryAcquire succeeded unexpectedly"))
}
}()
wg.Wait()
ex.Release(p)
p, ok = ex.TryAcquire()
if !ok {
panic(fmt.Sprintf("TryAcquire failed"))
}
}
func TestRanger() {
s, r := a.Ranger[int]()
ctx := context.Background()
go func() {
// Receive one value then exit.
v, ok := r.Next(ctx)
if !ok {
panic(fmt.Sprintf("did not receive any values"))
} else if v != 1 {
panic(fmt.Sprintf("received %d, want 1", v))
}
}()
c1 := make(chan bool)
c2 := make(chan bool)
go func() {
defer close(c2)
if !s.Send(ctx, 1) {
panic(fmt.Sprintf("Send failed unexpectedly"))
}
close(c1)
if s.Send(ctx, 2) {
panic(fmt.Sprintf("Send succeeded unexpectedly"))
}
}()
<-c1
// Force a garbage collection to try to get the finalizers to run.
runtime.GC()
select {
case <-c2:
case <-time.After(time.Minute):
panic("Ranger Send should have failed, but timed out")
}
}
func main() {
TestReadAll()
TestMerge()
TestFilter()
TestSink()
TestExclusive()
TestExclusiveTry()
TestRanger()
}

View File

@@ -0,0 +1,7 @@
// rundir
// Copyright 2021 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.
package ignored

65
test/typeparam/combine.go Normal file
View File

@@ -0,0 +1,65 @@
// run
// Copyright 2021 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.
package main
import (
"fmt"
)
type Gen[A any] func() (A, bool)
func Combine[T1, T2, T any](g1 Gen[T1], g2 Gen[T2], join func(T1, T2) T) Gen[T] {
return func() (T, bool) {
var t T
t1, ok := g1()
if !ok {
return t, false
}
t2, ok := g2()
if !ok {
return t, false
}
return join(t1, t2), true
}
}
type Pair[A, B any] struct {
A A
B B
}
func _NewPair[A, B any](a A, b B) Pair[A, B] {
return Pair[A, B]{a, b}
}
func Combine2[A, B any](ga Gen[A], gb Gen[B]) Gen[Pair[A, B]] {
return Combine(ga, gb, _NewPair[A, B])
}
func main() {
var g1 Gen[int] = func() (int, bool) { return 3, true }
var g2 Gen[string] = func() (string, bool) { return "x", false }
var g3 Gen[string] = func() (string, bool) { return "y", true }
gc := Combine(g1, g2, _NewPair[int, string])
if got, ok := gc(); ok {
panic(fmt.Sprintf("got %v, %v, wanted -/false", got, ok))
}
gc2 := Combine2(g1, g2)
if got, ok := gc2(); ok {
panic(fmt.Sprintf("got %v, %v, wanted -/false", got, ok))
}
gc3 := Combine(g1, g3, _NewPair[int, string])
if got, ok := gc3(); !ok || got.A != 3 || got.B != "y" {
panic(fmt.Sprintf("got %v, %v, wanted {3, y}, true", got, ok))
}
gc4 := Combine2(g1, g3)
if got, ok := gc4(); !ok || got.A != 3 || got.B != "y" {
panic(fmt.Sprintf("got %v, %v, wanted {3, y}, true", got, ok))
}
}

100
test/typeparam/cons.go Normal file
View File

@@ -0,0 +1,100 @@
// run
// Copyright 2021 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.
package main
import "fmt"
// Overriding the predeclare "any", so it can be used as a type constraint or a type
// argument
type any interface{}
type Function[a, b any] interface {
Apply(x a) b
}
type incr struct{ n int }
func (this incr) Apply(x int) int {
return x + this.n
}
type pos struct{}
func (this pos) Apply(x int) bool {
return x > 0
}
type compose[a, b, c any] struct {
f Function[a, b]
g Function[b, c]
}
func (this compose[a, b, c]) Apply(x a) c {
return this.g.Apply(this.f.Apply(x))
}
type _Eq[a any] interface {
Equal(a) bool
}
type Int int
func (this Int) Equal(that int) bool {
return int(this) == that
}
type List[a any] interface {
Match(casenil Function[Nil[a], any], casecons Function[Cons[a], any]) any
}
type Nil[a any] struct {
}
func (xs Nil[a]) Match(casenil Function[Nil[a], any], casecons Function[Cons[a], any]) any {
return casenil.Apply(xs)
}
type Cons[a any] struct {
Head a
Tail List[a]
}
func (xs Cons[a]) Match(casenil Function[Nil[a], any], casecons Function[Cons[a], any]) any {
return casecons.Apply(xs)
}
type mapNil[a, b any] struct {
}
func (m mapNil[a, b]) Apply(_ Nil[a]) any {
return Nil[b]{}
}
type mapCons[a, b any] struct {
f Function[a, b]
}
func (m mapCons[a, b]) Apply(xs Cons[a]) any {
return Cons[b]{m.f.Apply(xs.Head), Map[a, b](m.f, xs.Tail)}
}
func Map[a, b any](f Function[a, b], xs List[a]) List[b] {
return xs.Match(mapNil[a, b]{}, mapCons[a, b]{f}).(List[b])
}
func main() {
var xs List[int] = Cons[int]{3, Cons[int]{6, Nil[int]{}}}
var ys List[int] = Map[int, int](incr{-5}, xs)
var xz List[bool] = Map[int, bool](pos{}, ys)
cs1 := xz.(Cons[bool])
cs2 := cs1.Tail.(Cons[bool])
_, ok := cs2.Tail.(Nil[bool])
if cs1.Head != false || cs2.Head != true || !ok {
panic(fmt.Sprintf("got %v, %v, %v, expected false, true, true",
cs1.Head, cs2.Head, ok))
}
}

View File

@@ -0,0 +1,10 @@
// Copyright 2021 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.
package a
//go:noinline
func F[T comparable](a, b T) bool {
return a == b
}

View File

@@ -0,0 +1,14 @@
// Copyright 2021 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.
package b
import "./a"
func B() {
var x int64
println(a.F(&x, &x))
var y int32
println(a.F(&y, &y))
}

View File

@@ -0,0 +1,14 @@
// Copyright 2021 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.
package c
import "./a"
func C() {
var x int64
println(a.F(&x, &x))
var y int32
println(a.F(&y, &y))
}

View File

@@ -0,0 +1,15 @@
// Copyright 2021 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.
package main
import (
"./b"
"./c"
)
func main() {
b.B()
c.C()
}

12
test/typeparam/dedup.go Normal file
View File

@@ -0,0 +1,12 @@
// rundir
// Copyright 2021 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.
// Note: this doesn't really test the deduplication of
// instantiations. It just provides an easy mechanism to build a
// binary that you can then check with objdump manually to make sure
// deduplication is happening. TODO: automate this somehow?
package ignored

4
test/typeparam/dedup.out Normal file
View File

@@ -0,0 +1,4 @@
true
true
true
true

View File

@@ -0,0 +1,22 @@
// run
// Copyright 2023 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.
package main
type S struct {
x int
}
func (t *S) M1() {
}
func F[T any](x T) any {
return x
}
func main() {
F(&S{}).(interface{ M1() }).M1()
}

View File

@@ -0,0 +1,28 @@
// run
// Copyright 2023 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.
package main
type S struct {
x int
}
func (t *S) M1() {
}
func (t *S) M2() {
}
type I interface {
M1()
}
func F[T I](x T) I {
return x
}
func main() {
F(&S{}).(interface{ M2() }).M2()
}

View File

@@ -0,0 +1,126 @@
// run -gcflags="-l"
// Copyright 2021 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.
// Test situations where functions/methods are not
// immediately called and we need to capture the dictionary
// required for later invocation.
package main
func main() {
functions()
methodExpressions()
methodValues()
interfaceMethods()
globals()
}
func g0[T any](x T) {
}
func g1[T any](x T) T {
return x
}
func g2[T any](x T) (T, T) {
return x, x
}
func functions() {
f0 := g0[int]
f0(7)
f1 := g1[int]
is7(f1(7))
f2 := g2[int]
is77(f2(7))
}
func is7(x int) {
if x != 7 {
println(x)
panic("assertion failed")
}
}
func is77(x, y int) {
if x != 7 || y != 7 {
println(x, y)
panic("assertion failed")
}
}
type s[T any] struct {
a T
}
func (x s[T]) g0() {
}
func (x s[T]) g1() T {
return x.a
}
func (x s[T]) g2() (T, T) {
return x.a, x.a
}
func methodExpressions() {
x := s[int]{a: 7}
f0 := s[int].g0
f0(x)
f1 := s[int].g1
is7(f1(x))
f2 := s[int].g2
is77(f2(x))
}
func methodValues() {
x := s[int]{a: 7}
f0 := x.g0
f0()
f1 := x.g1
is7(f1())
f2 := x.g2
is77(f2())
}
var x interface {
g0()
g1() int
g2() (int, int)
} = s[int]{a: 7}
var y interface{} = s[int]{a: 7}
func interfaceMethods() {
x.g0()
is7(x.g1())
is77(x.g2())
y.(interface{ g0() }).g0()
is7(y.(interface{ g1() int }).g1())
is77(y.(interface{ g2() (int, int) }).g2())
}
// Also check for instantiations outside functions.
var gg0 = g0[int]
var gg1 = g1[int]
var gg2 = g2[int]
var hh0 = s[int].g0
var hh1 = s[int].g1
var hh2 = s[int].g2
var xtop = s[int]{a: 7}
var ii0 = x.g0
var ii1 = x.g1
var ii2 = x.g2
func globals() {
gg0(7)
is7(gg1(7))
is77(gg2(7))
x := s[int]{a: 7}
hh0(x)
is7(hh1(x))
is77(hh2(x))
ii0()
is7(ii1())
is77(ii2())
}

View File

@@ -0,0 +1,203 @@
// run
// Copyright 2021 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.
// Test situations where functions/methods are not
// immediately called and we need to capture the dictionary
// required for later invocation.
package main
import (
"fmt"
)
func main() {
functions()
methodExpressions()
genMethodExpressions[int](7)
methodValues()
genMethodValues[int](7)
interfaceMethods()
globals()
recursive()
}
func g0[T any](x T) {
}
func g1[T any](x T) T {
return x
}
func g2[T any](x T) (T, T) {
return x, x
}
func functions() {
f0 := g0[int]
f0(7)
f1 := g1[int]
is7(f1(7))
f2 := g2[int]
is77(f2(7))
}
func is7(x int) {
if x != 7 {
println(x)
panic("assertion failed")
}
}
func is77(x, y int) {
if x != 7 || y != 7 {
println(x, y)
panic("assertion failed")
}
}
type s[T any] struct {
a T
}
func (x s[T]) g0() {
}
func (x s[T]) g1() T {
return x.a
}
func (x s[T]) g2() (T, T) {
return x.a, x.a
}
func methodExpressions() {
x := s[int]{a: 7}
f0 := s[int].g0
f0(x)
f0p := (*s[int]).g0
f0p(&x)
f1 := s[int].g1
is7(f1(x))
f1p := (*s[int]).g1
is7(f1p(&x))
f2 := s[int].g2
is77(f2(x))
f2p := (*s[int]).g2
is77(f2p(&x))
}
func genMethodExpressions[T comparable](want T) {
x := s[T]{a: want}
f0 := s[T].g0
f0(x)
f0p := (*s[T]).g0
f0p(&x)
f1 := s[T].g1
if got := f1(x); got != want {
panic(fmt.Sprintf("f1(x) == %d, want %d", got, want))
}
f1p := (*s[T]).g1
if got := f1p(&x); got != want {
panic(fmt.Sprintf("f1p(&x) == %d, want %d", got, want))
}
f2 := s[T].g2
if got1, got2 := f2(x); got1 != want || got2 != want {
panic(fmt.Sprintf("f2(x) == %d, %d, want %d, %d", got1, got2, want, want))
}
}
func methodValues() {
x := s[int]{a: 7}
f0 := x.g0
f0()
f1 := x.g1
is7(f1())
f2 := x.g2
is77(f2())
}
func genMethodValues[T comparable](want T) {
x := s[T]{a: want}
f0 := x.g0
f0()
f1 := x.g1
if got := f1(); got != want {
panic(fmt.Sprintf("f1() == %d, want %d", got, want))
}
f2 := x.g2
if got1, got2 := f2(); got1 != want || got2 != want {
panic(fmt.Sprintf("f2() == %d, %d, want %d, %d", got1, got2, want, want))
}
}
var x interface {
g0()
g1() int
g2() (int, int)
} = s[int]{a: 7}
var y interface{} = s[int]{a: 7}
func interfaceMethods() {
x.g0()
is7(x.g1())
is77(x.g2())
y.(interface{ g0() }).g0()
is7(y.(interface{ g1() int }).g1())
is77(y.(interface{ g2() (int, int) }).g2())
}
// Also check for instantiations outside functions.
var gg0 = g0[int]
var gg1 = g1[int]
var gg2 = g2[int]
var hh0 = s[int].g0
var hh1 = s[int].g1
var hh2 = s[int].g2
var xtop = s[int]{a: 7}
var ii0 = x.g0
var ii1 = x.g1
var ii2 = x.g2
func globals() {
gg0(7)
is7(gg1(7))
is77(gg2(7))
x := s[int]{a: 7}
hh0(x)
is7(hh1(x))
is77(hh2(x))
ii0()
is7(ii1())
is77(ii2())
}
func recursive() {
if got, want := recur1[int](5), 110; got != want {
panic(fmt.Sprintf("recur1[int](5) = %d, want = %d", got, want))
}
}
type Integer interface {
int | int32 | int64
}
func recur1[T Integer](n T) T {
if n == 0 || n == 1 {
return T(1)
} else {
return n * recur2(n-1)
}
}
func recur2[T Integer](n T) T {
list := make([]T, n)
for i, _ := range list {
list[i] = T(i + 1)
}
var sum T
for _, elt := range list {
sum += elt
}
return sum + recur1(n-1)
}

86
test/typeparam/dottype.go Normal file
View File

@@ -0,0 +1,86 @@
// run
// Copyright 2021 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.
package main
func f[T any](x interface{}) T {
return x.(T)
}
func f2[T any](x interface{}) (T, bool) {
t, ok := x.(T)
return t, ok
}
type I interface {
foo()
}
type myint int
func (myint) foo() {
}
type myfloat float64
func (myfloat) foo() {
}
func g[T I](x I) T {
return x.(T)
}
func g2[T I](x I) (T, bool) {
t, ok := x.(T)
return t, ok
}
func h[T any](x interface{}) struct{ a, b T } {
return x.(struct{ a, b T })
}
func k[T any](x interface{}) interface{ bar() T } {
return x.(interface{ bar() T })
}
type mybar int
func (x mybar) bar() int {
return int(x)
}
func main() {
var i interface{} = int(3)
var j I = myint(3)
var x interface{} = float64(3)
var y I = myfloat(3)
println(f[int](i))
shouldpanic(func() { f[int](x) })
println(f2[int](i))
println(f2[int](x))
println(g[myint](j))
shouldpanic(func() { g[myint](y) })
println(g2[myint](j))
println(g2[myint](y))
println(h[int](struct{ a, b int }{3, 5}).a)
println(k[int](mybar(3)).bar())
type large struct {a,b,c,d,e,f int}
println(f[large](large{}).a)
l2, ok := f2[large](large{})
println(l2.a, ok)
}
func shouldpanic(x func()) {
defer func() {
e := recover()
if e == nil {
panic("didn't panic")
}
}()
x()
}

View File

@@ -0,0 +1,10 @@
3
3 true
0 false
3
3 true
0 false
3
3
0
0 true

72
test/typeparam/double.go Normal file
View File

@@ -0,0 +1,72 @@
// run
// Copyright 2021 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.
package main
import (
"fmt"
"reflect"
)
type Number interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr | ~float32 | ~float64
}
type MySlice []int
type MyFloatSlice []float64
type _SliceOf[E any] interface {
~[]E
}
func _DoubleElems[S _SliceOf[E], E Number](s S) S {
r := make(S, len(s))
for i, v := range s {
r[i] = v + v
}
return r
}
// Test use of untyped constant in an expression with a generically-typed parameter
func _DoubleElems2[S _SliceOf[E], E Number](s S) S {
r := make(S, len(s))
for i, v := range s {
r[i] = v * 2
}
return r
}
func main() {
arg := MySlice{1, 2, 3}
want := MySlice{2, 4, 6}
got := _DoubleElems[MySlice, int](arg)
if !reflect.DeepEqual(got, want) {
panic(fmt.Sprintf("got %s, want %s", got, want))
}
// constraint type inference
got = _DoubleElems[MySlice](arg)
if !reflect.DeepEqual(got, want) {
panic(fmt.Sprintf("got %s, want %s", got, want))
}
got = _DoubleElems(arg)
if !reflect.DeepEqual(got, want) {
panic(fmt.Sprintf("got %s, want %s", got, want))
}
farg := MyFloatSlice{1.2, 2.0, 3.5}
fwant := MyFloatSlice{2.4, 4.0, 7.0}
fgot := _DoubleElems(farg)
if !reflect.DeepEqual(fgot, fwant) {
panic(fmt.Sprintf("got %s, want %s", fgot, fwant))
}
fgot = _DoubleElems2(farg)
if !reflect.DeepEqual(fgot, fwant) {
panic(fmt.Sprintf("got %s, want %s", fgot, fwant))
}
}

67
test/typeparam/eface.go Normal file
View File

@@ -0,0 +1,67 @@
// run
// Copyright 2021 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.
// Make sure we handle instantiated empty interfaces.
package main
type E[T any] interface {
}
//go:noinline
func f[T any](x E[T]) interface{} {
return x
}
//go:noinline
func g[T any](x interface{}) E[T] {
return x
}
type I[T any] interface {
foo()
}
type myint int
func (x myint) foo() {}
//go:noinline
func h[T any](x I[T]) interface{ foo() } {
return x
}
//go:noinline
func i[T any](x interface{ foo() }) I[T] {
return x
}
func main() {
if f[int](1) != 1 {
println("test 1 failed")
}
if f[int](2) != (interface{})(2) {
println("test 2 failed")
}
if g[int](3) != 3 {
println("test 3 failed")
}
if g[int](4) != (E[int])(4) {
println("test 4 failed")
}
if h[int](myint(5)) != myint(5) {
println("test 5 failed")
}
if h[int](myint(6)) != interface{ foo() }(myint(6)) {
println("test 6 failed")
}
if i[int](myint(7)) != myint(7) {
println("test 7 failed")
}
if i[int](myint(8)) != I[int](myint(8)) {
println("test 8 failed")
}
}

69
test/typeparam/equal.go Normal file
View File

@@ -0,0 +1,69 @@
// run
// Copyright 2021 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.
// comparisons of type parameters to interfaces
package main
func f[T comparable](t, u T) bool {
// Comparing two type parameters directly.
// (Not really testing comparisons to interfaces, but just 'cause we're here.)
return t == u
}
func g[T comparable](t T, i interface{}) bool {
// Compare type parameter value to empty interface.
return t == i
}
type I interface {
foo()
}
type C interface {
comparable
I
}
func h[T C](t T, i I) bool {
// Compare type parameter value to nonempty interface.
return t == i
}
type myint int
func (x myint) foo() {
}
func k[T comparable](t T, i interface{}) bool {
// Compare derived type value to interface.
return struct{ a, b T }{t, t} == i
}
func main() {
assert(f(3, 3))
assert(!f(3, 5))
assert(g(3, 3))
assert(!g(3, 5))
assert(h(myint(3), myint(3)))
assert(!h(myint(3), myint(5)))
type S struct{ a, b float64 }
assert(f(S{3, 5}, S{3, 5}))
assert(!f(S{3, 5}, S{4, 6}))
assert(g(S{3, 5}, S{3, 5}))
assert(!g(S{3, 5}, S{4, 6}))
assert(k(3, struct{ a, b int }{3, 3}))
assert(!k(3, struct{ a, b int }{3, 4}))
}
func assert(b bool) {
if !b {
panic("assertion failed")
}
}

32
test/typeparam/fact.go Normal file
View File

@@ -0,0 +1,32 @@
// run
// Copyright 2021 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.
package main
import "fmt"
func fact[T interface{ ~int | ~int64 | ~float64 }](n T) T {
if n == 1 {
return 1
}
return n * fact(n-1)
}
func main() {
const want = 120
if got := fact(5); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
if got := fact[int64](5); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
if got := fact(5.0); got != want {
panic(fmt.Sprintf("got %f, want %f", got, want))
}
}

View File

@@ -0,0 +1,12 @@
// Copyright 2021 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.
package a
func Fact[T interface{ int | int64 | float64 }](n T) T {
if n == 1 {
return 1
}
return n * Fact(n-1)
}

View File

@@ -0,0 +1,26 @@
// Copyright 2021 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.
package main
import (
"./a"
"fmt"
)
func main() {
const want = 120
if got := a.Fact(5); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
if got := a.Fact[int64](5); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
if got := a.Fact(5.0); got != want {
panic(fmt.Sprintf("got %f, want %f", got, want))
}
}

View File

@@ -0,0 +1,7 @@
// rundir
// Copyright 2021 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.
package ignored

View File

@@ -0,0 +1,27 @@
// Copyright 2021 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.
package a
var V val[int]
type val[T any] struct {
valx T
}
func (v *val[T]) Print() {
v.print1()
}
func (v *val[T]) print1() {
println(v.valx)
}
func (v *val[T]) fnprint1() {
println(v.valx)
}
func FnPrint[T any](v *val[T]) {
v.fnprint1()
}

View File

@@ -0,0 +1,12 @@
// Copyright 2021 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.
package main
import "./a"
func main() {
a.V.Print()
a.FnPrint(&a.V)
}

View File

@@ -0,0 +1,10 @@
// rundir
// Copyright 2021 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.
// Testing that all methods of a private generic type are exported, if a variable
// with that type is exported.
package ignored

View File

@@ -0,0 +1,2 @@
0
0

View File

@@ -0,0 +1,52 @@
// run
// Copyright 2021 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.
// Test wrappers/interfaces for generic type embedding another generic type.
package main
import "fmt"
type A[T any] struct {
B[T]
}
type B[T any] struct {
val T
}
func (b *B[T]) get() T {
return b.val
}
type getter[T any] interface {
get() T
}
//go:noinline
func doGet[T any](i getter[T]) T {
return i.get()
}
//go:noline
func doGet2[T any](i interface{}) T {
i2 := i.(getter[T])
return i2.get()
}
func main() {
a := A[int]{B: B[int]{3}}
var i getter[int] = &a
if got, want := doGet(i), 3; got != want {
panic(fmt.Sprintf("got %v, want %v", got, want))
}
as := A[string]{B: B[string]{"abc"}}
if got, want := doGet2[string](&as), "abc"; got != want {
panic(fmt.Sprintf("got %v, want %v", got, want))
}
}

View File

@@ -0,0 +1,46 @@
// run
// Copyright 2021 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.
// Test for declaration and use of a parameterized embedded field.
package main
import (
"fmt"
"sync"
)
type MyStruct[T any] struct {
val T
}
type Lockable[T any] struct {
MyStruct[T]
mu sync.Mutex
}
// Get returns the value stored in a Lockable.
func (l *Lockable[T]) Get() T {
l.mu.Lock()
defer l.mu.Unlock()
return l.MyStruct.val
}
// Set sets the value in a Lockable.
func (l *Lockable[T]) Set(v T) {
l.mu.Lock()
defer l.mu.Unlock()
l.MyStruct = MyStruct[T]{v}
}
func main() {
var li Lockable[int]
li.Set(5)
if got, want := li.Get(), 5; got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
}

View File

@@ -0,0 +1,56 @@
// Copyright 2021 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.
package a
type IVal[T comparable] interface {
check(want T)
}
type Val[T comparable] struct {
val T
}
//go:noinline
func (l *Val[T]) check(want T) {
if l.val != want {
panic("hi")
}
}
func Test1() {
var l Val[int]
if l.val != 0 {
panic("hi")
}
_ = IVal[int](&l)
}
func Test2() {
var l Val[float64]
l.val = 3.0
l.check(float64(3))
_ = IVal[float64](&l)
}
type privateVal[T comparable] struct {
val T
}
//go:noinline
func (l *privateVal[T]) check(want T) {
if l.val != want {
panic("hi")
}
}
type Outer struct {
val privateVal[string]
}
func Test3() {
var o Outer
o.val.check("")
_ = IVal[string](&o.val)
}

View File

@@ -0,0 +1,16 @@
// Copyright 2021 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.
package main
import "./a"
// Testing inlining of functions that refer to instantiated exported and non-exported
// generic types.
func main() {
a.Test1()
a.Test2()
a.Test3()
}

View File

@@ -0,0 +1,7 @@
// rundir
// Copyright 2021 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.
package ignored

231
test/typeparam/graph.go Normal file
View File

@@ -0,0 +1,231 @@
// run
// Copyright 2021 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.
package main
import (
"errors"
"fmt"
)
// _SliceEqual reports whether two slices are equal: the same length and all
// elements equal. All floating point NaNs are considered equal.
func _SliceEqual[Elem comparable](s1, s2 []Elem) bool {
if len(s1) != len(s2) {
return false
}
for i, v1 := range s1 {
v2 := s2[i]
if v1 != v2 {
isNaN := func(f Elem) bool { return f != f }
if !isNaN(v1) || !isNaN(v2) {
return false
}
}
}
return true
}
// A Graph is a collection of nodes. A node may have an arbitrary number
// of edges. An edge connects two nodes. Both nodes and edges must be
// comparable. This is an undirected simple graph.
type _Graph[_Node _NodeC[_Edge], _Edge _EdgeC[_Node]] struct {
nodes []_Node
}
// _NodeC is the constraints on a node in a graph, given the _Edge type.
type _NodeC[_Edge any] interface {
comparable
Edges() []_Edge
}
// _EdgeC is the constraints on an edge in a graph, given the _Node type.
type _EdgeC[_Node any] interface {
comparable
Nodes() (a, b _Node)
}
// _New creates a new _Graph from a collection of Nodes.
func _New[_Node _NodeC[_Edge], _Edge _EdgeC[_Node]](nodes []_Node) *_Graph[_Node, _Edge] {
return &_Graph[_Node, _Edge]{nodes: nodes}
}
// nodePath holds the path to a node during ShortestPath.
// This should ideally be a type defined inside ShortestPath,
// but the translator tool doesn't support that.
type nodePath[_Node _NodeC[_Edge], _Edge _EdgeC[_Node]] struct {
node _Node
path []_Edge
}
// ShortestPath returns the shortest path between two nodes,
// as an ordered list of edges. If there are multiple shortest paths,
// which one is returned is unpredictable.
func (g *_Graph[_Node, _Edge]) ShortestPath(from, to _Node) ([]_Edge, error) {
visited := make(map[_Node]bool)
visited[from] = true
workqueue := []nodePath[_Node, _Edge]{nodePath[_Node, _Edge]{from, nil}}
for len(workqueue) > 0 {
current := workqueue
workqueue = nil
for _, np := range current {
edges := np.node.Edges()
for _, edge := range edges {
a, b := edge.Nodes()
if a == np.node {
a = b
}
if !visited[a] {
ve := append([]_Edge(nil), np.path...)
ve = append(ve, edge)
if a == to {
return ve, nil
}
workqueue = append(workqueue, nodePath[_Node, _Edge]{a, ve})
visited[a] = true
}
}
}
}
return nil, errors.New("no path")
}
type direction int
const (
north direction = iota
ne
east
se
south
sw
west
nw
up
down
)
func (dir direction) String() string {
strs := map[direction]string{
north: "north",
ne: "ne",
east: "east",
se: "se",
south: "south",
sw: "sw",
west: "west",
nw: "nw",
up: "up",
down: "down",
}
if str, ok := strs[dir]; ok {
return str
}
return fmt.Sprintf("direction %d", dir)
}
type mazeRoom struct {
index int
exits [10]int
}
type mazeEdge struct {
from, to int
dir direction
}
// Edges returns the exits from the room.
func (m mazeRoom) Edges() []mazeEdge {
var r []mazeEdge
for i, exit := range m.exits {
if exit != 0 {
r = append(r, mazeEdge{
from: m.index,
to: exit,
dir: direction(i),
})
}
}
return r
}
// Nodes returns the rooms connected by an edge.
//
//go:noinline
func (e mazeEdge) Nodes() (mazeRoom, mazeRoom) {
m1, ok := zork[e.from]
if !ok {
panic("bad edge")
}
m2, ok := zork[e.to]
if !ok {
panic("bad edge")
}
return m1, m2
}
// The first maze in Zork. Room indexes based on original Fortran data file.
// You are in a maze of twisty little passages, all alike.
var zork = map[int]mazeRoom{
11: {exits: [10]int{north: 11, south: 12, east: 14}}, // west to Troll Room
12: {exits: [10]int{south: 11, north: 14, east: 13}},
13: {exits: [10]int{west: 12, north: 14, up: 16}},
14: {exits: [10]int{west: 13, north: 11, east: 15}},
15: {exits: [10]int{south: 14}}, // Dead End
16: {exits: [10]int{east: 17, north: 13, sw: 18}}, // skeleton, etc.
17: {exits: [10]int{west: 16}}, // Dead End
18: {exits: [10]int{down: 16, east: 19, west: 18, up: 22}},
19: {exits: [10]int{up: 29, west: 18, ne: 15, east: 20, south: 30}},
20: {exits: [10]int{ne: 19, west: 20, se: 21}},
21: {exits: [10]int{north: 20}}, // Dead End
22: {exits: [10]int{north: 18, east: 24, down: 23, south: 28, west: 26, nw: 22}},
23: {exits: [10]int{east: 22, west: 28, up: 24}},
24: {exits: [10]int{ne: 25, down: 23, nw: 28, sw: 26}},
25: {exits: [10]int{sw: 24}}, // Grating room (up to Clearing)
26: {exits: [10]int{west: 16, sw: 24, east: 28, up: 22, north: 27}},
27: {exits: [10]int{south: 26}}, // Dead End
28: {exits: [10]int{east: 22, down: 26, south: 23, west: 24}},
29: {exits: [10]int{west: 30, nw: 29, ne: 19, south: 19}},
30: {exits: [10]int{west: 29, south: 19}}, // ne to Cyclops Room
}
func TestShortestPath() {
// The Zork maze is not a proper undirected simple graph,
// as there are some one way paths (e.g., 19 -> 15),
// but for this test that doesn't matter.
// Set the index field in the map. Simpler than doing it in the
// composite literal.
for k := range zork {
r := zork[k]
r.index = k
zork[k] = r
}
var nodes []mazeRoom
for idx, room := range zork {
mridx := room
mridx.index = idx
nodes = append(nodes, mridx)
}
g := _New[mazeRoom, mazeEdge](nodes)
path, err := g.ShortestPath(zork[11], zork[30])
if err != nil {
panic(fmt.Sprintf("%v", err))
}
var steps []direction
for _, edge := range path {
steps = append(steps, edge.dir)
}
want := []direction{east, west, up, sw, east, south}
if !_SliceEqual(steps, want) {
panic(fmt.Sprintf("ShortestPath returned %v, want %v", steps, want))
}
}
func main() {
TestShortestPath()
}

View File

@@ -0,0 +1,83 @@
// run
// Copyright 2021 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.
// Test that we can convert type parameters to both empty
// and nonempty interfaces, and named and nonnamed versions
// thereof.
package main
import "fmt"
type E interface{}
func f[T any](x T) interface{} {
var i interface{} = x
return i
}
func fs[T any](x T) interface{} {
y := []T{x}
var i interface{} = y
return i
}
func g[T any](x T) E {
var i E = x
return i
}
type C interface {
foo() int
}
type myInt int
func (x myInt) foo() int {
return int(x + 1)
}
func h[T C](x T) interface{ foo() int } {
var i interface{ foo() int } = x
return i
}
func i[T C](x T) C {
var i C = x // conversion in assignment
return i
}
func j[T C](t T) C {
return C(t) // explicit conversion
}
func js[T any](x T) interface{} {
y := []T{x}
return interface{}(y)
}
func main() {
if got, want := f[int](7), 7; got != want {
panic(fmt.Sprintf("got %d want %d", got, want))
}
if got, want := fs[int](7), []int{7}; got.([]int)[0] != want[0] {
panic(fmt.Sprintf("got %d want %d", got, want))
}
if got, want := g[int](7), 7; got != want {
panic(fmt.Sprintf("got %d want %d", got, want))
}
if got, want := h[myInt](7).foo(), 8; got != want {
panic(fmt.Sprintf("got %d want %d", got, want))
}
if got, want := i[myInt](7).foo(), 8; got != want {
panic(fmt.Sprintf("got %d want %d", got, want))
}
if got, want := j[myInt](7).foo(), 8; got != want {
panic(fmt.Sprintf("got %d want %d", got, want))
}
if got, want := js[int](7), []int{7}; got.([]int)[0] != want[0] {
panic(fmt.Sprintf("got %d want %d", got, want))
}
}

View File

@@ -0,0 +1,16 @@
// compile
// Copyright 2020 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.
// This file checks that basic importing works in -G mode.
package p
import "fmt"
import "math"
func f(x float64) {
fmt.Println(math.Sin(x))
}

81
test/typeparam/index.go Normal file
View File

@@ -0,0 +1,81 @@
// run
// Copyright 2021 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.
package main
import (
"fmt"
)
// Index returns the index of x in s, or -1 if not found.
func Index[T comparable](s []T, x T) int {
for i, v := range s {
// v and x are type T, which has the comparable
// constraint, so we can use == here.
if v == x {
return i
}
}
return -1
}
type obj struct {
x int
}
type obj2 struct {
x int8
y float64
}
type obj3 struct {
x int64
y int8
}
type inner struct {
y int64
z int32
}
type obj4 struct {
x int32
s inner
}
func main() {
want := 2
vec1 := []string{"ab", "cd", "ef"}
if got := Index(vec1, "ef"); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
vec2 := []byte{'c', '6', '@'}
if got := Index(vec2, '@'); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
vec3 := []*obj{&obj{2}, &obj{42}, &obj{1}}
if got := Index(vec3, vec3[2]); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
vec4 := []obj2{obj2{2, 3.0}, obj2{3, 4.0}, obj2{4, 5.0}}
if got := Index(vec4, vec4[2]); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
vec5 := []obj3{obj3{2, 3}, obj3{3, 4}, obj3{4, 5}}
if got := Index(vec5, vec5[2]); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
vec6 := []obj4{obj4{2, inner{3, 4}}, obj4{3, inner{4, 5}}, obj4{4, inner{5, 6}}}
if got := Index(vec6, vec6[2]); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
}

67
test/typeparam/index2.go Normal file
View File

@@ -0,0 +1,67 @@
// run
// Copyright 2021 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.
// Testing various generic uses of indexing, both for reads and writes.
package main
import "fmt"
// Can index an argument (read/write) constrained to be a slice or an array.
func Index1[T interface{ []int64 | [5]int64 }](x T) int64 {
x[2] = 5
return x[3]
}
// Can index an argument (read) constrained to be a byte array or a string.
func Index2[T interface{ []byte | string }](x T) byte {
return x[3]
}
// Can index an argument (write) constrained to be a byte array, but not a string.
func Index2a[T interface{ []byte }](x T) byte {
x[2] = 'b'
return x[3]
}
// Can index an argument (read/write) constrained to be a map. Maps can't
// be combined with any other type for indexing purposes.
func Index3[T interface{ map[int]int64 }](x T) int64 {
x[2] = 43
return x[3]
}
// But the type of the map keys or values can be parameterized.
func Index4[T any](x map[int]T) T {
var zero T
x[2] = zero
return x[3]
}
func test[T comparable](got, want T) {
if got != want {
panic(fmt.Sprintf("got %v, want %v", got, want))
}
}
func main() {
x := make([]int64, 4)
x[3] = 2
y := [5]int64{1, 2, 3, 4, 5}
z := "abcd"
w := make([]byte, 4)
w[3] = 5
v := make(map[int]int64)
v[3] = 18
test(Index1(x), int64(2))
test(Index1(y), int64(4))
test(Index2(z), byte(100))
test(Index2(w), byte(5))
test(Index2a(w), byte(5))
test(Index3(v), int64(18))
test(Index4(v), int64(18))
}

View File

@@ -0,0 +1,46 @@
// run
// Copyright 2021 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.
package main
type I interface{}
type _S[T any] struct {
x *T
}
// F is a non-generic function, but has a type _S[I] which is instantiated from a
// generic type. Test that _S[I] is successfully exported.
func F() {
v := _S[I]{}
if v.x != nil {
panic(v)
}
}
// Testing the various combinations of method expressions.
type S1 struct{}
func (*S1) M() {}
type S2 struct{}
func (S2) M() {}
func _F1[T interface{ M() }](t T) {
_ = T.M
}
func F2() {
_F1(&S1{})
_F1(S2{})
_F1(&S2{})
}
func main() {
F()
F2()
}

View File

@@ -0,0 +1,32 @@
// run
// Copyright 2022 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.
// Test case where a slice of a user-defined byte type (not uint8 or byte) is
// converted to a string. Same for slice of runes.
package main
type MyByte byte
type MyRune rune
func f[T []MyByte](x T) string {
return string(x)
}
func g[T []MyRune](x T) string {
return string(x)
}
func main() {
var y []MyByte
_ = f(y)
_ = string(y)
var z []MyRune
_ = g(z)
_ = string(z)
}

View File

@@ -0,0 +1,20 @@
// run
// Copyright 2022 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.
package main
func add[S ~string | ~[]byte](buf *[]byte, s S) {
*buf = append(*buf, s...)
}
func main() {
var buf []byte
add(&buf, "foo")
add(&buf, []byte("bar"))
if string(buf) != "foobar" {
panic("got " + string(buf))
}
}

View File

@@ -0,0 +1,27 @@
// compile
// Copyright 2020 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.
// copied from cmd/compile/internal/types2/testdata/fixedbugs/issue39755.go
package p
func _[T interface{ ~map[string]int }](x T) {
_ = x == nil
}
// simplified test case from issue
type PathParamsConstraint interface {
~map[string]string | ~[]struct{ key, value string }
}
type PathParams[T PathParamsConstraint] struct {
t T
}
func (pp *PathParams[T]) IsNil() bool {
return pp.t == nil // this must succeed
}

View File

@@ -0,0 +1,19 @@
// run
// Copyright 2022 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.
package main
func F[T, U int]() interface{} {
switch interface{}(nil) {
case int(0), T(0), U(0):
}
return map[interface{}]int{int(0): 0, T(0): 0, U(0): 0}
}
func main() {
F[int, int]()
}

View File

@@ -0,0 +1,149 @@
// run
// Copyright 2021 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.
// derived & expanded from cmd/compile/internal/types2/testdata/fixedbugs/issue44688.go2
package main
type A1[T any] struct {
val T
}
func (p *A1[T]) m1(val T) {
p.val = val
}
type A2[T any] interface {
m2(T)
}
type B1[T any] struct {
filler int
*A1[T]
A2[T]
}
type B2[T any] interface {
A2[T]
}
type ImpA2[T any] struct {
f T
}
func (a2 *ImpA2[T]) m2(s T) {
a2.f = s
}
type C[T any] struct {
filler1 int
filler2 int
B1[T]
}
type D[T any] struct {
filler1 int
filler2 int
filler3 int
C[T]
}
func test1[T any](arg T) {
// calling embedded methods
var b1 B1[T]
b1.A1 = &A1[T]{}
b1.A2 = &ImpA2[T]{}
b1.A1.m1(arg)
b1.m1(arg)
b1.A2.m2(arg)
b1.m2(arg)
var b2 B2[T]
b2 = &ImpA2[T]{}
b2.m2(arg)
// a deeper nesting
var d D[T]
d.C.B1.A1 = &A1[T]{}
d.C.B1.A2 = &ImpA2[T]{}
d.m1(arg)
d.m2(arg)
// calling method expressions
m1x := B1[T].m1
m1x(b1, arg)
// TODO(khr): reenable these.
//m2x := B2[T].m2
//m2x(b2, arg)
// calling method values
m1v := b1.m1
m1v(arg)
m2v := b1.m2
m2v(arg)
b2v := b2.m2
b2v(arg)
}
func test2() {
// calling embedded methods
var b1 B1[string]
b1.A1 = &A1[string]{}
b1.A2 = &ImpA2[string]{}
b1.A1.m1("")
b1.m1("")
b1.A2.m2("")
b1.m2("")
var b2 B2[string]
b2 = &ImpA2[string]{}
b2.m2("")
// a deeper nesting
var d D[string]
d.C.B1.A1 = &A1[string]{}
d.C.B1.A2 = &ImpA2[string]{}
d.m1("")
d.m2("")
// calling method expressions
m1x := B1[string].m1
m1x(b1, "")
m2x := B2[string].m2
m2x(b2, "")
// calling method values
m1v := b1.m1
m1v("")
m2v := b1.m2
m2v("")
b2v := b2.m2
b2v("")
}
// actual test case from issue
type A[T any] struct{}
func (*A[T]) f(T) {}
type B[T any] struct{ A[T] }
func test3() {
var b B[string]
b.A.f("")
b.f("")
}
func main() {
test1[string]("")
test2()
test3()
}

View File

@@ -0,0 +1,20 @@
// compile
// Copyright 2021 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.
package p
func f[T any]() (f, g T) { return f, g }
// Tests for generic function instantiation on the right hande side of multi-value
// assignments.
func g() {
// Multi-value assignment within a function
var _, _ = f[int]()
}
// Multi-value assignment outside a function.
var _, _ = f[int]()

View File

@@ -0,0 +1,34 @@
// run
// Copyright 2021 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.
package main
import (
"fmt"
"log"
)
func try[T any](v T, err error) T {
if err != nil {
panic(err)
}
return v
}
func handle(handle func(error)) {
if issue := recover(); issue != nil {
if e, ok := issue.(error); ok && e != nil {
handle(e)
} else {
handle(fmt.Errorf("%v", e))
}
}
}
func main() {
defer handle(func(e error) { log.Fatalln(e) })
_ = try(fmt.Print(""))
}

View File

@@ -0,0 +1,18 @@
// compile
// Copyright 2021 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.
package main
//go:noinline
func f[T any]() {
x := 5
g := func() int { return x }
g()
}
func main() {
f[int]()
}

View File

@@ -0,0 +1,26 @@
// run
// Copyright 2021 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.
package main
import (
"fmt"
)
type s[T any] struct {
a T
}
func (x s[T]) f() T {
return x.a
}
func main() {
x := s[int]{a: 7}
f := x.f
if got, want := f(), 7; got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
}

View File

@@ -0,0 +1,13 @@
// errorcheck
// Copyright 2021 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.
package p
type T[U interface{ M() T[U] }] int // ERROR "invalid recursive type: T refers to itself"
type X int
func (X) M() T[X] { return 0 }

View File

@@ -0,0 +1,7 @@
// Copyright 2021 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.
package a
type T[U interface{ M() int }] int

View File

@@ -0,0 +1,13 @@
// Copyright 2021 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.
package b
import "./a"
type X int
func (X) M() int { return 0 }
type _ a.T[X]

View File

@@ -0,0 +1,7 @@
// compiledir
// Copyright 2021 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.
package ignored

View File

@@ -0,0 +1,20 @@
// run
// Copyright 2021 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.
package main
func foo[T any](d T) {
switch v := interface{}(d).(type) {
case string:
if v != "x" {
panic("unexpected v: " + v)
}
}
}
func main() {
foo("x")
}

View File

@@ -0,0 +1,22 @@
// run
// Copyright 2021 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.
package main
type T[_ any] struct{}
var m = map[interface{}]int{
T[struct{ int }]{}: 0,
T[struct {
int "x"
}]{}: 0,
}
func main() {
if len(m) != 2 {
panic(len(m))
}
}

View File

@@ -0,0 +1,32 @@
// run
// Copyright 2021 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.
package main
import (
"fmt"
)
type Numeric interface {
int32 | int64 | float64 | complex64
}
//go:noline
func inc[T Numeric](x T) T {
x++
return x
}
func main() {
if got, want := inc(int32(5)), int32(6); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
if got, want := inc(float64(5)), float64(6.0); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
if got, want := inc(complex64(5)), complex64(6.0); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
}

View File

@@ -0,0 +1,55 @@
// run
// Copyright 2021 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.
package main
import (
"errors"
"fmt"
)
type Option[T any] struct {
ok bool
val T
}
func (o Option[T]) String() string {
if o.ok {
return fmt.Sprintf("Some(%v)", o.val)
}
return "None"
}
func Some[T any](val T) Option[T] { return Option[T]{ok: true, val: val} }
func None[T any]() Option[T] { return Option[T]{ok: false} }
type Result[T, E any] struct {
ok bool
val T
err E
}
func (r Result[T, E]) String() string {
if r.ok {
return fmt.Sprintf("Ok(%v)", r.val)
}
return fmt.Sprintf("Err(%v)", r.err)
}
func Ok[T, E any](val T) Result[T, E] { return Result[T, E]{ok: true, val: val} }
func Err[T, E any](err E) Result[T, E] { return Result[T, E]{ok: false, err: err} }
func main() {
a := Some[int](1)
b := None[int]()
fmt.Println(a, b)
x := Ok[int, error](1)
y := Err[int, error](errors.New("test"))
fmt.Println(x, y)
// fmt.Println(x)
_, _, _, _ = a, b, x, y
}

View File

@@ -0,0 +1,2 @@
Some(1) None
Ok(1) Err(test)

View File

@@ -0,0 +1,20 @@
// run
// Copyright 2021 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.
// Test that closures inside a generic function are not exported,
// even though not themselves generic.
package main
func Do[T any]() {
_ = func() string {
return ""
}
}
func main() {
Do[int]()
}

View File

@@ -0,0 +1,19 @@
// run
// Copyright 2021 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.
package main
func Do[T any](do func() (T, string)) {
_ = func() (T, string) {
return do()
}
}
func main() {
Do[int](func() (int, string) {
return 3, "3"
})
}

View File

@@ -0,0 +1,5 @@
package a
type Doer[T any] interface {
Do() T
}

View File

@@ -0,0 +1,10 @@
package main
import "./a"
func Do[T any](doer a.Doer[T]) {
doer.Do()
}
func main() {
}

View File

@@ -0,0 +1,7 @@
// rundir
// Copyright 2021 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.
package ignored

View File

@@ -0,0 +1,31 @@
// compile
// Copyright 2021 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.
package p
func g[T any]() {
type U []T
type V []int
}
type S[T any] struct {
}
func (s S[T]) m() {
type U []T
type V []int
}
func f() {
type U []int
}
type X struct {
}
func (x X) m() {
type U []int
}

View File

@@ -0,0 +1,23 @@
// run
// Copyright 2021 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.
package main
func main() {
d := diff([]int{}, func(int) string {
return "foo"
})
d()
}
func diff[T any](previous []T, uniqueKey func(T) string) func() {
return func() {
newJSON := map[string]T{}
for _, prev := range previous {
delete(newJSON, uniqueKey(prev))
}
}
}

View File

@@ -0,0 +1,19 @@
// run
// Copyright 2021 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.
package main
func f[G any]() int {
return func() int {
return func() int {
return 0
}()
}()
}
func main() {
f[int]()
}

View File

@@ -0,0 +1,23 @@
// run
// Copyright 2021 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.
package main
func f[G any]() interface{} {
return func() interface{} {
return func() interface{} {
var x G
return x
}()
}()
}
func main() {
x := f[int]()
if v, ok := x.(int); !ok || v != 0 {
panic("bad")
}
}

View File

@@ -0,0 +1,19 @@
// run
// Copyright 2021 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.
package main
func f[G any]() func()func()int {
return func() func()int {
return func() int {
return 0
}
}
}
func main() {
f[int]()()()
}

View File

@@ -0,0 +1,37 @@
// run
// Copyright 2021 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.
package main
type FooType[T any] interface {
Foo(BarType[T]) string
}
type BarType[T any] interface {
Bar(FooType[T]) string
}
// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639).
// type Baz[T any] T
// func (l Baz[T]) Foo(v BarType[T]) string {
// return v.Bar(l)
// }
// type Bob[T any] T
// func (l Bob[T]) Bar(v FooType[T]) string {
// if v,ok := v.(Baz[T]);ok{
// return fmt.Sprintf("%v%v",v,l)
// }
// return ""
// }
func main() {
// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639).
// var baz Baz[int] = 123
// var bob Bob[int] = 456
//
// if got, want := baz.Foo(bob), "123456"; got != want {
// panic(fmt.Sprintf("got %s want %s", got, want))
// }
}

View File

@@ -0,0 +1,19 @@
// compile
// Copyright 2021 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.
package p
type FooType[t any] interface {
Foo(BarType[t])
}
type BarType[t any] interface {
Int(IntType[t]) FooType[int]
}
type IntType[t any] int
func (n IntType[t]) Foo(BarType[t]) {}
func (n IntType[_]) String() {}

View File

@@ -0,0 +1,52 @@
// run
// Copyright 2021 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.
package main
import (
"encoding"
"fmt"
)
type Seralizable interface {
encoding.BinaryMarshaler
encoding.BinaryUnmarshaler
}
type SerDeString string
func (s *SerDeString) UnmarshalBinary(in []byte) error {
*s = SerDeString(in)
return nil
}
func (s SerDeString) MarshalBinary() ([]byte, error) {
return []byte(s), nil
}
type GenericSerializable[T Seralizable] struct {
Key string
Value T
}
func (g GenericSerializable[T]) Send() {
out, err := g.Value.MarshalBinary()
if err != nil {
panic("bad")
}
var newval SerDeString
newval.UnmarshalBinary(out)
fmt.Printf("Sent %s\n", newval)
}
func main() {
val := SerDeString("asdf")
x := GenericSerializable[*SerDeString]{
Value: &val,
}
x.Send()
}

View File

@@ -0,0 +1 @@
Sent asdf

View File

@@ -0,0 +1,68 @@
// run
// Copyright 2021 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.
package main
import (
"fmt"
"unsafe"
)
// size returns the size of type T
func size[T any](x T) uintptr {
return unsafe.Sizeof(x)
}
// size returns the alignment of type T
func align[T any](x T) uintptr {
return unsafe.Alignof(x)
}
type Tstruct[T any] struct {
f1 T
f2 int
}
// offset returns the offset of field f2 in the generic type Tstruct
func (r *Tstruct[T]) offset() uintptr {
return unsafe.Offsetof(r.f2)
}
func main() {
v1 := int(5)
if got, want := size(v1), unsafe.Sizeof(v1); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
if got, want := align(v1), unsafe.Alignof(v1); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
v2 := "abc"
if got, want := size(v2), unsafe.Sizeof(v2); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
if got, want := align(v2), unsafe.Alignof(v2); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
var v3 Tstruct[int]
if got, want := unsafe.Offsetof(v3.f2), unsafe.Sizeof(v1); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
var v4 Tstruct[interface{}]
var v5 interface{}
if got, want := unsafe.Offsetof(v4.f2), unsafe.Sizeof(v5); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
if got, want := v3.offset(), unsafe.Offsetof(v3.f2); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
if got, want := v4.offset(), unsafe.Offsetof(v4.f2); got != want {
panic(fmt.Sprintf("got %d, want %d", got, want))
}
}

View File

@@ -0,0 +1,23 @@
// run
// Copyright 2021 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.
package main
func f[_ any]() int {
var a [1]int
_ = func() int {
return func() int {
return 0
}()
}()
return a[func() int {
return 0
}()]
}
func main() {
f[int]()
}

View File

@@ -0,0 +1,40 @@
// run
// Copyright 2021 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.
package main
import "fmt"
type Exp[Ty any] interface {
Eval() Ty
}
// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639).
// type Lit[Ty any] Ty
//
// func (lit Lit[Ty]) Eval() Ty { return Ty(lit) }
// func (lit Lit[Ty]) String() string { return fmt.Sprintf("(lit %v)", Ty(lit)) }
type Eq[Ty any] struct {
a Exp[Ty]
b Exp[Ty]
}
func (e Eq[Ty]) String() string {
return fmt.Sprintf("(eq %v %v)", e.a, e.b)
}
// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639).
// var (
// e0 = Eq[int]{Lit[int](128), Lit[int](64)}
// e1 = Eq[bool]{Lit[bool](true), Lit[bool](true)}
// )
func main() {
// For now, a lone type parameter is not permitted as RHS in a type declaration (issue #45639).
// fmt.Printf("%v\n", e0)
// fmt.Printf("%v\n", e1)
}

View File

View File

@@ -0,0 +1,23 @@
// run
// Copyright 2021 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.
package main
import "reflect"
type S[T any] struct {
a interface{}
}
func (e S[T]) M() {
v := reflect.ValueOf(e.a)
_, _ = v.Interface().(int)
}
func main() {
e := S[int]{0}
e.M()
}

View File

@@ -0,0 +1,19 @@
// Copyright 2021 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.
package b
type C[T any] struct {
}
func (c *C[T]) reset() {
}
func New[T any]() {
c := &C[T]{}
z(c.reset)
}
func z(interface{}) {
}

View File

@@ -0,0 +1,11 @@
// Copyright 2021 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.
package main
import "./b"
func main() {
b.New[int]()
}

View File

@@ -0,0 +1,7 @@
// rundir
// Copyright 2021 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.
package ignored

View File

@@ -0,0 +1,28 @@
// run
// Copyright 2021 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.
package main
type C[T any] struct {
}
func (c *C[T]) reset() {
}
func New[T any]() {
c := &C[T]{}
i = c.reset
z(c.reset)
}
var i interface{}
func z(interface{}) {
}
func main() {
New[int]()
}

View File

@@ -0,0 +1,22 @@
// compile
// Copyright 2021 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.
package p
type Foo[T any] struct {
Val T
}
func (f Foo[T]) Bat() {}
type Bar struct {
Foo[int]
}
func foo() {
var b Bar
b.Bat()
}

View File

@@ -0,0 +1,23 @@
// run
// Copyright 2021 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.
package main
type Map[K comparable, V any] struct {
m map[K]V
}
func NewMap[K comparable, V any]() Map[K, V] {
return Map[K, V]{m: map[K]V{}}
}
func (m Map[K, V]) Get(key K) V {
return m.m[key]
}
func main() {
_ = NewMap[int, struct{}]()
}

View File

@@ -0,0 +1,56 @@
// compile
// Copyright 2021 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.
package main
type Src1[T any] func() Src1[T]
func (s *Src1[T]) Next() {
*s = (*s)()
}
type Src2[T any] []func() Src2[T]
func (s Src2[T]) Next() {
_ = s[0]()
}
type Src3[T comparable] map[T]func() Src3[T]
func (s Src3[T]) Next() {
var a T
_ = s[a]()
}
type Src4[T any] chan func() T
func (s Src4[T]) Next() {
_ = (<-s)()
}
type Src5[T any] func() Src5[T]
func (s Src5[T]) Next() {
var x interface{} = s
_ = (x.(Src5[T]))()
}
func main() {
var src1 Src1[int]
src1.Next()
var src2 Src2[int]
src2.Next()
var src3 Src3[string]
src3.Next()
var src4 Src4[int]
src4.Next()
var src5 Src5[int]
src5.Next()
}

Some files were not shown because too many files have changed in this diff Show More