| // 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 file shows some examples of type inference. |
| |
| package p |
| |
| type Ordered interface { |
| ~int|~float64|~string |
| } |
| |
| func min[T Ordered](x, y T) T { panic(0) } |
| |
| func _() { |
| // min can be called with explicit instantiation. |
| _ = min[int](1, 2) |
| |
| // Alternatively, the type argument can be inferred from |
| // one of the arguments. Untyped arguments will be considered |
| // last. |
| var x int |
| _ = min(x, x) |
| _ = min(x, 1) |
| _ = min(x, 1.0) |
| _ = min(1, 2) |
| _ = min(1, 2.3 /* ERROR default type float64 .* does not match */ ) |
| |
| var y float64 |
| _ = min(1, y) |
| _ = min(1.2, y) |
| _ = min(1.2, 3.4) |
| _ = min(1.2, 3 /* ERROR default type int .* does not match */ ) |
| |
| var s string |
| _ = min(s, "foo") |
| _ = min("foo", "bar") |
| } |
| |
| func mixed[T1, T2, T3 any](T1, T2, T3) {} |
| |
| func _() { |
| // mixed can be called with explicit instantiation. |
| mixed[int, string, bool](0, "", false) |
| |
| // Alternatively, partial type arguments may be provided |
| // (from left to right), and the other may be inferred. |
| mixed[int, string](0, "", false) |
| mixed[int](0, "", false) |
| mixed(0, "", false) |
| |
| // Provided type arguments always take precedence over |
| // inferred types. |
| mixed[int, string](1.1 /* ERROR cannot use 1.1 */ , "", false) |
| } |
| |
| func related1[Slice interface{~[]Elem}, Elem any](s Slice, e Elem) {} |
| |
| func _() { |
| // related1 can be called with explicit instantiation. |
| var si []int |
| related1[[]int, int](si, 0) |
| |
| // Alternatively, the 2nd type argument can be inferred |
| // from the first one through constraint type inference. |
| var ss []string |
| _ = related1[[]string] |
| related1[[]string](ss, "foo") |
| |
| // A type argument inferred from another explicitly provided |
| // type argument overrides whatever value argument type is given. |
| related1[[]string](ss, 0 /* ERROR cannot use 0 */ ) |
| |
| // A type argument may be inferred from a value argument |
| // and then help infer another type argument via constraint |
| // type inference. |
| related1(si, 0) |
| related1(si, "foo" /* ERROR cannot use "foo" */ ) |
| } |
| |
| func related2[Elem any, Slice interface{~[]Elem}](e Elem, s Slice) {} |
| |
| func _() { |
| // related2 can be called with explicit instantiation. |
| var si []int |
| related2[int, []int](0, si) |
| |
| // Alternatively, the 2nd type argument can be inferred |
| // from the first one through constraint type inference. |
| var ss []string |
| _ = related2[string] |
| related2[string]("foo", ss) |
| |
| // A type argument may be inferred from a value argument |
| // and then help infer another type argument via constraint |
| // type inference. Untyped arguments are always considered |
| // last. |
| related2(1.2, []float64{}) |
| related2(1.0, []int{}) |
| related2( /* ERROR does not implement */ float64(1.0), []int{}) // TODO(gri) fix error position |
| } |
| |
| type List[P any] []P |
| |
| func related3[Elem any, Slice []Elem | List[Elem]]() Slice { return nil } |
| |
| func _() { |
| // related3 can be instantiated explicitly |
| related3[int, []int]() |
| related3[byte, List[byte]]() |
| |
| // Alternatively, the 2nd type argument can be inferred |
| // from the first one through constraint type inference. |
| related3[int]() |
| |
| // The inferred type is the core type of the Slice |
| // type parameter. |
| var _ []int = related3[int]() |
| |
| // It is not the defined parameterized type List. |
| type anotherList []float32 |
| var _ anotherList = related3[float32]() // valid |
| var _ anotherList = related3 /* ERROR cannot use .* \(value of type List\[float32\]\) as anotherList */ [float32, List[float32]]() |
| } |