diff --git a/src/cmd/go2go/go2go_test.go b/src/cmd/go2go/go2go_test.go index eb8179ecee..a4177dcab8 100644 --- a/src/cmd/go2go/go2go_test.go +++ b/src/cmd/go2go/go2go_test.go @@ -109,7 +109,7 @@ func TestGO2PATH(t *testing.T) { for _, dir := range dirs { t.Run(dir, func(t *testing.T) { - cmd := exec.Command(testGo2go, "test") + cmd := exec.Command(testGo2go, "-brackets", "test") cmd.Dir = filepath.Join(testTempDir, "testdata", "go2path", "src", dir) cmd.Env = append(os.Environ(), "GO2PATH="+filepath.Join(testTempDir, "testdata", "go2path")) t.Logf("running [%s test] in %s", testGo2go, cmd.Dir) diff --git a/src/cmd/go2go/testdata/go2path/src/alg/alg.go2 b/src/cmd/go2go/testdata/go2path/src/alg/alg.go2 index 3d1b420f60..52020bf16b 100644 --- a/src/cmd/go2go/testdata/go2path/src/alg/alg.go2 +++ b/src/cmd/go2go/testdata/go2path/src/alg/alg.go2 @@ -8,7 +8,7 @@ package alg import "constraints" // Max returns the maximum of two values of some ordered type. -func Max(type T constraints.Ordered)(a, b T) T { +func Max[type T constraints.Ordered](a, b T) T { if a < b { return b } @@ -16,7 +16,7 @@ func Max(type T constraints.Ordered)(a, b T) T { } // Min returns the minimum of two values of some ordered type. -func Min(type T constraints.Ordered)(a, b T) T { +func Min[type T constraints.Ordered](a, b T) T { if a < b { return a } diff --git a/src/cmd/go2go/testdata/go2path/src/chans/chans.go2 b/src/cmd/go2go/testdata/go2path/src/chans/chans.go2 index d990670ede..d7f36bca5c 100644 --- a/src/cmd/go2go/testdata/go2path/src/chans/chans.go2 +++ b/src/cmd/go2go/testdata/go2path/src/chans/chans.go2 @@ -12,7 +12,7 @@ import ( // ReadAll reads from c until the channel is closed or the context is // canceled, returning all the values read. -func ReadAll(type Elem)(ctx context.Context, c <-chan Elem) []Elem { +func ReadAll[type Elem](ctx context.Context, c <-chan Elem) []Elem { var r []Elem for { select { @@ -30,7 +30,7 @@ func ReadAll(type Elem)(ctx context.Context, c <-chan Elem) []Elem { // Merge merges two channels into a single channel. // This will leave a goroutine running until either both channels are closed // or the context is canceled, at which point the returned channel is closed. -func Merge(type Elem)(ctx context.Context, c1, c2 <-chan Elem) <-chan Elem { +func Merge[type Elem](ctx context.Context, c1, c2 <-chan Elem) <-chan Elem { r := make(chan Elem) go func(ctx context.Context, c1, c2 <-chan Elem, r chan<- Elem) { defer close(r) @@ -60,7 +60,7 @@ func Merge(type Elem)(ctx context.Context, c1, c2 <-chan Elem) <-chan Elem { // is sent on the returned channel. This will leave a goroutine running // until c is closed or the context is canceled, at which point the // returned channel is closed. -func Filter(type Elem)(ctx context.Context, c <-chan Elem, f func(Elem) bool) <-chan Elem { +func Filter[type Elem](ctx context.Context, c <-chan Elem, f func(Elem) bool) <-chan Elem { r := make(chan Elem) go func(ctx context.Context, c <-chan Elem, f func(Elem) bool, r chan<- Elem) { defer close(r) @@ -84,7 +84,7 @@ func Filter(type Elem)(ctx context.Context, c <-chan Elem, f func(Elem) bool) <- // Sink returns a channel that discards all values sent to it. // This will leave a goroutine running until the context is canceled // or the returned channel is closed. -func Sink(type Elem)(ctx context.Context) chan<- Elem { +func Sink[type Elem](ctx context.Context) chan<- Elem { r := make(chan Elem) go func(ctx context.Context, r <-chan Elem) { for { @@ -103,13 +103,13 @@ func Sink(type Elem)(ctx context.Context) chan<- Elem { // An Exclusive is a value that may only be used by a single goroutine // at a time. This is implemented using channels rather than a mutex. -type Exclusive(type Val) struct { +type Exclusive[type Val] struct { c chan Val } // MakeExclusive makes an initialized exclusive value. -func MakeExclusive(type Val)(initial Val) *Exclusive(Val) { - r := &Exclusive(Val){ +func MakeExclusive[type Val](initial Val) *Exclusive[Val] { + r := &Exclusive[Val]{ c: make(chan Val, 1), } r.c <- initial @@ -118,14 +118,14 @@ func MakeExclusive(type Val)(initial Val) *Exclusive(Val) { // Acquire acquires the exclusive value for private use. // It must be released using the Release method. -func (e *Exclusive(Val)) Acquire() Val { +func (e *Exclusive[Val]) Acquire() Val { return <-e.c } // TryAcquire attempts to acquire the value. The ok result reports whether // the value was acquired. If the value is acquired, it must be released // using the Release method. -func (e *Exclusive(Val)) TryAcquire() (v Val, ok bool) { +func (e *Exclusive[Val]) TryAcquire() (v Val, ok bool) { select { case r := <-e.c: return r, true @@ -136,7 +136,7 @@ func (e *Exclusive(Val)) TryAcquire() (v Val, ok bool) { // Release updates and releases the value. // This method panics if the value has not been acquired. -func (e *Exclusive(Val)) Release(v Val) { +func (e *Exclusive[Val]) Release(v Val) { select { case e.c <- v: default: @@ -152,23 +152,23 @@ func (e *Exclusive(Val)) Release(v Val) { // // This is a convenient way to exit a goroutine sending values when // the receiver stops reading them. -func Ranger(type Elem)() (*Sender(Elem), *Receiver(Elem)) { +func Ranger[type Elem]() (*Sender[Elem], *Receiver[Elem]) { c := make(chan Elem) d := make(chan struct{}) - s := &Sender(Elem){ + s := &Sender[Elem]{ values: c, done: d, } - r := &Receiver(Elem) { + r := &Receiver[Elem] { values: c, done: d, } - runtime.SetFinalizer(r, (*Receiver(Elem)).finalize) + runtime.SetFinalizer(r, (*Receiver[Elem]).finalize) return s, r } // A Sender is used to send values to a Receiver. -type Sender(type Elem) struct { +type Sender[type Elem] struct { values chan<- Elem done <-chan struct{} } @@ -176,7 +176,7 @@ type Sender(type Elem) struct { // Send sends a value to the receiver. It reports whether the value was sent. // The value will not be sent if the context is closed or the receiver // is freed. -func (s *Sender(Elem)) Send(ctx context.Context, v Elem) bool { +func (s *Sender[Elem]) Send(ctx context.Context, v Elem) bool { select { case <-ctx.Done(): return false @@ -189,19 +189,19 @@ func (s *Sender(Elem)) Send(ctx context.Context, v Elem) bool { // Close tells the receiver that no more values will arrive. // After Close is called, the Sender may no longer be used. -func (s *Sender(Elem)) Close() { +func (s *Sender[Elem]) Close() { close(s.values) } // A Receiver receives values from a Sender. -type Receiver(type Elem) struct { +type Receiver[type Elem] struct { values <-chan Elem done chan<- struct{} } // Next returns the next value from the channel. The bool result indicates // whether the value is valid. -func (r *Receiver(Elem)) Next(ctx context.Context) (v Elem, ok bool) { +func (r *Receiver[Elem]) Next(ctx context.Context) (v Elem, ok bool) { select { case <-ctx.Done(): case v, ok = <-r.values: @@ -210,6 +210,6 @@ func (r *Receiver(Elem)) Next(ctx context.Context) (v Elem, ok bool) { } // finalize is a finalizer for the receiver. -func (r *Receiver(Elem)) finalize() { +func (r *Receiver[Elem]) finalize() { close(r.done) } diff --git a/src/cmd/go2go/testdata/go2path/src/graph/graph.go2 b/src/cmd/go2go/testdata/go2path/src/graph/graph.go2 index 2102819c1b..90c6683308 100644 --- a/src/cmd/go2go/testdata/go2path/src/graph/graph.go2 +++ b/src/cmd/go2go/testdata/go2path/src/graph/graph.go2 @@ -10,31 +10,31 @@ import "errors" // A Graph is a collection of nodes. A node may have an arbitrary number // of edges. An edge connects two nodes. Both nodes and edges must be // comparable. This is an undirected simple graph. -type Graph(type Node NodeC(Edge), Edge EdgeC(Node)) struct { +type Graph[type Node NodeC[Edge], Edge EdgeC[Node]] struct { nodes []Node } // NodeC is the contraints on a node in a graph, given the Edge type. -type NodeC(type Edge) interface { +type NodeC[type Edge] interface { comparable Edges() []Edge } // Edgec is the constraints on an edge in a graph, given the Node type. -type EdgeC(type Node) interface { +type EdgeC[type Node] interface { comparable Nodes() (a, b Node) } // New creates a new Graph from a collection of Nodes. -func New(type Node NodeC(Edge), Edge EdgeC(Node))(nodes []Node) *Graph(Node, Edge) { - return &Graph(Node, Edge){nodes: nodes} +func New[type Node NodeC[Edge], Edge EdgeC[Node]](nodes []Node) *Graph[Node, Edge] { + return &Graph[Node, Edge]{nodes: nodes} } // nodePath holds the path to a node during ShortestPath. // This should ideally be a type defined inside ShortestPath, // but the translator tool doesn't support that. -type nodePath(type Node NodeC(Edge), Edge EdgeC(Node)) struct { +type nodePath[type Node NodeC[Edge], Edge EdgeC[Node]] struct { node Node path []Edge } @@ -42,10 +42,10 @@ type nodePath(type Node NodeC(Edge), Edge EdgeC(Node)) struct { // ShortestPath returns the shortest path between two nodes, // as an ordered list of edges. If there are multiple shortest paths, // which one is returned is unpredictable. -func (g *Graph(Node, Edge)) ShortestPath(from, to Node) ([]Edge, error) { +func (g *Graph[Node, Edge]) ShortestPath(from, to Node) ([]Edge, error) { visited := make(map[Node]bool) visited[from] = true - workqueue := [](nodePath(Node, Edge)){nodePath(Node, Edge){from, nil}} + workqueue := []nodePath[Node, Edge]{nodePath[Node, Edge]{from, nil}} for len(workqueue) > 0 { current := workqueue workqueue = nil @@ -62,7 +62,7 @@ func (g *Graph(Node, Edge)) ShortestPath(from, to Node) ([]Edge, error) { if a == to { return ve, nil } - workqueue = append(workqueue, nodePath(Node, Edge){a, ve}) + workqueue = append(workqueue, nodePath[Node, Edge]{a, ve}) visited[a] = true } } @@ -74,29 +74,29 @@ func (g *Graph(Node, Edge)) ShortestPath(from, to Node) ([]Edge, error) { // GraphP is a version of Graph that uses pointers. This is for testing. // I'm not sure which approach will be better in practice, or whether // this indicates a problem with the draft design. -type GraphP(type *Node NodeCP(Edge), *Edge EdgeCP(Node)) struct { +type GraphP[type *Node NodeCP[Edge], *Edge EdgeCP[Node]] struct { nodes []*Node } // NodeCP is the contraint on a Node in a GraphP. -type NodeCP(type Edge) interface { +type NodeCP[type Edge] interface { Edges() []*Edge } // EdgeCP is the contraint on an Edge in a GraphP. -type EdgeCP(type Node) interface { +type EdgeCP[type Node] interface { Nodes() (a, b *Node) } // NewP creates a new GraphP from a collection of Nodes. -func NewP(type *Node NodeCP(Edge), *Edge EdgeCP(Node))(nodes []*Node) *GraphP(Node, Edge) { - return &GraphP(Node, Edge){nodes: nodes} +func NewP[type *Node NodeCP[Edge], *Edge EdgeCP[Node]](nodes []*Node) *GraphP[Node, Edge] { + return &GraphP[Node, Edge]{nodes: nodes} } // nodePathP holds the path to a node during ShortestPath. // This should ideally be a type defined inside ShortestPath, // but the translator tool doesn't support that. -type nodePathP(type *Node NodeCP(Edge), *Edge EdgeCP(Node)) struct { +type nodePathP[type *Node NodeCP[Edge], *Edge EdgeCP[Node]] struct { node *Node path []*Edge } @@ -104,10 +104,10 @@ type nodePathP(type *Node NodeCP(Edge), *Edge EdgeCP(Node)) struct { // ShortestPath returns the shortest path between two nodes, // as an ordered list of edges. If there are multiple shortest paths, // which one is returned is unpredictable. -func (g *GraphP(Node, Edge)) ShortestPath(from, to *Node) ([]*Edge, error) { +func (g *GraphP[Node, Edge]) ShortestPath(from, to *Node) ([]*Edge, error) { visited := make(map[*Node]bool) visited[from] = true - workqueue := [](nodePathP(Node, Edge)){nodePathP(Node, Edge){from, nil}} + workqueue := [](nodePathP[Node, Edge]){nodePathP[Node, Edge]{from, nil}} for len(workqueue) > 0 { current := workqueue workqueue = nil @@ -124,7 +124,7 @@ func (g *GraphP(Node, Edge)) ShortestPath(from, to *Node) ([]*Edge, error) { if a == to { return ve, nil } - workqueue = append(workqueue, nodePathP(Node, Edge){a, ve}) + workqueue = append(workqueue, nodePathP[Node, Edge]{a, ve}) visited[a] = true } } diff --git a/src/cmd/go2go/testdata/go2path/src/graph/graph_test.go2 b/src/cmd/go2go/testdata/go2path/src/graph/graph_test.go2 index 572d3ebb91..3b8dd5d5b3 100644 --- a/src/cmd/go2go/testdata/go2path/src/graph/graph_test.go2 +++ b/src/cmd/go2go/testdata/go2path/src/graph/graph_test.go2 @@ -127,7 +127,7 @@ func TestShortestPath(t *testing.T) { mridx.index = idx nodes = append(nodes, mridx) } - g := New(mazeRoom, mazeEdge)(nodes) + g := New[mazeRoom, mazeEdge](nodes) path, err := g.ShortestPath(zork[11], zork[30]) if err != nil { t.Fatal(err) @@ -195,7 +195,7 @@ func TestShortestPathP(t *testing.T) { stop = mr } } - g := NewP(mazeRoomP, mazeEdgeP)(nodes) + g := NewP[mazeRoomP, mazeEdgeP](nodes) path, err := g.ShortestPath(start, stop) if err != nil { t.Fatal(err) diff --git a/src/cmd/go2go/testdata/go2path/src/gsort/gsort.go2 b/src/cmd/go2go/testdata/go2path/src/gsort/gsort.go2 index 3558f194fa..2c54e9d1d8 100644 --- a/src/cmd/go2go/testdata/go2path/src/gsort/gsort.go2 +++ b/src/cmd/go2go/testdata/go2path/src/gsort/gsort.go2 @@ -12,12 +12,12 @@ import ( ) // orderedSlice is a slice of values of some ordered type. -type orderedSlice(type Elem constraints.Ordered) []Elem +type orderedSlice[type Elem constraints.Ordered] []Elem // orderedSlice implements sort.Interface. -func (s orderedSlice(Elem)) Len() int { return len(s) } -func (s orderedSlice(Elem)) Less(i, j int) bool { +func (s orderedSlice[Elem]) Len() int { return len(s) } +func (s orderedSlice[Elem]) Less(i, j int) bool { if s[i] < s[j] { return true } @@ -27,25 +27,25 @@ func (s orderedSlice(Elem)) Less(i, j int) bool { } return false } -func (s orderedSlice(Elem)) Swap(i, j int) { s[i], s[j] = s[j], s[i] } +func (s orderedSlice[Elem]) Swap(i, j int) { s[i], s[j] = s[j], s[i] } // OrderedSlice sorts a slice of any ordered type in ascending order. -func OrderedSlice(type Elem constraints.Ordered)(s []Elem) { - sort.Sort(orderedSlice(Elem)(s)) +func OrderedSlice[type Elem constraints.Ordered](s []Elem) { + sort.Sort(orderedSlice[Elem](s)) } // sliceFn implements sort.Interface for a slice of any type with an // explicit less-than function. -type sliceFn(type Elem) struct { +type sliceFn[type Elem] struct { s []Elem less func(Elem, Elem) bool } -func (s sliceFn(Elem)) Len() int { return len(s.s) } -func (s sliceFn(Elem)) Less(i, j int) bool { return s.less(s.s[i], s.s[j]) } -func (s sliceFn(Elem)) Swap(i, j int) { s.s[i], s.s[j] = s.s[j], s.s[i] } +func (s sliceFn[Elem]) Len() int { return len(s.s) } +func (s sliceFn[Elem]) Less(i, j int) bool { return s.less(s.s[i], s.s[j]) } +func (s sliceFn[Elem]) Swap(i, j int) { s.s[i], s.s[j] = s.s[j], s.s[i] } // SliceFn sorts a slice of any type according to a less-than function. -func SliceFn(type Elem)(s []Elem, less func(Elem, Elem) bool) { - sort.Sort(sliceFn(Elem){s, less}) +func SliceFn[type Elem](s []Elem, less func(Elem, Elem) bool) { + sort.Sort(sliceFn[Elem]{s, less}) } diff --git a/src/cmd/go2go/testdata/go2path/src/gsort/gsort_test.go2 b/src/cmd/go2go/testdata/go2path/src/gsort/gsort_test.go2 index 9be9fa9e45..eb69893f1f 100644 --- a/src/cmd/go2go/testdata/go2path/src/gsort/gsort_test.go2 +++ b/src/cmd/go2go/testdata/go2path/src/gsort/gsort_test.go2 @@ -31,7 +31,7 @@ func TestSortOrderedStrings(t *testing.T) { testOrdered(t, strs, sort.Strings) } -func testOrdered(type Elem constraints.Ordered)(t *testing.T, s []Elem, sorter func([]Elem)) { +func testOrdered[type Elem constraints.Ordered](t *testing.T, s []Elem, sorter func([]Elem)) { s1 := make([]Elem, len(s)) copy(s1, s) s2 := make([]Elem, len(s)) diff --git a/src/cmd/go2go/testdata/go2path/src/list/list.go2 b/src/cmd/go2go/testdata/go2path/src/list/list.go2 index 777968904b..aa466a2792 100644 --- a/src/cmd/go2go/testdata/go2path/src/list/list.go2 +++ b/src/cmd/go2go/testdata/go2path/src/list/list.go2 @@ -9,23 +9,23 @@ package list // perhaps with different type names. // Element is an element of a linked list. -type Element(type TElem) struct { +type Element[type TElem] struct { // Next and previous pointers in the doubly-linked list of elements. // To simplify the implementation, internally a list l is implemented // as a ring, such that &l.root is both the next element of the last // list element (l.Back()) and the previous element of the first list // element (l.Front()). - next, prev *Element(TElem) + next, prev *Element[TElem] // The list to which this element belongs. - list *List(TElem) + list *List[TElem] // The value stored with this element. Value TElem } // Next returns the next list element or nil. -func (e *Element(TElem)) Next() *Element(TElem) { +func (e *Element[TElem]) Next() *Element[TElem] { if p := e.next; e.list != nil && p != &e.list.root { return p } @@ -33,7 +33,7 @@ func (e *Element(TElem)) Next() *Element(TElem) { } // Prev returns the previous list element or nil. -func (e *Element(TElem)) Prev() *Element(TElem) { +func (e *Element[TElem]) Prev() *Element[TElem] { if p := e.prev; e.list != nil && p != &e.list.root { return p } @@ -42,13 +42,13 @@ func (e *Element(TElem)) Prev() *Element(TElem) { // List represents a doubly linked list. // The zero value for List is an empty list ready to use. -type List(type TElem) struct { - root Element(TElem) // sentinel list element, only &root, root.prev, and root.next are used +type List[type TElem] struct { + root Element[TElem] // sentinel list element, only &root, root.prev, and root.next are used len int // current list length excluding (this) sentinel element } // Init initializes or clears list l. -func (l *List(TElem)) Init() *List(TElem) { +func (l *List[TElem]) Init() *List[TElem] { l.root.next = &l.root l.root.prev = &l.root l.len = 0 @@ -56,14 +56,14 @@ func (l *List(TElem)) Init() *List(TElem) { } // New returns an initialized list. -func New(type TElem)() *List(TElem) { return new(List(TElem)).Init() } +func New[type TElem]() *List[TElem] { return new(List[TElem]).Init() } // Len returns the number of elements of list l. // The complexity is O(1). -func (l *List(TElem)) Len() int { return l.len } +func (l *List[TElem]) Len() int { return l.len } // Front returns the first element of list l or nil if the list is empty. -func (l *List(TElem)) Front() *Element(TElem) { +func (l *List[TElem]) Front() *Element[TElem] { if l.len == 0 { return nil } @@ -71,7 +71,7 @@ func (l *List(TElem)) Front() *Element(TElem) { } // Back returns the last element of list l or nil if the list is empty. -func (l *List(TElem)) Back() *Element(TElem) { +func (l *List[TElem]) Back() *Element[TElem] { if l.len == 0 { return nil } @@ -79,14 +79,14 @@ func (l *List(TElem)) Back() *Element(TElem) { } // lazyInit lazily initializes a zero List value. -func (l *List(TElem)) lazyInit() { +func (l *List[TElem]) lazyInit() { if l.root.next == nil { l.Init() } } // insert inserts e after at, increments l.len, and returns e. -func (l *List(TElem)) insert(e, at *Element(TElem)) *Element(TElem) { +func (l *List[TElem]) insert(e, at *Element[TElem]) *Element[TElem] { e.prev = at e.next = at.next e.prev.next = e @@ -96,13 +96,13 @@ func (l *List(TElem)) insert(e, at *Element(TElem)) *Element(TElem) { return e } -// insertValue is a convenience wrapper for insert(&Element(TElem){Value: v}, at). -func (l *List(TElem)) insertValue(v TElem, at *Element(TElem)) *Element(TElem) { - return l.insert(&Element(TElem){Value: v}, at) +// insertValue is a convenience wrapper for insert(&Element[TElem]{Value: v}, at). +func (l *List[TElem]) insertValue(v TElem, at *Element[TElem]) *Element[TElem] { + return l.insert(&Element[TElem]{Value: v}, at) } // remove removes e from its list, decrements l.len, and returns e. -func (l *List(TElem)) remove(e *Element(TElem)) *Element(TElem) { +func (l *List[TElem]) remove(e *Element[TElem]) *Element[TElem] { e.prev.next = e.next e.next.prev = e.prev e.next = nil // avoid memory leaks @@ -113,7 +113,7 @@ func (l *List(TElem)) remove(e *Element(TElem)) *Element(TElem) { } // move moves e to next to at and returns e. -func (l *List(TElem)) move(e, at *Element(TElem)) *Element(TElem) { +func (l *List[TElem]) move(e, at *Element[TElem]) *Element[TElem] { if e == at { return e } @@ -131,7 +131,7 @@ func (l *List(TElem)) move(e, at *Element(TElem)) *Element(TElem) { // Remove removes e from l if e is an element of list l. // It returns the element value e.Value. // The element must not be nil. -func (l *List(TElem)) Remove(e *Element(TElem)) TElem { +func (l *List[TElem]) Remove(e *Element[TElem]) TElem { if e.list == l { // if e.list == l, l must have been initialized when e was inserted // in l or l == nil (e is a zero Element) and l.remove will crash @@ -141,13 +141,13 @@ func (l *List(TElem)) Remove(e *Element(TElem)) TElem { } // PushFront inserts a new element e with value v at the front of list l and returns e. -func (l *List(TElem)) PushFront(v TElem) *Element(TElem) { +func (l *List[TElem]) PushFront(v TElem) *Element[TElem] { l.lazyInit() return l.insertValue(v, &l.root) } // PushBack inserts a new element e with value v at the back of list l and returns e. -func (l *List(TElem)) PushBack(v TElem) *Element(TElem) { +func (l *List[TElem]) PushBack(v TElem) *Element[TElem] { l.lazyInit() return l.insertValue(v, l.root.prev) } @@ -155,7 +155,7 @@ func (l *List(TElem)) PushBack(v TElem) *Element(TElem) { // InsertBefore inserts a new element e with value v immediately before mark and returns e. // If mark is not an element of l, the list is not modified. // The mark must not be nil. -func (l *List(TElem)) InsertBefore(v TElem, mark *Element(TElem)) *Element(TElem) { +func (l *List[TElem]) InsertBefore(v TElem, mark *Element[TElem]) *Element[TElem] { if mark.list != l { return nil } @@ -166,7 +166,7 @@ func (l *List(TElem)) InsertBefore(v TElem, mark *Element(TElem)) *Element(TElem // InsertAfter inserts a new element e with value v immediately after mark and returns e. // If mark is not an element of l, the list is not modified. // The mark must not be nil. -func (l *List(TElem)) InsertAfter(v TElem, mark *Element(TElem)) *Element(TElem) { +func (l *List[TElem]) InsertAfter(v TElem, mark *Element[TElem]) *Element[TElem] { if mark.list != l { return nil } @@ -177,7 +177,7 @@ func (l *List(TElem)) InsertAfter(v TElem, mark *Element(TElem)) *Element(TElem) // MoveToFront moves element e to the front of list l. // If e is not an element of l, the list is not modified. // The element must not be nil. -func (l *List(TElem)) MoveToFront(e *Element(TElem)) { +func (l *List[TElem]) MoveToFront(e *Element[TElem]) { if e.list != l || l.root.next == e { return } @@ -188,7 +188,7 @@ func (l *List(TElem)) MoveToFront(e *Element(TElem)) { // MoveToBack moves element e to the back of list l. // If e is not an element of l, the list is not modified. // The element must not be nil. -func (l *List(TElem)) MoveToBack(e *Element(TElem)) { +func (l *List[TElem]) MoveToBack(e *Element[TElem]) { if e.list != l || l.root.prev == e { return } @@ -199,7 +199,7 @@ func (l *List(TElem)) MoveToBack(e *Element(TElem)) { // MoveBefore moves element e to its new position before mark. // If e or mark is not an element of l, or e == mark, the list is not modified. // The element and mark must not be nil. -func (l *List(TElem)) MoveBefore(e, mark *Element(TElem)) { +func (l *List[TElem]) MoveBefore(e, mark *Element[TElem]) { if e.list != l || e == mark || mark.list != l { return } @@ -209,7 +209,7 @@ func (l *List(TElem)) MoveBefore(e, mark *Element(TElem)) { // MoveAfter moves element e to its new position after mark. // If e or mark is not an element of l, or e == mark, the list is not modified. // The element and mark must not be nil. -func (l *List(TElem)) MoveAfter(e, mark *Element(TElem)) { +func (l *List[TElem]) MoveAfter(e, mark *Element[TElem]) { if e.list != l || e == mark || mark.list != l { return } @@ -218,7 +218,7 @@ func (l *List(TElem)) MoveAfter(e, mark *Element(TElem)) { // PushBackList inserts a copy of an other list at the back of list l. // The lists l and other may be the same. They must not be nil. -func (l *List(TElem)) PushBackList(other *List(TElem)) { +func (l *List[TElem]) PushBackList(other *List[TElem]) { l.lazyInit() for i, e := other.Len(), other.Front(); i > 0; i, e = i-1, e.Next() { l.insertValue(e.Value, l.root.prev) @@ -227,7 +227,7 @@ func (l *List(TElem)) PushBackList(other *List(TElem)) { // PushFrontList inserts a copy of an other list at the front of list l. // The lists l and other may be the same. They must not be nil. -func (l *List(TElem)) PushFrontList(other *List(TElem)) { +func (l *List[TElem]) PushFrontList(other *List[TElem]) { l.lazyInit() for i, e := other.Len(), other.Back(); i > 0; i, e = i-1, e.Prev() { l.insertValue(e.Value, &l.root) @@ -235,8 +235,8 @@ func (l *List(TElem)) PushFrontList(other *List(TElem)) { } // Transform runs a transform function on a list returning a new list. -func Transform(type TElem1, TElem2)(lst *List(TElem1), f func(TElem1) TElem2) *List(TElem2) { - ret := New(TElem2)() +func Transform[type TElem1, TElem2](lst *List[TElem1], f func(TElem1) TElem2) *List[TElem2] { + ret := New[TElem2]() for p := lst.Front(); p != nil; p = p.Next() { ret.PushBack(f(p.Value)) } diff --git a/src/cmd/go2go/testdata/go2path/src/list/list_test.go2 b/src/cmd/go2go/testdata/go2path/src/list/list_test.go2 index 675a5bc682..4f91736a1b 100644 --- a/src/cmd/go2go/testdata/go2path/src/list/list_test.go2 +++ b/src/cmd/go2go/testdata/go2path/src/list/list_test.go2 @@ -9,7 +9,7 @@ import ( "testing" ) -func checkListLen(type TElem)(t *testing.T, l *List(TElem), len int) bool { +func checkListLen[type TElem](t *testing.T, l *List[TElem], len int) bool { if n := l.Len(); n != len { t.Errorf("l.Len() = %d, want %d", n, len) return false @@ -17,7 +17,7 @@ func checkListLen(type TElem)(t *testing.T, l *List(TElem), len int) bool { return true } -func checkListPointers(type TElem)(t *testing.T, l *List(TElem), es []*Element(TElem)) { +func checkListPointers[type TElem](t *testing.T, l *List[TElem], es []*Element[TElem]) { root := &l.root if !checkListLen(t, l, len(es)) { @@ -36,7 +36,7 @@ func checkListPointers(type TElem)(t *testing.T, l *List(TElem), es []*Element(T // check internal and external prev/next connections for i, e := range es { prev := root - Prev := (*Element(TElem))(nil) + Prev := (*Element[TElem])(nil) if i > 0 { prev = es[i-1] Prev = prev @@ -49,7 +49,7 @@ func checkListPointers(type TElem)(t *testing.T, l *List(TElem), es []*Element(T } next := root - Next := (*Element(TElem))(nil) + Next := (*Element[TElem])(nil) if i < len(es)-1 { next = es[i+1] Next = next @@ -65,64 +65,64 @@ func checkListPointers(type TElem)(t *testing.T, l *List(TElem), es []*Element(T func TestList(t *testing.T) { l := New(string)() - checkListPointers(t, l, []*(Element(string)){}) + checkListPointers(t, l, []*(Element[string]){}) // Single element list e := l.PushFront("a") - checkListPointers(t, l, []*(Element(string)){e}) + checkListPointers(t, l, []*(Element[string]){e}) l.MoveToFront(e) - checkListPointers(t, l, []*(Element(string)){e}) + checkListPointers(t, l, []*(Element[string]){e}) l.MoveToBack(e) - checkListPointers(t, l, []*(Element(string)){e}) + checkListPointers(t, l, []*(Element[string]){e}) l.Remove(e) - checkListPointers(t, l, []*(Element(string)){}) + checkListPointers(t, l, []*(Element[string]){}) // Bigger list - l2 := New(int)() + l2 := New[int]() e2 := l2.PushFront(2) e1 := l2.PushFront(1) e3 := l2.PushBack(3) e4 := l2.PushBack(600) - checkListPointers(t, l2, []*(Element(int)){e1, e2, e3, e4}) + checkListPointers(t, l2, []*(Element[int]){e1, e2, e3, e4}) l2.Remove(e2) - checkListPointers(t, l2, []*(Element(int)){e1, e3, e4}) + checkListPointers(t, l2, []*(Element[int]){e1, e3, e4}) l2.MoveToFront(e3) // move from middle - checkListPointers(t, l2, []*(Element(int)){e3, e1, e4}) + checkListPointers(t, l2, []*(Element[int]){e3, e1, e4}) l2.MoveToFront(e1) l2.MoveToBack(e3) // move from middle - checkListPointers(t, l2, []*(Element(int)){e1, e4, e3}) + checkListPointers(t, l2, []*(Element[int]){e1, e4, e3}) l2.MoveToFront(e3) // move from back - checkListPointers(t, l2, []*(Element(int)){e3, e1, e4}) + checkListPointers(t, l2, []*(Element[int]){e3, e1, e4}) l2.MoveToFront(e3) // should be no-op - checkListPointers(t, l2, []*(Element(int)){e3, e1, e4}) + checkListPointers(t, l2, []*(Element[int]){e3, e1, e4}) l2.MoveToBack(e3) // move from front - checkListPointers(t, l2, []*(Element(int)){e1, e4, e3}) + checkListPointers(t, l2, []*(Element[int]){e1, e4, e3}) l2.MoveToBack(e3) // should be no-op - checkListPointers(t, l2, []*(Element(int)){e1, e4, e3}) + checkListPointers(t, l2, []*(Element[int]){e1, e4, e3}) e2 = l2.InsertBefore(2, e1) // insert before front - checkListPointers(t, l2, []*(Element(int)){e2, e1, e4, e3}) + checkListPointers(t, l2, []*(Element[int]){e2, e1, e4, e3}) l2.Remove(e2) e2 = l2.InsertBefore(2, e4) // insert before middle - checkListPointers(t, l2, []*(Element(int)){e1, e2, e4, e3}) + checkListPointers(t, l2, []*(Element[int]){e1, e2, e4, e3}) l2.Remove(e2) e2 = l2.InsertBefore(2, e3) // insert before back - checkListPointers(t, l2, []*(Element(int)){e1, e4, e2, e3}) + checkListPointers(t, l2, []*(Element[int]){e1, e4, e2, e3}) l2.Remove(e2) e2 = l2.InsertAfter(2, e1) // insert after front - checkListPointers(t, l2, []*(Element(int)){e1, e2, e4, e3}) + checkListPointers(t, l2, []*(Element[int]){e1, e2, e4, e3}) l2.Remove(e2) e2 = l2.InsertAfter(2, e4) // insert after middle - checkListPointers(t, l2, []*(Element(int)){e1, e4, e2, e3}) + checkListPointers(t, l2, []*(Element[int]){e1, e4, e2, e3}) l2.Remove(e2) e2 = l2.InsertAfter(2, e3) // insert after back - checkListPointers(t, l2, []*(Element(int)){e1, e4, e3, e2}) + checkListPointers(t, l2, []*(Element[int]){e1, e4, e3, e2}) l2.Remove(e2) // Check standard iteration. @@ -135,15 +135,15 @@ func TestList(t *testing.T) { } // Clear all elements by iterating - var next *Element(int) + var next *Element[int] for e := l2.Front(); e != nil; e = next { next = e.Next() l2.Remove(e) } - checkListPointers(t, l2, []*(Element(int)){}) + checkListPointers(t, l2, []*(Element[int]){}) } -func checkList(type TElem comparable)(t *testing.T, l *List(TElem), es []interface{}) { +func checkList[type TElem comparable](t *testing.T, l *List[TElem], es []interface{}) { if !checkListLen(t, l, len(es)) { return } @@ -159,8 +159,8 @@ func checkList(type TElem comparable)(t *testing.T, l *List(TElem), es []interfa } func TestExtending(t *testing.T) { - l1 := New(int)() - l2 := New(int)() + l1 := New[int]() + l2 := New[int]() l1.PushBack(1) l1.PushBack(2) @@ -169,13 +169,13 @@ func TestExtending(t *testing.T) { l2.PushBack(4) l2.PushBack(5) - l3 := New(int)() + l3 := New[int]() l3.PushBackList(l1) checkList(t, l3, []interface{}{1, 2, 3}) l3.PushBackList(l2) checkList(t, l3, []interface{}{1, 2, 3, 4, 5}) - l3 = New(int)() + l3 = New[int]() l3.PushFrontList(l2) checkList(t, l3, []interface{}{4, 5}) l3.PushFrontList(l1) @@ -184,19 +184,19 @@ func TestExtending(t *testing.T) { checkList(t, l1, []interface{}{1, 2, 3}) checkList(t, l2, []interface{}{4, 5}) - l3 = New(int)() + l3 = New[int]() l3.PushBackList(l1) checkList(t, l3, []interface{}{1, 2, 3}) l3.PushBackList(l3) checkList(t, l3, []interface{}{1, 2, 3, 1, 2, 3}) - l3 = New(int)() + l3 = New[int]() l3.PushFrontList(l1) checkList(t, l3, []interface{}{1, 2, 3}) l3.PushFrontList(l3) checkList(t, l3, []interface{}{1, 2, 3, 1, 2, 3}) - l3 = New(int)() + l3 = New[int]() l1.PushBackList(l3) checkList(t, l1, []interface{}{1, 2, 3}) l1.PushFrontList(l3) @@ -204,23 +204,23 @@ func TestExtending(t *testing.T) { } func TestRemove(t *testing.T) { - l := New(int)() + l := New[int]() e1 := l.PushBack(1) e2 := l.PushBack(2) - checkListPointers(t, l, []*(Element(int)){e1, e2}) + checkListPointers(t, l, []*(Element[int]){e1, e2}) e := l.Front() l.Remove(e) - checkListPointers(t, l, []*(Element(int)){e2}) + checkListPointers(t, l, []*(Element[int]){e2}) l.Remove(e) - checkListPointers(t, l, []*(Element(int)){e2}) + checkListPointers(t, l, []*(Element[int]){e2}) } func TestIssue4103(t *testing.T) { - l1 := New(int)() + l1 := New[int]() l1.PushBack(1) l1.PushBack(2) - l2 := New(int)() + l2 := New[int]() l2.PushBack(3) l2.PushBack(4) @@ -237,7 +237,7 @@ func TestIssue4103(t *testing.T) { } func TestIssue6349(t *testing.T) { - l := New(int)() + l := New[int]() l.PushBack(1) l.PushBack(2) @@ -255,84 +255,84 @@ func TestIssue6349(t *testing.T) { } func TestMove(t *testing.T) { - l := New(int)() + l := New[int]() e1 := l.PushBack(1) e2 := l.PushBack(2) e3 := l.PushBack(3) e4 := l.PushBack(4) l.MoveAfter(e3, e3) - checkListPointers(t, l, []*(Element(int)){e1, e2, e3, e4}) + checkListPointers(t, l, []*(Element[int]){e1, e2, e3, e4}) l.MoveBefore(e2, e2) - checkListPointers(t, l, []*(Element(int)){e1, e2, e3, e4}) + checkListPointers(t, l, []*(Element[int]){e1, e2, e3, e4}) l.MoveAfter(e3, e2) - checkListPointers(t, l, []*(Element(int)){e1, e2, e3, e4}) + checkListPointers(t, l, []*(Element[int]){e1, e2, e3, e4}) l.MoveBefore(e2, e3) - checkListPointers(t, l, []*(Element(int)){e1, e2, e3, e4}) + checkListPointers(t, l, []*(Element[int]){e1, e2, e3, e4}) l.MoveBefore(e2, e4) - checkListPointers(t, l, []*(Element(int)){e1, e3, e2, e4}) + checkListPointers(t, l, []*(Element[int]){e1, e3, e2, e4}) e2, e3 = e3, e2 l.MoveBefore(e4, e1) - checkListPointers(t, l, []*(Element(int)){e4, e1, e2, e3}) + checkListPointers(t, l, []*(Element[int]){e4, e1, e2, e3}) e1, e2, e3, e4 = e4, e1, e2, e3 l.MoveAfter(e4, e1) - checkListPointers(t, l, []*(Element(int)){e1, e4, e2, e3}) + checkListPointers(t, l, []*(Element[int]){e1, e4, e2, e3}) e2, e3, e4 = e4, e2, e3 l.MoveAfter(e2, e3) - checkListPointers(t, l, []*(Element(int)){e1, e3, e2, e4}) + checkListPointers(t, l, []*(Element[int]){e1, e3, e2, e4}) e2, e3 = e3, e2 } // Test PushFront, PushBack, PushFrontList, PushBackList with uninitialized List func TestZeroList(t *testing.T) { - var l1 = new(List(int)) + var l1 = new(List[int]) l1.PushFront(1) checkList(t, l1, []interface{}{1}) - var l2 = new(List(int)) + var l2 = new(List[int]) l2.PushBack(1) checkList(t, l2, []interface{}{1}) - var l3 = new(List(int)) + var l3 = new(List[int]) l3.PushFrontList(l1) checkList(t, l3, []interface{}{1}) - var l4 = new(List(int)) + var l4 = new(List[int]) l4.PushBackList(l2) checkList(t, l4, []interface{}{1}) } // Test that a list l is not modified when calling InsertBefore with a mark that is not an element of l. func TestInsertBeforeUnknownMark(t *testing.T) { - var l List(int) + var l List[int] l.PushBack(1) l.PushBack(2) l.PushBack(3) - l.InsertBefore(1, new(Element(int))) + l.InsertBefore(1, new(Element[int])) checkList(t, &l, []interface{}{1, 2, 3}) } // Test that a list l is not modified when calling InsertAfter with a mark that is not an element of l. func TestInsertAfterUnknownMark(t *testing.T) { - var l List(int) + var l List[int] l.PushBack(1) l.PushBack(2) l.PushBack(3) - l.InsertAfter(1, new(Element(int))) + l.InsertAfter(1, new(Element[int])) checkList(t, &l, []interface{}{1, 2, 3}) } // Test that a list l is not modified when calling MoveAfter or MoveBefore with a mark that is not an element of l. func TestMoveUnknownMark(t *testing.T) { - var l1 List(int) + var l1 List[int] e1 := l1.PushBack(1) - var l2 List(int) + var l2 List[int] e2 := l2.PushBack(2) l1.MoveAfter(e1, e2) @@ -346,7 +346,7 @@ func TestMoveUnknownMark(t *testing.T) { // Test the Transform function. func TestTransform(t *testing.T) { - l1 := New(int)() + l1 := New[int]() l1.PushBack(1) l1.PushBack(2) l2 := Transform(l1, strconv.Itoa) diff --git a/src/cmd/go2go/testdata/go2path/src/maps/maps.go2 b/src/cmd/go2go/testdata/go2path/src/maps/maps.go2 index 1d05f42c02..ac0b968c48 100644 --- a/src/cmd/go2go/testdata/go2path/src/maps/maps.go2 +++ b/src/cmd/go2go/testdata/go2path/src/maps/maps.go2 @@ -10,7 +10,7 @@ type any interface{} // Keys returns the keys of the map m. // The keys will be an indeterminate order. -func Keys(type K comparable, V any)(m map[K]V) []K { +func Keys[type K comparable, V any](m map[K]V) []K { r := make([]K, 0, len(m)) for k := range m { r = append(r, k) @@ -20,7 +20,7 @@ func Keys(type K comparable, V any)(m map[K]V) []K { // Values returns the values of the map m. // The values will be in an indeterminate order. -func Values(type K comparable, V any)(m map[K]V) []V { +func Values[type K comparable, V any](m map[K]V) []V { r := make([]V, 0, len(m)) for _, v := range m { r = append(r, v) @@ -30,7 +30,7 @@ func Values(type K comparable, V any)(m map[K]V) []V { // Equal reports whether two maps contain the same key/value pairs. // Values are compared using ==. -func Equal(type K, V comparable)(m1, m2 map[K]V) bool { +func Equal[type K, V comparable](m1, m2 map[K]V) bool { if len(m1) != len(m2) { return false } @@ -43,7 +43,7 @@ func Equal(type K, V comparable)(m1, m2 map[K]V) bool { } // Copy returns a copy of m. -func Copy(type K comparable, V any)(m map[K]V) map[K]V { +func Copy[type K comparable, V any](m map[K]V) map[K]V { r := make(map[K]V, len(m)) for k, v := range m { r[k] = v @@ -53,7 +53,7 @@ func Copy(type K comparable, V any)(m map[K]V) map[K]V { // Add adds all key/value pairs in m2 to m1. Keys in m2 that are already // present in m1 will be overwritten with the value in m2. -func Add(type K comparable, V any)(m1, m2 map[K]V) { +func Add[type K comparable, V any](m1, m2 map[K]V) { for k, v := range m2 { m1[k] = v } @@ -61,7 +61,7 @@ func Add(type K comparable, V any)(m1, m2 map[K]V) { // Sub removes all keys in m2 from m1. Keys in m2 that are not present // in m1 are ignored. The values in m2 are ignored. -func Sub(type K comparable, V any)(m1, m2 map[K]V) { +func Sub[type K comparable, V any](m1, m2 map[K]V) { for k := range m2 { delete(m1, k) } @@ -69,7 +69,7 @@ func Sub(type K comparable, V any)(m1, m2 map[K]V) { // Intersect removes all keys from m1 that are not present in m2. // Keys in m2 that are not in m1 are ignored. The values in m2 are ignored. -func Intersect(type K comparable, V any)(m1, m2 map[K]V) { +func Intersect[type K comparable, V any](m1, m2 map[K]V) { for k := range m1 { if _, ok := m2[k]; !ok { delete(m1, k) @@ -78,7 +78,7 @@ func Intersect(type K comparable, V any)(m1, m2 map[K]V) { } // Filter deletes any key/value pairs from m for which f returns false. -func Filter(type K comparable, V any)(m map[K]V, f func(K, V) bool) { +func Filter[type K comparable, V any](m map[K]V, f func(K, V) bool) { for k, v := range m { if !f(k, v) { delete(m, k) @@ -87,7 +87,7 @@ func Filter(type K comparable, V any)(m map[K]V, f func(K, V) bool) { } // TransformValues applies f to each value in m. The keys remain unchanged. -func TransformValues(type K comparable, V any)(m map[K]V, f func(V) V) { +func TransformValues[type K comparable, V any](m map[K]V, f func(V) V) { for k, v := range m { m[k] = f(v) } diff --git a/src/cmd/go2go/testdata/go2path/src/metrics/metrics.go2 b/src/cmd/go2go/testdata/go2path/src/metrics/metrics.go2 index dd89535200..5e470314bf 100644 --- a/src/cmd/go2go/testdata/go2path/src/metrics/metrics.go2 +++ b/src/cmd/go2go/testdata/go2path/src/metrics/metrics.go2 @@ -13,13 +13,13 @@ import ( ) // Metric1 tracks metrics of values of some type. -type Metric1(type T comparable) struct { +type Metric1[type T comparable] struct { mu sync.Mutex m map[T]int } // Add adds another instance of some value. -func (m *Metric1(T)) Add(v T) { +func (m *Metric1[T]) Add(v T) { m.mu.Lock() defer m.mu.Unlock() if m.m == nil { @@ -29,47 +29,47 @@ func (m *Metric1(T)) Add(v T) { } // Count returns the number of instances we've seen of v. -func (m *Metric1(T)) Count(v T) int { +func (m *Metric1[T]) Count(v T) int { m.mu.Lock() defer m.mu.Unlock() return m.m[v] } // Metrics returns all the values we've seen, in an indeterminate order. -func (m *Metric1(T)) Metrics() []T { +func (m *Metric1[T]) Metrics() []T { return maps.Keys(m.m) } -type key2(type T1, T2 comparable) struct { +type key2[type T1, T2 comparable] struct { f1 T1 f2 T2 } // Metric2 tracks metrics of pairs of values. -type Metric2(type T1, T2 comparable) struct { +type Metric2[type T1, T2 comparable] struct { mu sync.Mutex - m map[key2(T1, T2)]int + m map[key2[T1, T2]]int } // Add adds another instance of some pair of values. -func (m *Metric2(T1, T2)) Add(v1 T1, v2 T2) { +func (m *Metric2[T1, T2]) Add(v1 T1, v2 T2) { m.mu.Lock() defer m.mu.Unlock() if m.m == nil { - m.m = make(map[key2(T1, T2)]int) + m.m = make(map[key2[T1, T2]]int) } - m.m[key2(T1, T2){v1, v2}]++ + m.m[key2[T1, T2]{v1, v2}]++ } // Count returns the number of instances we've seen of v1/v2. -func (m *Metric2(T1, T2)) Count(v1 T1, v2 T2) int { +func (m *Metric2[T1, T2]) Count(v1 T1, v2 T2) int { m.mu.Lock() defer m.mu.Unlock() - return m.m[key2(T1, T2){v1, v2}] + return m.m[key2[T1, T2]{v1, v2}] } // Metrics returns all the values we've seen, in an indeterminate order. -func (m *Metric2(T1, T2)) Metrics() (r1 []T1, r2 []T2) { +func (m *Metric2[T1, T2]) Metrics() (r1 []T1, r2 []T2) { for _, k := range maps.Keys(m.m) { r1 = append(r1, k.f1) r2 = append(r2, k.f2) @@ -77,37 +77,37 @@ func (m *Metric2(T1, T2)) Metrics() (r1 []T1, r2 []T2) { return r1, r2 } -type key3(type T1, T2, T3 comparable) struct { +type key3[type T1, T2, T3 comparable] struct { f1 T1 f2 T2 f3 T3 } // Metric3 tracks metrics of triplets of values. -type Metric3(type T1, T2, T3 comparable) struct { +type Metric3[type T1, T2, T3 comparable] struct { mu sync.Mutex - m map[key3(T1, T2, T3)]int + m map[key3[T1, T2, T3]]int } // Add adds another instance of some triplet of values. -func (m *Metric3(T1, T2, T3)) Add(v1 T1, v2 T2, v3 T3) { +func (m *Metric3[T1, T2, T3]) Add(v1 T1, v2 T2, v3 T3) { m.mu.Lock() defer m.mu.Unlock() if m.m == nil { - m.m = make(map[key3(T1, T2, T3)]int) + m.m = make(map[key3[T1, T2, T3]]int) } - m.m[key3(T1, T2, T3){v1, v2, v3}]++ + m.m[key3[T1, T2, T3]{v1, v2, v3}]++ } // Count returns the number of instances we've seen of v1/v2/v3. -func (m *Metric3(T1, T2, T3)) Count(v1 T1, v2 T2, v3 T3) int { +func (m *Metric3[T1, T2, T3]) Count(v1 T1, v2 T2, v3 T3) int { m.mu.Lock() defer m.mu.Unlock() - return m.m[key3(T1, T2, T3){v1, v2, v3}] + return m.m[key3[T1, T2, T3]{v1, v2, v3}] } // Metrics returns all the values we've seen, in an indeterminate order. -func (m *Metric3(T1, T2, T3)) Metrics() (r1 []T1, r2 []T2, r3 []T3) { +func (m *Metric3[T1, T2, T3]) Metrics() (r1 []T1, r2 []T2, r3 []T3) { for k := range m.m { r1 = append(r1, k.f1) r2 = append(r2, k.f2) diff --git a/src/cmd/go2go/testdata/go2path/src/metrics/metrics_test.go2 b/src/cmd/go2go/testdata/go2path/src/metrics/metrics_test.go2 index e2334ab277..1fbf4b8d6c 100644 --- a/src/cmd/go2go/testdata/go2path/src/metrics/metrics_test.go2 +++ b/src/cmd/go2go/testdata/go2path/src/metrics/metrics_test.go2 @@ -14,7 +14,7 @@ import ( type S struct{ a, b, c string } func TestMetrics(t *testing.T) { - m1 := Metric1(string){} + m1 := Metric1[string]{} if got := m1.Count("a"); got != 0 { t.Errorf("Count(%q) = %d, want 0", "a", got) } @@ -27,7 +27,7 @@ func TestMetrics(t *testing.T) { t.Errorf("Metrics = %v, want %v", got, want) } - m2 := Metric2(int, float64){} + m2 := Metric2[int, float64]{} m2.Add(1, 1) m2.Add(2, 2) m2.Add(3, 3) @@ -46,7 +46,7 @@ func TestMetrics(t *testing.T) { t.Errorf("Metric2.Metrics first slice = %v, want %v", k2, w2) } - m3 := Metric3(string, S, S){} + m3 := Metric3[string, S, S]{} m3.Add("a", S{"d", "e", "f"}, S{"g", "h", "i"}) m3.Add("a", S{"d", "e", "f"}, S{"g", "h", "i"}) m3.Add("a", S{"d", "e", "f"}, S{"g", "h", "i"}) diff --git a/src/cmd/go2go/testdata/go2path/src/orderedmap/orderedmap.go2 b/src/cmd/go2go/testdata/go2path/src/orderedmap/orderedmap.go2 index d997e4ab4f..c216d159b5 100644 --- a/src/cmd/go2go/testdata/go2path/src/orderedmap/orderedmap.go2 +++ b/src/cmd/go2go/testdata/go2path/src/orderedmap/orderedmap.go2 @@ -15,30 +15,30 @@ import ( ) // Map is an ordered map. -type Map(type K, V) struct { - root *node(K, V) +type Map[type K, V] struct { + root *node[K, V] compare func(K, K) int } // node is the type of a node in the binary tree. -type node(type K, V) struct { +type node[type K, V] struct { key K val V - left, right *node(K, V) + left, right *node[K, V] } // New returns a new map. It takes a comparison function that compares two // keys and returns < 0 if the first is less, == 0 if they are equal, // > 0 if the first is greater. -func New(type K, V)(compare func(K, K) int) *Map(K, V) { - return &Map(K, V){compare: compare} +func New[type K, V](compare func(K, K) int) *Map[K, V] { + return &Map[K, V]{compare: compare} } // NewOrdered returns a new map whose key is an ordered type. // This is like New, but does not require providing a compare function. // The map compare function uses the obvious key ordering. -func NewOrdered(type K constraints.Ordered, V interface{})() *Map(K, V) { - return New(K, V)(func(k1, k2 K) int { +func NewOrdered[type K constraints.Ordered, V interface{}]() *Map[K, V] { + return New[K, V](func(k1, k2 K) int { switch { case k1 < k2: return -1 @@ -52,7 +52,7 @@ func NewOrdered(type K constraints.Ordered, V interface{})() *Map(K, V) { // find looks up key in the map, returning either a pointer to the slot of the // node holding key, or a pointer to the slot where should a node would go. -func (m *Map(K, V)) find(key K) **node(K, V) { +func (m *Map[K, V]) find(key K) **node[K, V] { pn := &m.root for *pn != nil { switch cmp := m.compare(key, (*pn).key); { @@ -70,19 +70,19 @@ func (m *Map(K, V)) find(key K) **node(K, V) { // Insert inserts a new key/value into the map. // If the key is already present, the value is replaced. // Reports whether this is a new key. -func (m *Map(K, V)) Insert(key K, val V) bool { +func (m *Map[K, V]) Insert(key K, val V) bool { pn := m.find(key) if *pn != nil { (*pn).val = val return false } - *pn = &node(K, V){key: key, val: val} + *pn = &node[K, V]{key: key, val: val} return true } // Find returns the value associated with a key, or the zero value // if not present. The found result reports whether the key was found. -func (m *Map(K, V)) Find(key K) (V, bool) { +func (m *Map[K, V]) Find(key K) (V, bool) { pn := m.find(key) if *pn == nil { var zero V @@ -92,40 +92,40 @@ func (m *Map(K, V)) Find(key K) (V, bool) { } // keyValue is a pair of key and value used while iterating. -type keyValue(type K, V) struct { +type keyValue[type K, V] struct { key K val V } // iterate returns an iterator that traverses the map. -func (m *Map(K, V)) Iterate() *Iterator(K, V) { - sender, receiver := chans.Ranger(keyValue(K, V))() - var f func(*node(K, V)) bool - f = func(n *node(K, V)) bool { +func (m *Map[K, V]) Iterate() *Iterator[K, V] { + sender, receiver := chans.Ranger(keyValue[K, V])() + var f func(*node[K, V]) bool + f = func(n *node[K, V]) bool { if n == nil { return true } // Stop the traversal if Send fails, which means that // nothing is listening to the receiver. return f(n.left) && - sender.Send(context.Background(), keyValue(K, V){n.key, n.val}) && + sender.Send(context.Background(), keyValue[K, V]{n.key, n.val}) && f(n.right) } go func() { f(m.root) sender.Close() }() - return &Iterator(K, V){receiver} + return &Iterator[K, V]{receiver} } // Iterator is used to iterate over the map. -type Iterator(type K, V) struct { - r *chans.Receiver(keyValue(K, V)) +type Iterator[type K, V] struct { + r *chans.Receiver[keyValue[K, V]] } // Next returns the next key and value pair, and a boolean that reports // whether they are valid. If not valid, we have reached the end of the map. -func (it *Iterator(K, V)) Next() (K, V, bool) { +func (it *Iterator[K, V]) Next() (K, V, bool) { keyval, ok := it.r.Next(context.Background()) if !ok { var zerok K diff --git a/src/cmd/go2go/testdata/go2path/src/orderedmap/orderedmap_test.go2 b/src/cmd/go2go/testdata/go2path/src/orderedmap/orderedmap_test.go2 index b51ac0a7f3..dd7306b2a0 100644 --- a/src/cmd/go2go/testdata/go2path/src/orderedmap/orderedmap_test.go2 +++ b/src/cmd/go2go/testdata/go2path/src/orderedmap/orderedmap_test.go2 @@ -12,7 +12,7 @@ import ( ) func TestMap(t *testing.T) { - m := New([]byte, int)(bytes.Compare) + m := New[[]byte, int](bytes.Compare) if _, found := m.Find([]byte("a")); found { t.Errorf("unexpectedly found %q in empty map", []byte("a")) @@ -45,7 +45,7 @@ func TestMap(t *testing.T) { t.Errorf("unexpectedly found %q", []byte("d")) } - gather := func(it *Iterator([]byte, int)) []int { + gather := func(it *Iterator[[]byte, int]) []int { var r []int for { _, v, ok := it.Next() diff --git a/src/cmd/go2go/testdata/go2path/src/sets/sets.go2 b/src/cmd/go2go/testdata/go2path/src/sets/sets.go2 index 55ce782477..05dc6d1ea4 100644 --- a/src/cmd/go2go/testdata/go2path/src/sets/sets.go2 +++ b/src/cmd/go2go/testdata/go2path/src/sets/sets.go2 @@ -6,40 +6,40 @@ package sets // A Set is a set of elements of some type. -type Set(type Elem comparable) struct { +type Set[type Elem comparable] struct { m map[Elem]struct{} } // Make makes a new set. -func Make(type Elem comparable)() Set(Elem) { - return Set(Elem){m: make(map[Elem]struct{})} +func Make[type Elem comparable]() Set[Elem] { + return Set[Elem]{m: make(map[Elem]struct{})} } // Add adds an element to a set. -func (s Set(Elem)) Add(v Elem) { +func (s Set[Elem]) Add(v Elem) { s.m[v] = struct{}{} } // Delete removes an element from a set. If the element is not present // in the set, this does nothing. -func (s Set(Elem)) Delete(v Elem) { +func (s Set[Elem]) Delete(v Elem) { delete(s.m, v) } // Contains reports whether v is in the set. -func (s Set(Elem)) Contains(v Elem) bool { +func (s Set[Elem]) Contains(v Elem) bool { _, ok := s.m[v] return ok } // Len returns the number of elements in the set. -func (s Set(Elem)) Len() int { +func (s Set[Elem]) Len() int { return len(s.m) } // Values returns the values in the set. // The values will be in an indeterminate order. -func (s Set(Elem)) Values() []Elem { +func (s Set[Elem]) Values() []Elem { r := make([]Elem, 0, len(s.m)) for v := range s.m { r = append(r, v) @@ -48,7 +48,7 @@ func (s Set(Elem)) Values() []Elem { } // Equal reports whether two sets contain the same elements. -func Equal(type Elem comparable)(s1, s2 Set(Elem)) bool { +func Equal[type Elem comparable](s1, s2 Set[Elem]) bool { if len(s1.m) != len(s2.m) { return false } @@ -61,8 +61,8 @@ func Equal(type Elem comparable)(s1, s2 Set(Elem)) bool { } // Copy returns a copy of s. -func (s Set(Elem)) Copy() Set(Elem) { - r := Set(Elem){m: make(map[Elem]struct{}, len(s.m))} +func (s Set[Elem]) Copy() Set[Elem] { + r := Set[Elem]{m: make(map[Elem]struct{}, len(s.m))} for v := range s.m { r.m[v] = struct{}{} } @@ -70,7 +70,7 @@ func (s Set(Elem)) Copy() Set(Elem) { } // AddSet adds all the elements of s2 to s. -func (s Set(Elem)) AddSet(s2 Set(Elem)) { +func (s Set[Elem]) AddSet(s2 Set[Elem]) { for v := range s2.m { s.m[v] = struct{}{} } @@ -78,7 +78,7 @@ func (s Set(Elem)) AddSet(s2 Set(Elem)) { // SubSet removes all elements in s2 from s. // Values in s2 that are not in s are ignored. -func (s Set(Elem)) SubSet(s2 Set(Elem)) { +func (s Set[Elem]) SubSet(s2 Set[Elem]) { for v := range s2.m { delete(s.m, v) } @@ -86,7 +86,7 @@ func (s Set(Elem)) SubSet(s2 Set(Elem)) { // Intersect removes all elements from s that are not present in s2. // Values in s2 that are not in s are ignored. -func (s Set(Elem)) Intersect(s2 Set(Elem)) { +func (s Set[Elem]) Intersect(s2 Set[Elem]) { for v := range s.m { if !s2.Contains(v) { delete(s.m, v) @@ -95,14 +95,14 @@ func (s Set(Elem)) Intersect(s2 Set(Elem)) { } // Iterate calls f on every element in the set. -func (s Set(Elem)) Iterate(f func(Elem)) { +func (s Set[Elem]) Iterate(f func(Elem)) { for v := range s.m { f(v) } } // Filter deletes any elements from s for which f returns false. -func (s Set(Elem)) Filter(f func(Elem) bool) { +func (s Set[Elem]) Filter(f func(Elem) bool) { for v := range s.m { if !f(v) { delete(s.m, v) diff --git a/src/cmd/go2go/testdata/go2path/src/sets/sets_test.go2 b/src/cmd/go2go/testdata/go2path/src/sets/sets_test.go2 index b06248f506..6994d9d82c 100644 --- a/src/cmd/go2go/testdata/go2path/src/sets/sets_test.go2 +++ b/src/cmd/go2go/testdata/go2path/src/sets/sets_test.go2 @@ -12,7 +12,7 @@ import ( ) func TestSet(t *testing.T) { - s1 := Make(int)() + s1 := Make[int]() if got := s1.Len(); got != 0 { t.Errorf("Len of empty set = %d, want 0", got) } @@ -43,8 +43,8 @@ func TestSet(t *testing.T) { } func TestEqual(t *testing.T) { - s1 := Make(string)() - s2 := Make(string)() + s1 := Make[string]() + s2 := Make[string]() if !Equal(s1, s2) { t.Errorf("Equal(%v, %v) = false, want true", s1, s2) } @@ -59,7 +59,7 @@ func TestEqual(t *testing.T) { } func TestCopy(t *testing.T) { - s1 := Make(float64)() + s1 := Make[float64]() s1.Add(0) s2 := s1.Copy() if !Equal(s1, s2) { @@ -72,10 +72,10 @@ func TestCopy(t *testing.T) { } func TestAddSet(t *testing.T) { - s1 := Make(int)() + s1 := Make[int]() s1.Add(1) s1.Add(2) - s2 := Make(int)() + s2 := Make[int]() s2.Add(2) s2.Add(3) s1.AddSet(s2) @@ -89,10 +89,10 @@ func TestAddSet(t *testing.T) { } func TestSubSet(t *testing.T) { - s1 := Make(int)() + s1 := Make[int]() s1.Add(1) s1.Add(2) - s2 := Make(int)() + s2 := Make[int]() s2.Add(2) s2.Add(3) s1.SubSet(s2) @@ -105,10 +105,10 @@ func TestSubSet(t *testing.T) { } func TestIntersect(t *testing.T) { - s1 := Make(int)() + s1 := Make[int]() s1.Add(1) s1.Add(2) - s2 := Make(int)() + s2 := Make[int]() s2.Add(2) s2.Add(3) s1.Intersect(s2) @@ -121,7 +121,7 @@ func TestIntersect(t *testing.T) { } func TestIterate(t *testing.T) { - s1 := Make(int)() + s1 := Make[int]() s1.Add(1) s1.Add(2) s1.Add(3) @@ -134,7 +134,7 @@ func TestIterate(t *testing.T) { } func TestFilter(t *testing.T) { - s1 := Make(int)() + s1 := Make[int]() s1.Add(1) s1.Add(2) s1.Add(3) diff --git a/src/cmd/go2go/testdata/go2path/src/slices/slices.go2 b/src/cmd/go2go/testdata/go2path/src/slices/slices.go2 index ab687d6e20..123a822a88 100644 --- a/src/cmd/go2go/testdata/go2path/src/slices/slices.go2 +++ b/src/cmd/go2go/testdata/go2path/src/slices/slices.go2 @@ -13,7 +13,7 @@ import ( // Equal reports whether two slices are equal: the same length and all // elements equal. All floating point NaNs are considered equal. -func Equal(type Elem comparable)(s1, s2 []Elem) bool { +func Equal[type Elem comparable](s1, s2 []Elem) bool { if len(s1) != len(s2) { return false } @@ -31,7 +31,7 @@ func Equal(type Elem comparable)(s1, s2 []Elem) bool { // EqualFn reports whether two slices are equal using a comparision // function on each element. -func EqualFn(type Elem)(s1, s2 []Elem, eq func(Elem, Elem) bool) bool { +func EqualFn[type Elem](s1, s2 []Elem, eq func(Elem, Elem) bool) bool { if len(s1) != len(s2) { return false } @@ -45,7 +45,7 @@ func EqualFn(type Elem)(s1, s2 []Elem, eq func(Elem, Elem) bool) bool { } // Map turns a []Elem1 to a []Elem2 using a mapping function. -func Map(type Elem1, Elem2)(s []Elem1, f func(Elem1) Elem2) []Elem2 { +func Map[type Elem1, Elem2](s []Elem1, f func(Elem1) Elem2) []Elem2 { r := make([]Elem2, len(s)) for i, v := range s { r[i] = f(v) @@ -55,7 +55,7 @@ func Map(type Elem1, Elem2)(s []Elem1, f func(Elem1) Elem2) []Elem2 { // Reduce reduces a []Elem1 to a single value of type Elem2 using // a reduction function. -func Reduce(type Elem1, Elem2)(s []Elem1, initializer Elem2, f func(Elem2, Elem1) Elem2) Elem2 { +func Reduce[type Elem1, Elem2](s []Elem1, initializer Elem2, f func(Elem2, Elem1) Elem2) Elem2 { r := initializer for _, v := range s { r = f(r, v) @@ -64,7 +64,7 @@ func Reduce(type Elem1, Elem2)(s []Elem1, initializer Elem2, f func(Elem2, Elem1 } // Filter filters values from a slice using a filter function. -func Filter(type Elem)(s []Elem, f func(Elem) bool) []Elem { +func Filter[type Elem](s []Elem, f func(Elem) bool) []Elem { var r []Elem for _, v := range s { if f(v) { @@ -76,7 +76,7 @@ func Filter(type Elem)(s []Elem, f func(Elem) bool) []Elem { // Max returns the maximum element in a slice of some ordered type. // If the slice is empty it returns the zero value of the element type. -func Max(type Elem constraints.Ordered)(s []Elem) Elem { +func Max[type Elem constraints.Ordered](s []Elem) Elem { if len(s) == 0 { var zero Elem return zero @@ -86,7 +86,7 @@ func Max(type Elem constraints.Ordered)(s []Elem) Elem { // Min returns the minimum element in a slice of some ordered type. // If the slice is empty it returns the zero value of the element type. -func Min(type Elem constraints.Ordered)(s []Elem) Elem { +func Min[type Elem constraints.Ordered](s []Elem) Elem { if len(s) == 0 { var zero Elem return zero @@ -99,7 +99,7 @@ func Min(type Elem constraints.Ordered)(s []Elem) Elem { // of how to write it using generics. We used to write code like // this before append was added to the language, but we had to write // a separate copy for each type. -func Append(type T)(s []T, t ...T) []T { +func Append[type T](s []T, t ...T) []T { lens := len(s) tot := lens + len(t) if tot <= cap(s) { @@ -116,7 +116,7 @@ func Append(type T)(s []T, t ...T) []T { // Copy copies values from t to s, stopping when either slice is full, // returning the number of values copied. This is like the predeclared // copy function; it's an example of how to write it using generics. -func Copy(type T)(s, t []T) int { +func Copy[type T](s, t []T) int { i := 0 for ; i < len(s) && i < len(t); i++ { s[i] = t[i] diff --git a/src/cmd/go2go/testdata/go2path/src/slices/slices_test.go2 b/src/cmd/go2go/testdata/go2path/src/slices/slices_test.go2 index 5c2cdeeaf2..3ee2bfc411 100644 --- a/src/cmd/go2go/testdata/go2path/src/slices/slices_test.go2 +++ b/src/cmd/go2go/testdata/go2path/src/slices/slices_test.go2 @@ -42,7 +42,7 @@ func TestEqual(t *testing.T) { } } -func offByOne(type Elem constraints.Integer)(a, b Elem) bool { +func offByOne[type Elem constraints.Integer](a, b Elem) bool { return a == b + 1 || a == b - 1 }