]> Cypherpunks.ru repositories - gostls13.git/blob - test/typeparam/settable.go
cmd/compile/internal/inline: score call sites exposed by inlines
[gostls13.git] / test / typeparam / settable.go
1 // run
2
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.
6
7 package main
8
9 import (
10         "fmt"
11         "strconv"
12 )
13
14 // Various implementations of fromStrings().
15
16 type Setter[B any] interface {
17         Set(string)
18         *B
19 }
20
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))
24         for i, v := range 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.
27                 p := PT(&result[i])
28                 // PT has a Set method.
29                 p.Set(v)
30         }
31         return result
32 }
33
34 func fromStrings1a[T any, PT Setter[T]](s []string) []PT {
35         result := make([]PT, len(s))
36         for i, v := range 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))
40                 p := result[i]
41                 // PT has a Set method.
42                 p.Set(v)
43         }
44         return result
45 }
46
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))
50         for i, v := range s {
51                 set(&results[i], v)
52         }
53         return results
54 }
55
56 type Setter2 interface {
57         Set(string)
58 }
59
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))
63         for i, v := range s {
64                 // Panics if T is a pointer type because receiver is T(nil).
65                 results[i].Set(v)
66         }
67         return results
68 }
69
70 // Two concrete types with the appropriate Set method.
71
72 type SettableInt int
73
74 func (p *SettableInt) Set(s string) {
75         i, err := strconv.Atoi(s)
76         if err != nil {
77                 panic(err)
78         }
79         *p = SettableInt(i)
80 }
81
82 type SettableString struct {
83         s string
84 }
85
86 func (x *SettableString) Set(s string) {
87         x.s = s
88 }
89
90 func main() {
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}))
94         }
95
96         s2 := fromStrings1a[SettableInt, *SettableInt]([]string{"1"})
97         if len(s2) != 1 || *s2[0] != 1 {
98                 x := 1
99                 panic(fmt.Sprintf("got %v, want %v", s2, []*int{&x}))
100         }
101
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"}) {
106                 panic(s)
107         }
108
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}))
112         }
113
114         defer func() {
115                 if recover() == nil {
116                         panic("did not panic as expected")
117                 }
118         }()
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"})
123 }