// 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) }