mirror of
https://github.com/golang/go
synced 2024-11-17 20:14:45 -07:00
df4c625d88
Add (temporary) syntax.AllowTypeLists mode to control the acceptance of type lists; the compiler doesn't set it, but existing syntax and types2 tests do so that the code remains exercised while it exists. Adjust various tests to use the type set notation. Change-Id: I798e607912552db6bfe38a7cd4324b74c6bf4d95 Reviewed-on: https://go-review.googlesource.com/c/go/+/347249 Trust: Robert Griesemer <gri@golang.org> Run-TryBot: Robert Griesemer <gri@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
124 lines
2.8 KiB
Go
124 lines
2.8 KiB
Go
// run -gcflags=-G=3
|
|
|
|
// 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.
|
|
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"strconv"
|
|
)
|
|
|
|
// Various implementations of fromStrings().
|
|
|
|
type Setter[B any] interface {
|
|
Set(string)
|
|
~*B
|
|
}
|
|
|
|
// Takes two type parameters where PT = *T
|
|
func fromStrings1[T any, PT Setter[T]](s []string) []T {
|
|
result := make([]T, len(s))
|
|
for i, v := range s {
|
|
// The type of &result[i] is *T which is in the type list
|
|
// of Setter, so we can convert it to PT.
|
|
p := PT(&result[i])
|
|
// PT has a Set method.
|
|
p.Set(v)
|
|
}
|
|
return result
|
|
}
|
|
|
|
func fromStrings1a[T any, PT Setter[T]](s []string) []PT {
|
|
result := make([]PT, len(s))
|
|
for i, v := range s {
|
|
// The type new(T) is *T which is in the type list
|
|
// of Setter, so we can convert it to PT.
|
|
result[i] = PT(new(T))
|
|
p := result[i]
|
|
// PT has a Set method.
|
|
p.Set(v)
|
|
}
|
|
return result
|
|
}
|
|
|
|
// Takes one type parameter and a set function
|
|
func fromStrings2[T any](s []string, set func(*T, string)) []T {
|
|
results := make([]T, len(s))
|
|
for i, v := range s {
|
|
set(&results[i], v)
|
|
}
|
|
return results
|
|
}
|
|
|
|
type Setter2 interface {
|
|
Set(string)
|
|
}
|
|
|
|
// Takes only one type parameter, but causes a panic (see below)
|
|
func fromStrings3[T Setter2](s []string) []T {
|
|
results := make([]T, len(s))
|
|
for i, v := range s {
|
|
// Panics if T is a pointer type because receiver is T(nil).
|
|
results[i].Set(v)
|
|
}
|
|
return results
|
|
}
|
|
|
|
// Two concrete types with the appropriate Set method.
|
|
|
|
type SettableInt int
|
|
|
|
func (p *SettableInt) Set(s string) {
|
|
i, err := strconv.Atoi(s)
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
*p = SettableInt(i)
|
|
}
|
|
|
|
type SettableString struct {
|
|
s string
|
|
}
|
|
|
|
func (x *SettableString) Set(s string) {
|
|
x.s = s
|
|
}
|
|
|
|
func main() {
|
|
s := fromStrings1[SettableInt, *SettableInt]([]string{"1"})
|
|
if len(s) != 1 || s[0] != 1 {
|
|
panic(fmt.Sprintf("got %v, want %v", s, []int{1}))
|
|
}
|
|
|
|
s2 := fromStrings1a[SettableInt, *SettableInt]([]string{"1"})
|
|
if len(s2) != 1 || *s2[0] != 1 {
|
|
x := 1
|
|
panic(fmt.Sprintf("got %v, want %v", s2, []*int{&x}))
|
|
}
|
|
|
|
// Test out constraint type inference, which should determine that the second
|
|
// type param is *SettableString.
|
|
ps := fromStrings1[SettableString]([]string{"x", "y"})
|
|
if len(ps) != 2 || ps[0] != (SettableString{"x"}) || ps[1] != (SettableString{"y"}) {
|
|
panic(s)
|
|
}
|
|
|
|
s = fromStrings2([]string{"1"}, func(p *SettableInt, s string) { p.Set(s) })
|
|
if len(s) != 1 || s[0] != 1 {
|
|
panic(fmt.Sprintf("got %v, want %v", s, []int{1}))
|
|
}
|
|
|
|
defer func() {
|
|
if recover() == nil {
|
|
panic("did not panic as expected")
|
|
}
|
|
}()
|
|
// This should type check but should panic at run time,
|
|
// because it will make a slice of *SettableInt and then call
|
|
// Set on a nil value.
|
|
fromStrings3[*SettableInt]([]string{"1"})
|
|
}
|