Initial commit: Go 1.23 release state
This commit is contained in:
94
test/typeparam/absdiff.go
Normal file
94
test/typeparam/absdiff.go
Normal 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
135
test/typeparam/absdiff2.go
Normal 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))
|
||||
}
|
||||
}
|
||||
98
test/typeparam/absdiff3.go
Normal file
98
test/typeparam/absdiff3.go
Normal 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))
|
||||
}
|
||||
}
|
||||
72
test/typeparam/absdiffimp.dir/a.go
Normal file
72
test/typeparam/absdiffimp.dir/a.go
Normal 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)))
|
||||
// }
|
||||
25
test/typeparam/absdiffimp.dir/main.go
Normal file
25
test/typeparam/absdiffimp.dir/main.go
Normal 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))
|
||||
// }
|
||||
}
|
||||
7
test/typeparam/absdiffimp.go
Normal file
7
test/typeparam/absdiffimp.go
Normal 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
|
||||
110
test/typeparam/absdiffimp2.dir/a.go
Normal file
110
test/typeparam/absdiffimp2.dir/a.go
Normal 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})
|
||||
}
|
||||
29
test/typeparam/absdiffimp2.dir/main.go
Normal file
29
test/typeparam/absdiffimp2.dir/main.go
Normal 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))
|
||||
}
|
||||
}
|
||||
7
test/typeparam/absdiffimp2.go
Normal file
7
test/typeparam/absdiffimp2.go
Normal 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
29
test/typeparam/adder.go
Normal 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))
|
||||
}
|
||||
}
|
||||
9
test/typeparam/aliasimp.dir/a.go
Normal file
9
test/typeparam/aliasimp.dir/a.go
Normal 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
|
||||
}
|
||||
41
test/typeparam/aliasimp.dir/main.go
Normal file
41
test/typeparam/aliasimp.dir/main.go
Normal 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)
|
||||
}
|
||||
}
|
||||
7
test/typeparam/aliasimp.go
Normal file
7
test/typeparam/aliasimp.go
Normal 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
31
test/typeparam/append.go
Normal 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)
|
||||
}
|
||||
}
|
||||
108
test/typeparam/boundmethod.go
Normal file
108
test/typeparam/boundmethod.go
Normal 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
112
test/typeparam/builtins.go
Normal 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
413
test/typeparam/chans.go
Normal 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()
|
||||
}
|
||||
232
test/typeparam/chansimp.dir/a.go
Normal file
232
test/typeparam/chansimp.dir/a.go
Normal 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)
|
||||
}
|
||||
189
test/typeparam/chansimp.dir/main.go
Normal file
189
test/typeparam/chansimp.dir/main.go
Normal 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()
|
||||
}
|
||||
7
test/typeparam/chansimp.go
Normal file
7
test/typeparam/chansimp.go
Normal 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
65
test/typeparam/combine.go
Normal 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
100
test/typeparam/cons.go
Normal 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))
|
||||
}
|
||||
}
|
||||
10
test/typeparam/dedup.dir/a.go
Normal file
10
test/typeparam/dedup.dir/a.go
Normal 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
|
||||
}
|
||||
14
test/typeparam/dedup.dir/b.go
Normal file
14
test/typeparam/dedup.dir/b.go
Normal 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))
|
||||
}
|
||||
14
test/typeparam/dedup.dir/c.go
Normal file
14
test/typeparam/dedup.dir/c.go
Normal 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))
|
||||
}
|
||||
15
test/typeparam/dedup.dir/main.go
Normal file
15
test/typeparam/dedup.dir/main.go
Normal 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
12
test/typeparam/dedup.go
Normal 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
4
test/typeparam/dedup.out
Normal file
@@ -0,0 +1,4 @@
|
||||
true
|
||||
true
|
||||
true
|
||||
true
|
||||
22
test/typeparam/devirtualize1.go
Normal file
22
test/typeparam/devirtualize1.go
Normal 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()
|
||||
}
|
||||
28
test/typeparam/devirtualize2.go
Normal file
28
test/typeparam/devirtualize2.go
Normal 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()
|
||||
}
|
||||
126
test/typeparam/dictionaryCapture-noinline.go
Normal file
126
test/typeparam/dictionaryCapture-noinline.go
Normal 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())
|
||||
}
|
||||
203
test/typeparam/dictionaryCapture.go
Normal file
203
test/typeparam/dictionaryCapture.go
Normal 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
86
test/typeparam/dottype.go
Normal 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()
|
||||
}
|
||||
10
test/typeparam/dottype.out
Normal file
10
test/typeparam/dottype.out
Normal 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
72
test/typeparam/double.go
Normal 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
67
test/typeparam/eface.go
Normal 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
69
test/typeparam/equal.go
Normal 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
32
test/typeparam/fact.go
Normal 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))
|
||||
}
|
||||
}
|
||||
12
test/typeparam/factimp.dir/a.go
Normal file
12
test/typeparam/factimp.dir/a.go
Normal 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)
|
||||
}
|
||||
26
test/typeparam/factimp.dir/main.go
Normal file
26
test/typeparam/factimp.dir/main.go
Normal 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))
|
||||
}
|
||||
}
|
||||
7
test/typeparam/factimp.go
Normal file
7
test/typeparam/factimp.go
Normal 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
|
||||
27
test/typeparam/gencrawler.dir/a.go
Normal file
27
test/typeparam/gencrawler.dir/a.go
Normal 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()
|
||||
}
|
||||
12
test/typeparam/gencrawler.dir/main.go
Normal file
12
test/typeparam/gencrawler.dir/main.go
Normal 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)
|
||||
}
|
||||
10
test/typeparam/gencrawler.go
Normal file
10
test/typeparam/gencrawler.go
Normal 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
|
||||
2
test/typeparam/gencrawler.out
Normal file
2
test/typeparam/gencrawler.out
Normal file
@@ -0,0 +1,2 @@
|
||||
0
|
||||
0
|
||||
52
test/typeparam/genembed.go
Normal file
52
test/typeparam/genembed.go
Normal 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))
|
||||
}
|
||||
}
|
||||
46
test/typeparam/genembed2.go
Normal file
46
test/typeparam/genembed2.go
Normal 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))
|
||||
}
|
||||
}
|
||||
56
test/typeparam/geninline.dir/a.go
Normal file
56
test/typeparam/geninline.dir/a.go
Normal 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)
|
||||
}
|
||||
16
test/typeparam/geninline.dir/main.go
Normal file
16
test/typeparam/geninline.dir/main.go
Normal 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()
|
||||
}
|
||||
7
test/typeparam/geninline.go
Normal file
7
test/typeparam/geninline.go
Normal 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
231
test/typeparam/graph.go
Normal 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()
|
||||
}
|
||||
83
test/typeparam/ifaceconv.go
Normal file
83
test/typeparam/ifaceconv.go
Normal 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))
|
||||
}
|
||||
}
|
||||
16
test/typeparam/importtest.go
Normal file
16
test/typeparam/importtest.go
Normal 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
81
test/typeparam/index.go
Normal 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
67
test/typeparam/index2.go
Normal 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))
|
||||
}
|
||||
46
test/typeparam/interfacearg.go
Normal file
46
test/typeparam/interfacearg.go
Normal 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()
|
||||
}
|
||||
32
test/typeparam/issue23536.go
Normal file
32
test/typeparam/issue23536.go
Normal 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)
|
||||
}
|
||||
20
test/typeparam/issue376214.go
Normal file
20
test/typeparam/issue376214.go
Normal 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))
|
||||
}
|
||||
}
|
||||
27
test/typeparam/issue39755.go
Normal file
27
test/typeparam/issue39755.go
Normal 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
|
||||
}
|
||||
19
test/typeparam/issue42758.go
Normal file
19
test/typeparam/issue42758.go
Normal 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]()
|
||||
}
|
||||
149
test/typeparam/issue44688.go
Normal file
149
test/typeparam/issue44688.go
Normal 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()
|
||||
}
|
||||
20
test/typeparam/issue45547.go
Normal file
20
test/typeparam/issue45547.go
Normal 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]()
|
||||
34
test/typeparam/issue45722.go
Normal file
34
test/typeparam/issue45722.go
Normal 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(""))
|
||||
}
|
||||
18
test/typeparam/issue45738.go
Normal file
18
test/typeparam/issue45738.go
Normal 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]()
|
||||
}
|
||||
26
test/typeparam/issue45817.go
Normal file
26
test/typeparam/issue45817.go
Normal 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))
|
||||
}
|
||||
}
|
||||
13
test/typeparam/issue46461.go
Normal file
13
test/typeparam/issue46461.go
Normal 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 }
|
||||
7
test/typeparam/issue46461b.dir/a.go
Normal file
7
test/typeparam/issue46461b.dir/a.go
Normal 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
|
||||
13
test/typeparam/issue46461b.dir/b.go
Normal file
13
test/typeparam/issue46461b.dir/b.go
Normal 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]
|
||||
7
test/typeparam/issue46461b.go
Normal file
7
test/typeparam/issue46461b.go
Normal 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
|
||||
20
test/typeparam/issue46472.go
Normal file
20
test/typeparam/issue46472.go
Normal 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")
|
||||
}
|
||||
22
test/typeparam/issue46591.go
Normal file
22
test/typeparam/issue46591.go
Normal 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))
|
||||
}
|
||||
}
|
||||
32
test/typeparam/issue47258.go
Normal file
32
test/typeparam/issue47258.go
Normal 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))
|
||||
}
|
||||
}
|
||||
55
test/typeparam/issue47272.go
Normal file
55
test/typeparam/issue47272.go
Normal 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
|
||||
}
|
||||
2
test/typeparam/issue47272.out
Normal file
2
test/typeparam/issue47272.out
Normal file
@@ -0,0 +1,2 @@
|
||||
Some(1) None
|
||||
Ok(1) Err(test)
|
||||
20
test/typeparam/issue47514.go
Normal file
20
test/typeparam/issue47514.go
Normal 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]()
|
||||
}
|
||||
19
test/typeparam/issue47514b.go
Normal file
19
test/typeparam/issue47514b.go
Normal 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"
|
||||
})
|
||||
}
|
||||
5
test/typeparam/issue47514c.dir/a.go
Normal file
5
test/typeparam/issue47514c.dir/a.go
Normal file
@@ -0,0 +1,5 @@
|
||||
package a
|
||||
|
||||
type Doer[T any] interface {
|
||||
Do() T
|
||||
}
|
||||
10
test/typeparam/issue47514c.dir/main.go
Normal file
10
test/typeparam/issue47514c.dir/main.go
Normal file
@@ -0,0 +1,10 @@
|
||||
package main
|
||||
|
||||
import "./a"
|
||||
|
||||
func Do[T any](doer a.Doer[T]) {
|
||||
doer.Do()
|
||||
}
|
||||
|
||||
func main() {
|
||||
}
|
||||
7
test/typeparam/issue47514c.go
Normal file
7
test/typeparam/issue47514c.go
Normal 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/issue47631.go
Normal file
31
test/typeparam/issue47631.go
Normal 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
|
||||
}
|
||||
23
test/typeparam/issue47676.go
Normal file
23
test/typeparam/issue47676.go
Normal 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))
|
||||
}
|
||||
}
|
||||
}
|
||||
19
test/typeparam/issue47684.go
Normal file
19
test/typeparam/issue47684.go
Normal 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]()
|
||||
}
|
||||
23
test/typeparam/issue47684b.go
Normal file
23
test/typeparam/issue47684b.go
Normal 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")
|
||||
}
|
||||
}
|
||||
19
test/typeparam/issue47684c.go
Normal file
19
test/typeparam/issue47684c.go
Normal 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]()()()
|
||||
}
|
||||
37
test/typeparam/issue47708.go
Normal file
37
test/typeparam/issue47708.go
Normal 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))
|
||||
// }
|
||||
}
|
||||
19
test/typeparam/issue47710.go
Normal file
19
test/typeparam/issue47710.go
Normal 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() {}
|
||||
52
test/typeparam/issue47713.go
Normal file
52
test/typeparam/issue47713.go
Normal 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()
|
||||
}
|
||||
1
test/typeparam/issue47713.out
Normal file
1
test/typeparam/issue47713.out
Normal file
@@ -0,0 +1 @@
|
||||
Sent asdf
|
||||
68
test/typeparam/issue47716.go
Normal file
68
test/typeparam/issue47716.go
Normal 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))
|
||||
}
|
||||
}
|
||||
23
test/typeparam/issue47723.go
Normal file
23
test/typeparam/issue47723.go
Normal 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]()
|
||||
}
|
||||
40
test/typeparam/issue47740.go
Normal file
40
test/typeparam/issue47740.go
Normal 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)
|
||||
}
|
||||
0
test/typeparam/issue47740.out
Normal file
0
test/typeparam/issue47740.out
Normal file
23
test/typeparam/issue47740b.go
Normal file
23
test/typeparam/issue47740b.go
Normal 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()
|
||||
}
|
||||
19
test/typeparam/issue47775.dir/b.go
Normal file
19
test/typeparam/issue47775.dir/b.go
Normal 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{}) {
|
||||
}
|
||||
11
test/typeparam/issue47775.dir/main.go
Normal file
11
test/typeparam/issue47775.dir/main.go
Normal 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]()
|
||||
}
|
||||
7
test/typeparam/issue47775.go
Normal file
7
test/typeparam/issue47775.go
Normal 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
|
||||
28
test/typeparam/issue47775b.go
Normal file
28
test/typeparam/issue47775b.go
Normal 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]()
|
||||
}
|
||||
22
test/typeparam/issue47797.go
Normal file
22
test/typeparam/issue47797.go
Normal 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()
|
||||
}
|
||||
23
test/typeparam/issue47877.go
Normal file
23
test/typeparam/issue47877.go
Normal 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{}]()
|
||||
}
|
||||
56
test/typeparam/issue47878.go
Normal file
56
test/typeparam/issue47878.go
Normal 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
Reference in New Issue
Block a user