mirror of
https://github.com/golang/go
synced 2024-11-17 16:54:44 -07:00
go/types, types2: consolidate testdata/spec test files
Besides applying gofmt (which doesn't damage the tests in this case), this removes a TODO for a set of nil-related tests. The test files are now identical. For #54511. Change-Id: I0a286ad607f317f43972c1f5ee741b4f5bc9576d Reviewed-on: https://go-review.googlesource.com/c/go/+/424675 Run-TryBot: Robert Griesemer <gri@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> Reviewed-by: Robert Griesemer <gri@google.com>
This commit is contained in:
parent
9ad772033f
commit
17211c355f
@ -92,20 +92,20 @@ func _[
|
||||
var (
|
||||
_ _SendChan = c
|
||||
_ _RecvChan = c
|
||||
_ _Chan = c
|
||||
_ _Chan = c
|
||||
|
||||
_ _SendChan = C
|
||||
_ _RecvChan = C
|
||||
_ _Chan = C
|
||||
_ _Chan = C
|
||||
|
||||
_ SendChan = c
|
||||
_ RecvChan = c
|
||||
_ Chan = c
|
||||
_ Chan = c
|
||||
|
||||
_ SendChan = C // ERROR cannot use C .* as SendChan value
|
||||
_ RecvChan = C // ERROR cannot use C .* as RecvChan value
|
||||
_ Chan = C
|
||||
_ Chan = make /* ERROR cannot use make\(chan Basic\) .* as Chan value */ (chan Basic)
|
||||
_ Chan = C
|
||||
_ Chan = make /* ERROR cannot use make\(chan Basic\) .* as Chan value */ (chan Basic)
|
||||
)
|
||||
|
||||
var (
|
||||
@ -183,13 +183,13 @@ func _[
|
||||
Int16 ~int16,
|
||||
Int32 ~int32,
|
||||
Int64 ~int64,
|
||||
Int8_16 ~int8 | ~int16,
|
||||
Int8_16 ~int8 | ~int16,
|
||||
](
|
||||
i8 Int8,
|
||||
i16 Int16,
|
||||
i32 Int32,
|
||||
i64 Int64,
|
||||
i8_16 Int8_16,
|
||||
i8_16 Int8_16,
|
||||
) {
|
||||
b = 42
|
||||
b = 42.0
|
||||
|
@ -17,14 +17,14 @@ func _[T ~byte]() {
|
||||
var _ T = 256 // ERROR cannot use 256 .* as T value
|
||||
}
|
||||
|
||||
func _[T ~string]() T { return T('a') }
|
||||
func _[T ~int | ~string]() T { return T('a') }
|
||||
func _[T ~byte | ~int | ~string]() T { return T(256 /* ERROR cannot convert 256 .* to T */ ) }
|
||||
func _[T ~string]() T { return T('a') }
|
||||
func _[T ~int | ~string]() T { return T('a') }
|
||||
func _[T ~byte | ~int | ~string]() T { return T(256 /* ERROR cannot convert 256 .* to T */) }
|
||||
|
||||
// implicit conversions never convert to string
|
||||
func _[T ~string]() {
|
||||
var _ string = 0 // ERROR cannot use .* as string value
|
||||
var _ T = 0 // ERROR cannot use .* as T value
|
||||
var _ T = 0 // ERROR cannot use .* as T value
|
||||
}
|
||||
|
||||
// failing const conversions of constants to type parameters report a cause
|
||||
@ -34,10 +34,10 @@ func _[
|
||||
T3 ~int | ~float64 | ~bool,
|
||||
T4 ~int | ~string,
|
||||
]() {
|
||||
_ = T1(0 /* ERROR cannot convert 0 .* to T1\n\tT1 does not contain specific types */ )
|
||||
_ = T2(1 /* ERROR cannot convert 1 .* to T2\n\tT2 does not contain specific types */ )
|
||||
_ = T3(2 /* ERROR cannot convert 2 .* to T3\n\tcannot convert 2 .* to bool \(in T3\) */ )
|
||||
_ = T4(3.14 /* ERROR cannot convert 3.14 .* to T4\n\tcannot convert 3.14 .* to int \(in T4\) */ )
|
||||
_ = T1(0 /* ERROR cannot convert 0 .* to T1\n\tT1 does not contain specific types */)
|
||||
_ = T2(1 /* ERROR cannot convert 1 .* to T2\n\tT2 does not contain specific types */)
|
||||
_ = T3(2 /* ERROR cannot convert 2 .* to T3\n\tcannot convert 2 .* to bool \(in T3\) */)
|
||||
_ = T4(3.14 /* ERROR cannot convert 3.14 .* to T4\n\tcannot convert 3.14 .* to int \(in T4\) */)
|
||||
}
|
||||
|
||||
// "x is assignable to T"
|
||||
@ -46,111 +46,143 @@ func _[
|
||||
// "x's type and T have identical underlying types if tags are ignored"
|
||||
|
||||
func _[X ~int, T ~int](x X) T { return T(x) }
|
||||
func _[X struct{f int "foo"}, T struct{f int "bar"}](x X) T { return T(x) }
|
||||
func _[X struct {
|
||||
f int "foo"
|
||||
}, T struct {
|
||||
f int "bar"
|
||||
}](x X) T {
|
||||
return T(x)
|
||||
}
|
||||
|
||||
type Foo struct{f int "foo"}
|
||||
type Bar struct{f int "bar"}
|
||||
type Far struct{f float64 }
|
||||
type Foo struct {
|
||||
f int "foo"
|
||||
}
|
||||
type Bar struct {
|
||||
f int "bar"
|
||||
}
|
||||
type Far struct{ f float64 }
|
||||
|
||||
func _[X Foo, T Bar](x X) T { return T(x) }
|
||||
func _[X Foo|Bar, T Bar](x X) T { return T(x) }
|
||||
func _[X Foo, T Foo|Bar](x X) T { return T(x) }
|
||||
func _[X Foo, T Far](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Foo\) to T\n\tcannot convert Foo \(in X\) to Far \(in T\) */ ) }
|
||||
func _[X Foo, T Bar](x X) T { return T(x) }
|
||||
func _[X Foo | Bar, T Bar](x X) T { return T(x) }
|
||||
func _[X Foo, T Foo | Bar](x X) T { return T(x) }
|
||||
func _[X Foo, T Far](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by Foo\) to T\n\tcannot convert Foo \(in X\) to Far \(in T\) */)
|
||||
}
|
||||
|
||||
// "x's type and T are unnamed pointer types and their pointer base types
|
||||
// have identical underlying types if tags are ignored"
|
||||
|
||||
func _[X ~*Foo, T ~*Bar](x X) T { return T(x) }
|
||||
func _[X ~*Foo|~*Bar, T ~*Bar](x X) T { return T(x) }
|
||||
func _[X ~*Foo, T ~*Foo|~*Bar](x X) T { return T(x) }
|
||||
func _[X ~*Foo, T ~*Far](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\*Foo\) to T\n\tcannot convert \*Foo \(in X\) to \*Far \(in T\) */ ) }
|
||||
func _[X ~*Foo, T ~*Bar](x X) T { return T(x) }
|
||||
func _[X ~*Foo | ~*Bar, T ~*Bar](x X) T { return T(x) }
|
||||
func _[X ~*Foo, T ~*Foo | ~*Bar](x X) T { return T(x) }
|
||||
func _[X ~*Foo, T ~*Far](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\*Foo\) to T\n\tcannot convert \*Foo \(in X\) to \*Far \(in T\) */)
|
||||
}
|
||||
|
||||
// Verify that the defined types in constraints are considered for the rule above.
|
||||
|
||||
type (
|
||||
B int
|
||||
C int
|
||||
B int
|
||||
C int
|
||||
X0 *B
|
||||
T0 *C
|
||||
)
|
||||
|
||||
func _(x X0) T0 { return T0(x /* ERROR cannot convert */ ) } // non-generic reference
|
||||
func _[X X0, T T0](x X) T { return T(x /* ERROR cannot convert */ ) }
|
||||
func _[T T0](x X0) T { return T(x /* ERROR cannot convert */ ) }
|
||||
func _[X X0](x X) T0 { return T0(x /* ERROR cannot convert */ ) }
|
||||
func _(x X0) T0 { return T0(x /* ERROR cannot convert */) } // non-generic reference
|
||||
func _[X X0, T T0](x X) T { return T(x /* ERROR cannot convert */) }
|
||||
func _[T T0](x X0) T { return T(x /* ERROR cannot convert */) }
|
||||
func _[X X0](x X) T0 { return T0(x /* ERROR cannot convert */) }
|
||||
|
||||
// "x's type and T are both integer or floating point types"
|
||||
|
||||
func _[X Integer, T Integer](x X) T { return T(x) }
|
||||
func _[X Integer, T Integer](x X) T { return T(x) }
|
||||
func _[X Unsigned, T Integer](x X) T { return T(x) }
|
||||
func _[X Float, T Integer](x X) T { return T(x) }
|
||||
func _[X Float, T Integer](x X) T { return T(x) }
|
||||
|
||||
func _[X Integer, T Unsigned](x X) T { return T(x) }
|
||||
func _[X Integer, T Unsigned](x X) T { return T(x) }
|
||||
func _[X Unsigned, T Unsigned](x X) T { return T(x) }
|
||||
func _[X Float, T Unsigned](x X) T { return T(x) }
|
||||
func _[X Float, T Unsigned](x X) T { return T(x) }
|
||||
|
||||
func _[X Integer, T Float](x X) T { return T(x) }
|
||||
func _[X Integer, T Float](x X) T { return T(x) }
|
||||
func _[X Unsigned, T Float](x X) T { return T(x) }
|
||||
func _[X Float, T Float](x X) T { return T(x) }
|
||||
func _[X Float, T Float](x X) T { return T(x) }
|
||||
|
||||
func _[X, T Integer|Unsigned|Float](x X) T { return T(x) }
|
||||
func _[X, T Integer|~string](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Integer\|~string\) to T\n\tcannot convert string \(in X\) to int \(in T\) */ ) }
|
||||
func _[X, T Integer | Unsigned | Float](x X) T { return T(x) }
|
||||
func _[X, T Integer | ~string](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by Integer\|~string\) to T\n\tcannot convert string \(in X\) to int \(in T\) */)
|
||||
}
|
||||
|
||||
// "x's type and T are both complex types"
|
||||
|
||||
func _[X, T Complex](x X) T { return T(x) }
|
||||
func _[X, T Float|Complex](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Float\|Complex\) to T\n\tcannot convert float32 \(in X\) to complex64 \(in T\) */ ) }
|
||||
func _[X, T Float | Complex](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by Float\|Complex\) to T\n\tcannot convert float32 \(in X\) to complex64 \(in T\) */)
|
||||
}
|
||||
|
||||
// "x is an integer or a slice of bytes or runes and T is a string type"
|
||||
|
||||
type myInt int
|
||||
type myString string
|
||||
|
||||
func _[T ~string](x int) T { return T(x) }
|
||||
func _[T ~string](x myInt) T { return T(x) }
|
||||
func _[X Integer](x X) string { return string(x) }
|
||||
func _[T ~string](x int) T { return T(x) }
|
||||
func _[T ~string](x myInt) T { return T(x) }
|
||||
func _[X Integer](x X) string { return string(x) }
|
||||
func _[X Integer](x X) myString { return myString(x) }
|
||||
func _[X Integer](x X) *string { return (*string)(x /* ERROR cannot convert x \(variable of type X constrained by Integer\) to \*string\n\tcannot convert int \(in X\) to \*string */ ) }
|
||||
func _[X Integer](x X) *string {
|
||||
return (*string)(x /* ERROR cannot convert x \(variable of type X constrained by Integer\) to \*string\n\tcannot convert int \(in X\) to \*string */)
|
||||
}
|
||||
|
||||
func _[T ~string](x []byte) T { return T(x) }
|
||||
func _[T ~string](x []rune) T { return T(x) }
|
||||
func _[X ~[]byte, T ~string](x X) T { return T(x) }
|
||||
func _[X ~[]rune, T ~string](x X) T { return T(x) }
|
||||
func _[X Integer|~[]byte|~[]rune, T ~string](x X) T { return T(x) }
|
||||
func _[X Integer|~[]byte|~[]rune, T ~*string](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Integer\|~\[\]byte\|~\[\]rune\) to T\n\tcannot convert int \(in X\) to \*string \(in T\) */ ) }
|
||||
func _[T ~string](x []byte) T { return T(x) }
|
||||
func _[T ~string](x []rune) T { return T(x) }
|
||||
func _[X ~[]byte, T ~string](x X) T { return T(x) }
|
||||
func _[X ~[]rune, T ~string](x X) T { return T(x) }
|
||||
func _[X Integer | ~[]byte | ~[]rune, T ~string](x X) T { return T(x) }
|
||||
func _[X Integer | ~[]byte | ~[]rune, T ~*string](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by Integer\|~\[\]byte\|~\[\]rune\) to T\n\tcannot convert int \(in X\) to \*string \(in T\) */)
|
||||
}
|
||||
|
||||
// "x is a string and T is a slice of bytes or runes"
|
||||
|
||||
func _[T ~[]byte](x string) T { return T(x) }
|
||||
func _[T ~[]rune](x string) T { return T(x) }
|
||||
func _[T ~[]rune](x *string) T { return T(x /* ERROR cannot convert x \(variable of type \*string\) to T\n\tcannot convert \*string to \[\]rune \(in T\) */ ) }
|
||||
func _[T ~[]rune](x *string) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type \*string\) to T\n\tcannot convert \*string to \[\]rune \(in T\) */)
|
||||
}
|
||||
|
||||
func _[X ~string, T ~[]byte](x X) T { return T(x) }
|
||||
func _[X ~string, T ~[]rune](x X) T { return T(x) }
|
||||
func _[X ~string, T ~[]byte|~[]rune](x X) T { return T(x) }
|
||||
func _[X ~*string, T ~[]byte|~[]rune](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\*string\) to T\n\tcannot convert \*string \(in X\) to \[\]byte \(in T\) */ ) }
|
||||
func _[X ~string, T ~[]byte](x X) T { return T(x) }
|
||||
func _[X ~string, T ~[]rune](x X) T { return T(x) }
|
||||
func _[X ~string, T ~[]byte | ~[]rune](x X) T { return T(x) }
|
||||
func _[X ~*string, T ~[]byte | ~[]rune](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\*string\) to T\n\tcannot convert \*string \(in X\) to \[\]byte \(in T\) */)
|
||||
}
|
||||
|
||||
// package unsafe:
|
||||
// "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer"
|
||||
|
||||
type myUintptr uintptr
|
||||
|
||||
func _[X ~uintptr](x X) unsafe.Pointer { return unsafe.Pointer(x) }
|
||||
func _[X ~uintptr](x X) unsafe.Pointer { return unsafe.Pointer(x) }
|
||||
func _[T unsafe.Pointer](x myUintptr) T { return T(x) }
|
||||
func _[T unsafe.Pointer](x int64) T { return T(x /* ERROR cannot convert x \(variable of type int64\) to T\n\tcannot convert int64 to unsafe\.Pointer \(in T\) */ ) }
|
||||
func _[T unsafe.Pointer](x int64) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type int64\) to T\n\tcannot convert int64 to unsafe\.Pointer \(in T\) */)
|
||||
}
|
||||
|
||||
// "and vice versa"
|
||||
|
||||
func _[T ~uintptr](x unsafe.Pointer) T { return T(x) }
|
||||
func _[X unsafe.Pointer](x X) uintptr { return uintptr(x) }
|
||||
func _[T ~uintptr](x unsafe.Pointer) T { return T(x) }
|
||||
func _[X unsafe.Pointer](x X) uintptr { return uintptr(x) }
|
||||
func _[X unsafe.Pointer](x X) myUintptr { return myUintptr(x) }
|
||||
func _[X unsafe.Pointer](x X) int64 { return int64(x /* ERROR cannot convert x \(variable of type X constrained by unsafe\.Pointer\) to int64\n\tcannot convert unsafe\.Pointer \(in X\) to int64 */ ) }
|
||||
func _[X unsafe.Pointer](x X) int64 {
|
||||
return int64(x /* ERROR cannot convert x \(variable of type X constrained by unsafe\.Pointer\) to int64\n\tcannot convert unsafe\.Pointer \(in X\) to int64 */)
|
||||
}
|
||||
|
||||
// "x is a slice, T is a pointer-to-array type,
|
||||
// and the slice and array types have identical element types."
|
||||
|
||||
func _[X ~[]E, T ~*[10]E, E any](x X) T { return T(x) }
|
||||
func _[X ~[]E, T ~[10]E, E any](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\[\]E\) to T\n\tcannot convert \[\]E \(in X\) to \[10\]E \(in T\) */ ) }
|
||||
func _[X ~[]E, T ~[10]E, E any](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\[\]E\) to T\n\tcannot convert \[\]E \(in X\) to \[10\]E \(in T\) */)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// The following declarations can be replaced by the exported types of the
|
||||
|
16
src/go/types/testdata/spec/assignability.go
vendored
16
src/go/types/testdata/spec/assignability.go
vendored
@ -92,20 +92,20 @@ func _[
|
||||
var (
|
||||
_ _SendChan = c
|
||||
_ _RecvChan = c
|
||||
_ _Chan = c
|
||||
_ _Chan = c
|
||||
|
||||
_ _SendChan = C
|
||||
_ _RecvChan = C
|
||||
_ _Chan = C
|
||||
_ _Chan = C
|
||||
|
||||
_ SendChan = c
|
||||
_ RecvChan = c
|
||||
_ Chan = c
|
||||
_ Chan = c
|
||||
|
||||
_ SendChan = C // ERROR cannot use C .* as SendChan value
|
||||
_ RecvChan = C // ERROR cannot use C .* as RecvChan value
|
||||
_ Chan = C
|
||||
_ Chan = make /* ERROR cannot use make\(chan Basic\) .* as Chan value */ (chan Basic)
|
||||
_ Chan = C
|
||||
_ Chan = make /* ERROR cannot use make\(chan Basic\) .* as Chan value */ (chan Basic)
|
||||
)
|
||||
|
||||
var (
|
||||
@ -152,8 +152,6 @@ func _[
|
||||
}
|
||||
|
||||
// "x is the predeclared identifier nil and T is a pointer, function, slice, map, channel, or interface type"
|
||||
// TODO(rfindley) error messages about untyped nil diverge from types2 here.
|
||||
// Consider aligning them.
|
||||
func _[TP Interface](X TP) {
|
||||
b = nil // ERROR cannot use nil
|
||||
a = nil // ERROR cannot use nil
|
||||
@ -185,13 +183,13 @@ func _[
|
||||
Int16 ~int16,
|
||||
Int32 ~int32,
|
||||
Int64 ~int64,
|
||||
Int8_16 ~int8 | ~int16,
|
||||
Int8_16 ~int8 | ~int16,
|
||||
](
|
||||
i8 Int8,
|
||||
i16 Int16,
|
||||
i32 Int32,
|
||||
i64 Int64,
|
||||
i8_16 Int8_16,
|
||||
i8_16 Int8_16,
|
||||
) {
|
||||
b = 42
|
||||
b = 42.0
|
||||
|
144
src/go/types/testdata/spec/conversions.go
vendored
144
src/go/types/testdata/spec/conversions.go
vendored
@ -17,14 +17,14 @@ func _[T ~byte]() {
|
||||
var _ T = 256 // ERROR cannot use 256 .* as T value
|
||||
}
|
||||
|
||||
func _[T ~string]() T { return T('a') }
|
||||
func _[T ~int | ~string]() T { return T('a') }
|
||||
func _[T ~byte | ~int | ~string]() T { return T(256 /* ERROR cannot convert 256 .* to T */ ) }
|
||||
func _[T ~string]() T { return T('a') }
|
||||
func _[T ~int | ~string]() T { return T('a') }
|
||||
func _[T ~byte | ~int | ~string]() T { return T(256 /* ERROR cannot convert 256 .* to T */) }
|
||||
|
||||
// implicit conversions never convert to string
|
||||
func _[T ~string]() {
|
||||
var _ string = 0 // ERROR cannot use .* as string value
|
||||
var _ T = 0 // ERROR cannot use .* as T value
|
||||
var _ T = 0 // ERROR cannot use .* as T value
|
||||
}
|
||||
|
||||
// failing const conversions of constants to type parameters report a cause
|
||||
@ -34,10 +34,10 @@ func _[
|
||||
T3 ~int | ~float64 | ~bool,
|
||||
T4 ~int | ~string,
|
||||
]() {
|
||||
_ = T1(0 /* ERROR cannot convert 0 .* to T1\n\tT1 does not contain specific types */ )
|
||||
_ = T2(1 /* ERROR cannot convert 1 .* to T2\n\tT2 does not contain specific types */ )
|
||||
_ = T3(2 /* ERROR cannot convert 2 .* to T3\n\tcannot convert 2 .* to bool \(in T3\) */ )
|
||||
_ = T4(3.14 /* ERROR cannot convert 3.14 .* to T4\n\tcannot convert 3.14 .* to int \(in T4\) */ )
|
||||
_ = T1(0 /* ERROR cannot convert 0 .* to T1\n\tT1 does not contain specific types */)
|
||||
_ = T2(1 /* ERROR cannot convert 1 .* to T2\n\tT2 does not contain specific types */)
|
||||
_ = T3(2 /* ERROR cannot convert 2 .* to T3\n\tcannot convert 2 .* to bool \(in T3\) */)
|
||||
_ = T4(3.14 /* ERROR cannot convert 3.14 .* to T4\n\tcannot convert 3.14 .* to int \(in T4\) */)
|
||||
}
|
||||
|
||||
// "x is assignable to T"
|
||||
@ -46,111 +46,143 @@ func _[
|
||||
// "x's type and T have identical underlying types if tags are ignored"
|
||||
|
||||
func _[X ~int, T ~int](x X) T { return T(x) }
|
||||
func _[X struct{f int "foo"}, T struct{f int "bar"}](x X) T { return T(x) }
|
||||
func _[X struct {
|
||||
f int "foo"
|
||||
}, T struct {
|
||||
f int "bar"
|
||||
}](x X) T {
|
||||
return T(x)
|
||||
}
|
||||
|
||||
type Foo struct{f int "foo"}
|
||||
type Bar struct{f int "bar"}
|
||||
type Far struct{f float64 }
|
||||
type Foo struct {
|
||||
f int "foo"
|
||||
}
|
||||
type Bar struct {
|
||||
f int "bar"
|
||||
}
|
||||
type Far struct{ f float64 }
|
||||
|
||||
func _[X Foo, T Bar](x X) T { return T(x) }
|
||||
func _[X Foo|Bar, T Bar](x X) T { return T(x) }
|
||||
func _[X Foo, T Foo|Bar](x X) T { return T(x) }
|
||||
func _[X Foo, T Far](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Foo\) to T\n\tcannot convert Foo \(in X\) to Far \(in T\) */ ) }
|
||||
func _[X Foo, T Bar](x X) T { return T(x) }
|
||||
func _[X Foo | Bar, T Bar](x X) T { return T(x) }
|
||||
func _[X Foo, T Foo | Bar](x X) T { return T(x) }
|
||||
func _[X Foo, T Far](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by Foo\) to T\n\tcannot convert Foo \(in X\) to Far \(in T\) */)
|
||||
}
|
||||
|
||||
// "x's type and T are unnamed pointer types and their pointer base types
|
||||
// have identical underlying types if tags are ignored"
|
||||
|
||||
func _[X ~*Foo, T ~*Bar](x X) T { return T(x) }
|
||||
func _[X ~*Foo|~*Bar, T ~*Bar](x X) T { return T(x) }
|
||||
func _[X ~*Foo, T ~*Foo|~*Bar](x X) T { return T(x) }
|
||||
func _[X ~*Foo, T ~*Far](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\*Foo\) to T\n\tcannot convert \*Foo \(in X\) to \*Far \(in T\) */ ) }
|
||||
func _[X ~*Foo, T ~*Bar](x X) T { return T(x) }
|
||||
func _[X ~*Foo | ~*Bar, T ~*Bar](x X) T { return T(x) }
|
||||
func _[X ~*Foo, T ~*Foo | ~*Bar](x X) T { return T(x) }
|
||||
func _[X ~*Foo, T ~*Far](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\*Foo\) to T\n\tcannot convert \*Foo \(in X\) to \*Far \(in T\) */)
|
||||
}
|
||||
|
||||
// Verify that the defined types in constraints are considered for the rule above.
|
||||
|
||||
type (
|
||||
B int
|
||||
C int
|
||||
B int
|
||||
C int
|
||||
X0 *B
|
||||
T0 *C
|
||||
)
|
||||
|
||||
func _(x X0) T0 { return T0(x /* ERROR cannot convert */ ) } // non-generic reference
|
||||
func _[X X0, T T0](x X) T { return T(x /* ERROR cannot convert */ ) }
|
||||
func _[T T0](x X0) T { return T(x /* ERROR cannot convert */ ) }
|
||||
func _[X X0](x X) T0 { return T0(x /* ERROR cannot convert */ ) }
|
||||
func _(x X0) T0 { return T0(x /* ERROR cannot convert */) } // non-generic reference
|
||||
func _[X X0, T T0](x X) T { return T(x /* ERROR cannot convert */) }
|
||||
func _[T T0](x X0) T { return T(x /* ERROR cannot convert */) }
|
||||
func _[X X0](x X) T0 { return T0(x /* ERROR cannot convert */) }
|
||||
|
||||
// "x's type and T are both integer or floating point types"
|
||||
|
||||
func _[X Integer, T Integer](x X) T { return T(x) }
|
||||
func _[X Integer, T Integer](x X) T { return T(x) }
|
||||
func _[X Unsigned, T Integer](x X) T { return T(x) }
|
||||
func _[X Float, T Integer](x X) T { return T(x) }
|
||||
func _[X Float, T Integer](x X) T { return T(x) }
|
||||
|
||||
func _[X Integer, T Unsigned](x X) T { return T(x) }
|
||||
func _[X Integer, T Unsigned](x X) T { return T(x) }
|
||||
func _[X Unsigned, T Unsigned](x X) T { return T(x) }
|
||||
func _[X Float, T Unsigned](x X) T { return T(x) }
|
||||
func _[X Float, T Unsigned](x X) T { return T(x) }
|
||||
|
||||
func _[X Integer, T Float](x X) T { return T(x) }
|
||||
func _[X Integer, T Float](x X) T { return T(x) }
|
||||
func _[X Unsigned, T Float](x X) T { return T(x) }
|
||||
func _[X Float, T Float](x X) T { return T(x) }
|
||||
func _[X Float, T Float](x X) T { return T(x) }
|
||||
|
||||
func _[X, T Integer|Unsigned|Float](x X) T { return T(x) }
|
||||
func _[X, T Integer|~string](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Integer\|~string\) to T\n\tcannot convert string \(in X\) to int \(in T\) */ ) }
|
||||
func _[X, T Integer | Unsigned | Float](x X) T { return T(x) }
|
||||
func _[X, T Integer | ~string](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by Integer\|~string\) to T\n\tcannot convert string \(in X\) to int \(in T\) */)
|
||||
}
|
||||
|
||||
// "x's type and T are both complex types"
|
||||
|
||||
func _[X, T Complex](x X) T { return T(x) }
|
||||
func _[X, T Float|Complex](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Float\|Complex\) to T\n\tcannot convert float32 \(in X\) to complex64 \(in T\) */ ) }
|
||||
func _[X, T Float | Complex](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by Float\|Complex\) to T\n\tcannot convert float32 \(in X\) to complex64 \(in T\) */)
|
||||
}
|
||||
|
||||
// "x is an integer or a slice of bytes or runes and T is a string type"
|
||||
|
||||
type myInt int
|
||||
type myString string
|
||||
|
||||
func _[T ~string](x int) T { return T(x) }
|
||||
func _[T ~string](x myInt) T { return T(x) }
|
||||
func _[X Integer](x X) string { return string(x) }
|
||||
func _[T ~string](x int) T { return T(x) }
|
||||
func _[T ~string](x myInt) T { return T(x) }
|
||||
func _[X Integer](x X) string { return string(x) }
|
||||
func _[X Integer](x X) myString { return myString(x) }
|
||||
func _[X Integer](x X) *string { return (*string)(x /* ERROR cannot convert x \(variable of type X constrained by Integer\) to \*string\n\tcannot convert int \(in X\) to \*string */ ) }
|
||||
func _[X Integer](x X) *string {
|
||||
return (*string)(x /* ERROR cannot convert x \(variable of type X constrained by Integer\) to \*string\n\tcannot convert int \(in X\) to \*string */)
|
||||
}
|
||||
|
||||
func _[T ~string](x []byte) T { return T(x) }
|
||||
func _[T ~string](x []rune) T { return T(x) }
|
||||
func _[X ~[]byte, T ~string](x X) T { return T(x) }
|
||||
func _[X ~[]rune, T ~string](x X) T { return T(x) }
|
||||
func _[X Integer|~[]byte|~[]rune, T ~string](x X) T { return T(x) }
|
||||
func _[X Integer|~[]byte|~[]rune, T ~*string](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by Integer\|~\[\]byte\|~\[\]rune\) to T\n\tcannot convert int \(in X\) to \*string \(in T\) */ ) }
|
||||
func _[T ~string](x []byte) T { return T(x) }
|
||||
func _[T ~string](x []rune) T { return T(x) }
|
||||
func _[X ~[]byte, T ~string](x X) T { return T(x) }
|
||||
func _[X ~[]rune, T ~string](x X) T { return T(x) }
|
||||
func _[X Integer | ~[]byte | ~[]rune, T ~string](x X) T { return T(x) }
|
||||
func _[X Integer | ~[]byte | ~[]rune, T ~*string](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by Integer\|~\[\]byte\|~\[\]rune\) to T\n\tcannot convert int \(in X\) to \*string \(in T\) */)
|
||||
}
|
||||
|
||||
// "x is a string and T is a slice of bytes or runes"
|
||||
|
||||
func _[T ~[]byte](x string) T { return T(x) }
|
||||
func _[T ~[]rune](x string) T { return T(x) }
|
||||
func _[T ~[]rune](x *string) T { return T(x /* ERROR cannot convert x \(variable of type \*string\) to T\n\tcannot convert \*string to \[\]rune \(in T\) */ ) }
|
||||
func _[T ~[]rune](x *string) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type \*string\) to T\n\tcannot convert \*string to \[\]rune \(in T\) */)
|
||||
}
|
||||
|
||||
func _[X ~string, T ~[]byte](x X) T { return T(x) }
|
||||
func _[X ~string, T ~[]rune](x X) T { return T(x) }
|
||||
func _[X ~string, T ~[]byte|~[]rune](x X) T { return T(x) }
|
||||
func _[X ~*string, T ~[]byte|~[]rune](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\*string\) to T\n\tcannot convert \*string \(in X\) to \[\]byte \(in T\) */ ) }
|
||||
func _[X ~string, T ~[]byte](x X) T { return T(x) }
|
||||
func _[X ~string, T ~[]rune](x X) T { return T(x) }
|
||||
func _[X ~string, T ~[]byte | ~[]rune](x X) T { return T(x) }
|
||||
func _[X ~*string, T ~[]byte | ~[]rune](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\*string\) to T\n\tcannot convert \*string \(in X\) to \[\]byte \(in T\) */)
|
||||
}
|
||||
|
||||
// package unsafe:
|
||||
// "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer"
|
||||
|
||||
type myUintptr uintptr
|
||||
|
||||
func _[X ~uintptr](x X) unsafe.Pointer { return unsafe.Pointer(x) }
|
||||
func _[X ~uintptr](x X) unsafe.Pointer { return unsafe.Pointer(x) }
|
||||
func _[T unsafe.Pointer](x myUintptr) T { return T(x) }
|
||||
func _[T unsafe.Pointer](x int64) T { return T(x /* ERROR cannot convert x \(variable of type int64\) to T\n\tcannot convert int64 to unsafe\.Pointer \(in T\) */ ) }
|
||||
func _[T unsafe.Pointer](x int64) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type int64\) to T\n\tcannot convert int64 to unsafe\.Pointer \(in T\) */)
|
||||
}
|
||||
|
||||
// "and vice versa"
|
||||
|
||||
func _[T ~uintptr](x unsafe.Pointer) T { return T(x) }
|
||||
func _[X unsafe.Pointer](x X) uintptr { return uintptr(x) }
|
||||
func _[T ~uintptr](x unsafe.Pointer) T { return T(x) }
|
||||
func _[X unsafe.Pointer](x X) uintptr { return uintptr(x) }
|
||||
func _[X unsafe.Pointer](x X) myUintptr { return myUintptr(x) }
|
||||
func _[X unsafe.Pointer](x X) int64 { return int64(x /* ERROR cannot convert x \(variable of type X constrained by unsafe\.Pointer\) to int64\n\tcannot convert unsafe\.Pointer \(in X\) to int64 */ ) }
|
||||
func _[X unsafe.Pointer](x X) int64 {
|
||||
return int64(x /* ERROR cannot convert x \(variable of type X constrained by unsafe\.Pointer\) to int64\n\tcannot convert unsafe\.Pointer \(in X\) to int64 */)
|
||||
}
|
||||
|
||||
// "x is a slice, T is a pointer-to-array type,
|
||||
// and the slice and array types have identical element types."
|
||||
|
||||
func _[X ~[]E, T ~*[10]E, E any](x X) T { return T(x) }
|
||||
func _[X ~[]E, T ~[10]E, E any](x X) T { return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\[\]E\) to T\n\tcannot convert \[\]E \(in X\) to \[10\]E \(in T\) */ ) }
|
||||
func _[X ~[]E, T ~[10]E, E any](x X) T {
|
||||
return T(x /* ERROR cannot convert x \(variable of type X constrained by ~\[\]E\) to T\n\tcannot convert \[\]E \(in X\) to \[10\]E \(in T\) */)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// The following declarations can be replaced by the exported types of the
|
||||
|
Loading…
Reference in New Issue
Block a user