|
| 1 | +// Copyright 2021 The Go Authors. All rights reserved. |
| 2 | +// Use of this source code is governed by a BSD-style |
| 3 | +// license that can be found in the LICENSE file. |
| 4 | + |
| 5 | +package conversions |
| 6 | + |
| 7 | +import "unsafe" |
| 8 | + |
| 9 | +// "x is assignable to T" |
| 10 | +// - tested via assignability tests |
| 11 | + |
| 12 | +// "x's type and T have identical underlying types if tags are ignored" |
| 13 | + |
| 14 | +func _[X ~int, T ~int](x X) T { return T(x) } |
| 15 | +func _[X struct{f int "foo"}, T struct{f int "bar"}](x X) T { return T(x) } |
| 16 | + |
| 17 | +type Foo struct{f int "foo"} |
| 18 | +type Bar struct{f int "bar"} |
| 19 | +type Far struct{f float64 } |
| 20 | + |
| 21 | +func _[X Foo, T Bar](x X) T { return T(x) } |
| 22 | +func _[X Foo|Bar, T Bar](x X) T { return T(x) } |
| 23 | +func _[X Foo, T Foo|Bar](x X) T { return T(x) } |
| 24 | +func _[X Foo, T Far](x X) T { return T(x /* ERROR cannot convert */ ) } |
| 25 | + |
| 26 | +// "x's type and T are unnamed pointer types and their pointer base types |
| 27 | +// have identical underlying types if tags are ignored" |
| 28 | + |
| 29 | +func _[X ~*Foo, T ~*Bar](x X) T { return T(x) } |
| 30 | +func _[X ~*Foo|~*Bar, T ~*Bar](x X) T { return T(x) } |
| 31 | +func _[X ~*Foo, T ~*Foo|~*Bar](x X) T { return T(x) } |
| 32 | +func _[X ~*Foo, T ~*Far](x X) T { return T(x /* ERROR cannot convert */ ) } |
| 33 | + |
| 34 | +// "x's type and T are both integer or floating point types" |
| 35 | + |
| 36 | +func _[X Integer, T Integer](x X) T { return T(x) } |
| 37 | +func _[X Unsigned, T Integer](x X) T { return T(x) } |
| 38 | +func _[X Float, T Integer](x X) T { return T(x) } |
| 39 | + |
| 40 | +func _[X Integer, T Unsigned](x X) T { return T(x) } |
| 41 | +func _[X Unsigned, T Unsigned](x X) T { return T(x) } |
| 42 | +func _[X Float, T Unsigned](x X) T { return T(x) } |
| 43 | + |
| 44 | +func _[X Integer, T Float](x X) T { return T(x) } |
| 45 | +func _[X Unsigned, T Float](x X) T { return T(x) } |
| 46 | +func _[X Float, T Float](x X) T { return T(x) } |
| 47 | + |
| 48 | +func _[X, T Integer|Unsigned|Float](x X) T { return T(x) } |
| 49 | +func _[X, T Integer|~string](x X) T { return T(x /* ERROR cannot convert */ ) } |
| 50 | + |
| 51 | +// "x's type and T are both complex types" |
| 52 | + |
| 53 | +func _[X, T Complex](x X) T { return T(x) } |
| 54 | +func _[X, T Float|Complex](x X) T { return T(x /* ERROR cannot convert */ ) } |
| 55 | + |
| 56 | +// "x is an integer or a slice of bytes or runes and T is a string type" |
| 57 | + |
| 58 | +type myInt int |
| 59 | +type myString string |
| 60 | + |
| 61 | +func _[T ~string](x int) T { return T(x) } |
| 62 | +func _[T ~string](x myInt) T { return T(x) } |
| 63 | +func _[X Integer](x X) string { return string(x) } |
| 64 | +func _[X Integer](x X) myString { return myString(x) } |
| 65 | +func _[X Integer](x X) *string { return (*string)(x /* ERROR cannot convert */ ) } |
| 66 | + |
| 67 | +func _[T ~string](x []byte) T { return T(x) } |
| 68 | +func _[T ~string](x []rune) T { return T(x) } |
| 69 | +func _[X ~[]byte, T ~string](x X) T { return T(x) } |
| 70 | +func _[X ~[]rune, T ~string](x X) T { return T(x) } |
| 71 | +func _[X Integer|~[]byte|~[]rune, T ~string](x X) T { return T(x) } |
| 72 | +func _[X Integer|~[]byte|~[]rune, T ~*string](x X) T { return T(x /* ERROR cannot convert */ ) } |
| 73 | + |
| 74 | +// "x is a string and T is a slice of bytes or runes" |
| 75 | + |
| 76 | +func _[T ~[]byte](x string) T { return T(x) } |
| 77 | +func _[T ~[]rune](x string) T { return T(x) } |
| 78 | +func _[T ~[]rune](x *string) T { return T(x /* ERROR cannot convert */ ) } |
| 79 | + |
| 80 | +func _[X ~string, T ~[]byte](x X) T { return T(x) } |
| 81 | +func _[X ~string, T ~[]rune](x X) T { return T(x) } |
| 82 | +func _[X ~string, T ~[]byte|~[]rune](x X) T { return T(x) } |
| 83 | +func _[X ~*string, T ~[]byte|~[]rune](x X) T { return T(x /* ERROR cannot convert */ ) } |
| 84 | + |
| 85 | +// package unsafe: |
| 86 | +// "any pointer or value of underlying type uintptr can be converted into a unsafe.Pointer" |
| 87 | + |
| 88 | +type myUintptr uintptr |
| 89 | + |
| 90 | +func _[X ~uintptr](x X) unsafe.Pointer { return unsafe.Pointer(x) } |
| 91 | +func _[T unsafe.Pointer](x myUintptr) T { return T(x) } |
| 92 | +func _[T unsafe.Pointer](x int64) T { return T(x /* ERROR cannot convert */ ) } |
| 93 | + |
| 94 | +// "and vice versa" |
| 95 | + |
| 96 | +func _[T ~uintptr](x unsafe.Pointer) T { return T(x) } |
| 97 | +func _[X unsafe.Pointer](x X) uintptr { return uintptr(x) } |
| 98 | +func _[X unsafe.Pointer](x X) myUintptr { return myUintptr(x) } |
| 99 | +func _[X unsafe.Pointer](x X) int64 { return int64(x /* ERROR cannot convert */ ) } |
| 100 | + |
| 101 | +// "x is a slice, T is a pointer-to-array type, |
| 102 | +// and the slice and array types have identical element types." |
| 103 | + |
| 104 | +func _[X ~[]E, T ~*[10]E, E any](x X) T { return T(x) } |
| 105 | +func _[X ~[]E, T ~[10]E, E any](x X) T { return T(x /* ERROR cannot convert */ ) } |
| 106 | + |
| 107 | +// ---------------------------------------------------------------------------- |
| 108 | +// The following declarations can be replaced by the exported types of the |
| 109 | +// constraints package once all builders support importing interfaces with |
| 110 | +// type constraints. |
| 111 | + |
| 112 | +type Signed interface { |
| 113 | + ~int | ~int8 | ~int16 | ~int32 | ~int64 |
| 114 | +} |
| 115 | + |
| 116 | +type Unsigned interface { |
| 117 | + ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | ~uintptr |
| 118 | +} |
| 119 | + |
| 120 | +type Integer interface { |
| 121 | + Signed | Unsigned |
| 122 | +} |
| 123 | + |
| 124 | +type Float interface { |
| 125 | + ~float32 | ~float64 |
| 126 | +} |
| 127 | + |
| 128 | +type Complex interface { |
| 129 | + ~complex64 | ~complex128 |
| 130 | +} |
0 commit comments