blob: 0aaaa8278c1478fa472383dfa5dd9ec5badb8ebc [file] [log] [blame]
// -lang=go1.20
// 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)
var y float64
_ = min(1, y)
_ = min(1.2, y)
_ = min(1.2, 3.4)
_ = min(1.2, 3)
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 "Slice (type []int) does not satisfy interface{[]Elem}" */ (float64(1.0), []int{}) // TODO(gri) better error message
}
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]]()
// The 2nd type argument cannot be inferred from the first
// one because there's two possible choices: []Elem and
// List[Elem].
related3 /* ERROR "cannot infer Slice" */ [int]()
}
func wantsMethods[P interface {
m1(Q)
m2() R
}, Q, R any](P) {
}
type hasMethods1 struct{}
func (hasMethods1) m1(int)
func (hasMethods1) m2() string
type hasMethods2 struct{}
func (*hasMethods2) m1(int)
func (*hasMethods2) m2() string
type hasMethods3 interface {
m1(float64)
m2() complex128
}
type hasMethods4 interface {
m1()
}
func _() {
// wantsMethod can be called with arguments that have the relevant methods
// and wantsMethod's type arguments are inferred from those types' method
// signatures.
wantsMethods(hasMethods1{})
wantsMethods(&hasMethods1{})
wantsMethods /* ERROR "P (type hasMethods2) does not satisfy interface{m1(Q); m2() R} (method m1 has pointer receiver)" */ (hasMethods2{})
wantsMethods(&hasMethods2{})
wantsMethods(hasMethods3(nil))
wantsMethods /* ERROR "P (type any) does not satisfy interface{m1(Q); m2() R} (missing method m1)" */ (any(nil))
wantsMethods /* ERROR "P (type hasMethods4) does not satisfy interface{m1(Q); m2() R} (wrong type for method m1)" */ (hasMethods4(nil))
}
// "Reverse" type inference is not yet permitted.
func f[P any](P) {}
// This must not crash.
var _ func(int) = f // ERROR "implicitly instantiated function in assignment requires go1.21 or later"