3 // Copyright 2021 The Go Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style
5 // license that can be found in the LICENSE file.
14 // Various implementations of fromStrings().
16 type Setter[B any] interface {
21 // Takes two type parameters where PT = *T
22 func fromStrings1[T any, PT Setter[T]](s []string) []T {
23 result := make([]T, len(s))
25 // The type of &result[i] is *T which is in the type list
26 // of Setter, so we can convert it to PT.
28 // PT has a Set method.
34 func fromStrings1a[T any, PT Setter[T]](s []string) []PT {
35 result := make([]PT, len(s))
37 // The type new(T) is *T which is in the type list
38 // of Setter, so we can convert it to PT.
39 result[i] = PT(new(T))
41 // PT has a Set method.
47 // Takes one type parameter and a set function
48 func fromStrings2[T any](s []string, set func(*T, string)) []T {
49 results := make([]T, len(s))
56 type Setter2 interface {
60 // Takes only one type parameter, but causes a panic (see below)
61 func fromStrings3[T Setter2](s []string) []T {
62 results := make([]T, len(s))
64 // Panics if T is a pointer type because receiver is T(nil).
70 // Two concrete types with the appropriate Set method.
74 func (p *SettableInt) Set(s string) {
75 i, err := strconv.Atoi(s)
82 type SettableString struct {
86 func (x *SettableString) Set(s string) {
91 s := fromStrings1[SettableInt, *SettableInt]([]string{"1"})
92 if len(s) != 1 || s[0] != 1 {
93 panic(fmt.Sprintf("got %v, want %v", s, []int{1}))
96 s2 := fromStrings1a[SettableInt, *SettableInt]([]string{"1"})
97 if len(s2) != 1 || *s2[0] != 1 {
99 panic(fmt.Sprintf("got %v, want %v", s2, []*int{&x}))
102 // Test out constraint type inference, which should determine that the second
103 // type param is *SettableString.
104 ps := fromStrings1[SettableString]([]string{"x", "y"})
105 if len(ps) != 2 || ps[0] != (SettableString{"x"}) || ps[1] != (SettableString{"y"}) {
109 s = fromStrings2([]string{"1"}, func(p *SettableInt, s string) { p.Set(s) })
110 if len(s) != 1 || s[0] != 1 {
111 panic(fmt.Sprintf("got %v, want %v", s, []int{1}))
115 if recover() == nil {
116 panic("did not panic as expected")
119 // This should type check but should panic at run time,
120 // because it will make a slice of *SettableInt and then call
121 // Set on a nil value.
122 fromStrings3[*SettableInt]([]string{"1"})