summaryrefslogtreecommitdiffstats
path: root/src/go/parser/testdata
diff options
context:
space:
mode:
Diffstat (limited to 'src/go/parser/testdata')
-rw-r--r--src/go/parser/testdata/chans.go262
-rw-r--r--src/go/parser/testdata/commas.src19
-rw-r--r--src/go/parser/testdata/issue11377.src27
-rw-r--r--src/go/parser/testdata/issue23434.src25
-rw-r--r--src/go/parser/testdata/issue3106.src46
-rw-r--r--src/go/parser/testdata/issue34946.src22
-rw-r--r--src/go/parser/testdata/issue42951/not_a_file.go/invalid.go1
-rw-r--r--src/go/parser/testdata/issue44504.src13
-rw-r--r--src/go/parser/testdata/linalg.go283
-rw-r--r--src/go/parser/testdata/map.go2109
-rw-r--r--src/go/parser/testdata/metrics.go258
-rw-r--r--src/go/parser/testdata/resolution/issue45136.src27
-rw-r--r--src/go/parser/testdata/resolution/issue45160.src25
-rw-r--r--src/go/parser/testdata/resolution/resolution.src63
-rw-r--r--src/go/parser/testdata/resolution/typeparams.go243
-rw-r--r--src/go/parser/testdata/set.go231
-rw-r--r--src/go/parser/testdata/slices.go231
-rw-r--r--src/go/parser/testdata/sort.go227
-rw-r--r--src/go/parser/testdata/typeparams.src17
19 files changed, 729 insertions, 0 deletions
diff --git a/src/go/parser/testdata/chans.go2 b/src/go/parser/testdata/chans.go2
new file mode 100644
index 0000000..fad2bce
--- /dev/null
+++ b/src/go/parser/testdata/chans.go2
@@ -0,0 +1,62 @@
+package chans
+
+import "runtime"
+
+// Ranger returns a Sender and a Receiver. The Receiver provides a
+// Next method to retrieve values. The Sender provides a Send method
+// to send values and a Close method to stop sending values. The Next
+// method indicates when the Sender has been closed, and the Send
+// method indicates when the Receiver has been freed.
+//
+// This is a convenient way to exit a goroutine sending values when
+// the receiver stops reading them.
+func Ranger[T any]() (*Sender[T], *Receiver[T]) {
+ c := make(chan T)
+ d := make(chan bool)
+ s := &Sender[T]{values: c, done: d}
+ r := &Receiver[T]{values: c, done: d}
+ runtime.SetFinalizer(r, r.finalize)
+ return s, r
+}
+
+// A sender is used to send values to a Receiver.
+type Sender[T any] struct {
+ values chan<- T
+ done <-chan bool
+}
+
+// Send sends a value to the receiver. It returns whether any more
+// values may be sent; if it returns false the value was not sent.
+func (s *Sender[T]) Send(v T) bool {
+ select {
+ case s.values <- v:
+ return true
+ case <-s.done:
+ return false
+ }
+}
+
+// Close tells the receiver that no more values will arrive.
+// After Close is called, the Sender may no longer be used.
+func (s *Sender[T]) Close() {
+ close(s.values)
+}
+
+// A Receiver receives values from a Sender.
+type Receiver[T any] struct {
+ values <-chan T
+ done chan<- bool
+}
+
+// Next returns the next value from the channel. The bool result
+// indicates whether the value is valid, or whether the Sender has
+// been closed and no more values will be received.
+func (r *Receiver[T]) Next() (T, bool) {
+ v, ok := <-r.values
+ return v, ok
+}
+
+// finalize is a finalizer for the receiver.
+func (r *Receiver[T]) finalize() {
+ close(r.done)
+}
diff --git a/src/go/parser/testdata/commas.src b/src/go/parser/testdata/commas.src
new file mode 100644
index 0000000..e0603cf
--- /dev/null
+++ b/src/go/parser/testdata/commas.src
@@ -0,0 +1,19 @@
+// Copyright 2012 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 case for error messages/parser synchronization
+// after missing commas.
+
+package p
+
+var _ = []int{
+ 0/* ERROR HERE "missing ','" */
+}
+
+var _ = []int{
+ 0,
+ 1,
+ 2,
+ 3/* ERROR HERE "missing ','" */
+}
diff --git a/src/go/parser/testdata/issue11377.src b/src/go/parser/testdata/issue11377.src
new file mode 100644
index 0000000..1c43800
--- /dev/null
+++ b/src/go/parser/testdata/issue11377.src
@@ -0,0 +1,27 @@
+// Copyright 2018 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 case for issue 11377: Better synchronization of
+// parser after certain syntax errors.
+
+package p
+
+func bad1() {
+ if f()) /* ERROR "expected ';', found '\)'" */ {
+ return
+ }
+}
+
+// There shouldn't be any errors down below.
+
+func F1() {}
+func F2() {}
+func F3() {}
+func F4() {}
+func F5() {}
+func F6() {}
+func F7() {}
+func F8() {}
+func F9() {}
+func F10() {}
diff --git a/src/go/parser/testdata/issue23434.src b/src/go/parser/testdata/issue23434.src
new file mode 100644
index 0000000..24a0832
--- /dev/null
+++ b/src/go/parser/testdata/issue23434.src
@@ -0,0 +1,25 @@
+// Copyright 2018 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 case for issue 23434: Better synchronization of
+// parser after missing type. There should be exactly
+// one error each time, with now follow errors.
+
+package p
+
+func g() {
+ m := make(map[string]! /* ERROR "expected type, found '!'" */ )
+ for {
+ x := 1
+ print(x)
+ }
+}
+
+func f() {
+ m := make(map[string]) /* ERROR "expected type, found '\)'" */
+ for {
+ x := 1
+ print(x)
+ }
+}
diff --git a/src/go/parser/testdata/issue3106.src b/src/go/parser/testdata/issue3106.src
new file mode 100644
index 0000000..2db10be
--- /dev/null
+++ b/src/go/parser/testdata/issue3106.src
@@ -0,0 +1,46 @@
+// Copyright 2012 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 case for issue 3106: Better synchronization of
+// parser after certain syntax errors.
+
+package main
+
+func f() {
+ var m Mutex
+ c := MakeCond(&m)
+ percent := 0
+ const step = 10
+ for i := 0; i < 5; i++ {
+ go func() {
+ for {
+ // Emulates some useful work.
+ time.Sleep(1e8)
+ m.Lock()
+ defer
+ if /* ERROR "expected ';', found 'if'" */ percent == 100 {
+ m.Unlock()
+ break
+ }
+ percent++
+ if percent % step == 0 {
+ //c.Signal()
+ }
+ m.Unlock()
+ }
+ }()
+ }
+ for {
+ m.Lock()
+ if percent == 0 || percent % step != 0 {
+ c.Wait()
+ }
+ fmt.Print(",")
+ if percent == 100 {
+ m.Unlock()
+ break
+ }
+ m.Unlock()
+ }
+}
diff --git a/src/go/parser/testdata/issue34946.src b/src/go/parser/testdata/issue34946.src
new file mode 100644
index 0000000..6bb15e1
--- /dev/null
+++ b/src/go/parser/testdata/issue34946.src
@@ -0,0 +1,22 @@
+// Copyright 2019 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 case for issue 34946: Better synchronization of
+// parser for function declarations that start their
+// body's opening { on a new line.
+
+package p
+
+// accept Allman/BSD-style declaration but complain
+// (implicit semicolon between signature and body)
+func _() int
+{ /* ERROR "unexpected semicolon or newline before {" */
+ { return 0 }
+}
+
+func _() {}
+
+func _(); { /* ERROR "unexpected semicolon or newline before {" */ }
+
+func _() {}
diff --git a/src/go/parser/testdata/issue42951/not_a_file.go/invalid.go b/src/go/parser/testdata/issue42951/not_a_file.go/invalid.go
new file mode 100644
index 0000000..bb698be
--- /dev/null
+++ b/src/go/parser/testdata/issue42951/not_a_file.go/invalid.go
@@ -0,0 +1 @@
+This file should not be parsed by ParseDir.
diff --git a/src/go/parser/testdata/issue44504.src b/src/go/parser/testdata/issue44504.src
new file mode 100644
index 0000000..7791f4a
--- /dev/null
+++ b/src/go/parser/testdata/issue44504.src
@@ -0,0 +1,13 @@
+// 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 case for issue 44504: panic due to duplicate resolution of slice/index
+// operands. We should not try to resolve a LHS expression with invalid syntax.
+
+package p
+
+func _() {
+ var items []bool
+ items[] /* ERROR "operand" */ = false
+}
diff --git a/src/go/parser/testdata/linalg.go2 b/src/go/parser/testdata/linalg.go2
new file mode 100644
index 0000000..fba0d02
--- /dev/null
+++ b/src/go/parser/testdata/linalg.go2
@@ -0,0 +1,83 @@
+// Copyright 2019 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 linalg
+
+import "math"
+
+// Numeric is type bound that matches any numeric type.
+// It would likely be in a constraints package in the standard library.
+type Numeric interface {
+ type int, int8, int16, int32, int64,
+ uint, uint8, uint16, uint32, uint64, uintptr,
+ float32, float64,
+ complex64, complex128
+}
+
+func DotProduct[T Numeric](s1, s2 []T) T {
+ if len(s1) != len(s2) {
+ panic("DotProduct: slices of unequal length")
+ }
+ var r T
+ for i := range s1 {
+ r += s1[i] * s2[i]
+ }
+ return r
+}
+
+// NumericAbs matches numeric types with an Abs method.
+type NumericAbs[T any] interface {
+ Numeric
+
+ Abs() T
+}
+
+// AbsDifference computes the absolute value of the difference of
+// a and b, where the absolute value is determined by the Abs method.
+func AbsDifference[T NumericAbs](a, b T) T {
+ d := a - b
+ return d.Abs()
+}
+
+// OrderedNumeric is a type bound that matches numeric types that support the < operator.
+type OrderedNumeric interface {
+ type int, int8, int16, int32, int64,
+ uint, uint8, uint16, uint32, uint64, uintptr,
+ float32, float64
+}
+
+// Complex is a type bound that matches the two complex types, which do not have a < operator.
+type Complex interface {
+ type complex64, complex128
+}
+
+// OrderedAbs is a helper type that defines an Abs method for
+// ordered numeric types.
+type OrderedAbs[T OrderedNumeric] T
+
+func (a OrderedAbs[T]) Abs() OrderedAbs[T] {
+ if a < 0 {
+ return -a
+ }
+ return a
+}
+
+// ComplexAbs is a helper type that defines an Abs method for
+// complex types.
+type ComplexAbs[T Complex] T
+
+func (a ComplexAbs[T]) Abs() ComplexAbs[T] {
+ r := float64(real(a))
+ i := float64(imag(a))
+ d := math.Sqrt(r * r + i * i)
+ return ComplexAbs[T](complex(d, 0))
+}
+
+func OrderedAbsDifference[T OrderedNumeric](a, b T) T {
+ return T(AbsDifference(OrderedAbs[T](a), OrderedAbs[T](b)))
+}
+
+func ComplexAbsDifference[T Complex](a, b T) T {
+ return T(AbsDifference(ComplexAbs[T](a), ComplexAbs[T](b)))
+}
diff --git a/src/go/parser/testdata/map.go2 b/src/go/parser/testdata/map.go2
new file mode 100644
index 0000000..74c79ae
--- /dev/null
+++ b/src/go/parser/testdata/map.go2
@@ -0,0 +1,109 @@
+// Package orderedmap provides an ordered map, implemented as a binary tree.
+package orderedmap
+
+import "chans"
+
+// Map is an ordered map.
+type Map[K, V any] struct {
+ root *node[K, V]
+ compare func(K, K) int
+}
+
+// node is the type of a node in the binary tree.
+type node[K, V any] struct {
+ key K
+ val V
+ left, right *node[K, V]
+}
+
+// New returns a new map.
+func New[K, V any](compare func(K, K) int) *Map[K, V] {
+ return &Map[K, V]{compare: compare}
+}
+
+// find looks up key in the map, and returns either a pointer
+// to the node holding key, or a pointer to the location where
+// such a node would go.
+func (m *Map[K, V]) find(key K) **node[K, V] {
+ pn := &m.root
+ for *pn != nil {
+ switch cmp := m.compare(key, (*pn).key); {
+ case cmp < 0:
+ pn = &(*pn).left
+ case cmp > 0:
+ pn = &(*pn).right
+ default:
+ return pn
+ }
+ }
+ return pn
+}
+
+// Insert inserts a new key/value into the map.
+// If the key is already present, the value is replaced.
+// Returns true if this is a new key, false if already present.
+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}
+ return true
+}
+
+// Find returns the value associated with a key, or zero if not present.
+// The found result reports whether the key was found.
+func (m *Map[K, V]) Find(key K) (V, bool) {
+ pn := m.find(key)
+ if *pn == nil {
+ var zero V // see the discussion of zero values, above
+ return zero, false
+ }
+ return (*pn).val, true
+}
+
+// keyValue is a pair of key and value used when iterating.
+type keyValue[K, V any] struct {
+ key K
+ val V
+}
+
+// InOrder returns an iterator that does an in-order traversal of the map.
+func (m *Map[K, V]) InOrder() *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 sending values if sender.Send returns false,
+ // meaning that nothing is listening at the receiver end.
+ return f(n.left) &&
+ // TODO
+ // sender.Send(keyValue[K, V]{n.key, n.val}) &&
+ f(n.right)
+ }
+ go func() {
+ f(m.root)
+ sender.Close()
+ }()
+ return &Iterator{receiver}
+}
+
+// Iterator is used to iterate over the map.
+type Iterator[K, V any] struct {
+ r *chans.Receiver[keyValue[K, V]]
+}
+
+// Next returns the next key and value pair, and a boolean indicating
+// whether they are valid or whether we have reached the end.
+func (it *Iterator[K, V]) Next() (K, V, bool) {
+ keyval, ok := it.r.Next()
+ if !ok {
+ var zerok K
+ var zerov V
+ return zerok, zerov, false
+ }
+ return keyval.key, keyval.val, true
+}
diff --git a/src/go/parser/testdata/metrics.go2 b/src/go/parser/testdata/metrics.go2
new file mode 100644
index 0000000..ef1c66b
--- /dev/null
+++ b/src/go/parser/testdata/metrics.go2
@@ -0,0 +1,58 @@
+package metrics
+
+import "sync"
+
+type Metric1[T comparable] struct {
+ mu sync.Mutex
+ m map[T]int
+}
+
+func (m *Metric1[T]) Add(v T) {
+ m.mu.Lock()
+ defer m.mu.Unlock()
+ if m.m == nil {
+ m.m = make(map[T]int)
+ }
+ m[v]++
+}
+
+type key2[T1, T2 comparable] struct {
+ f1 T1
+ f2 T2
+}
+
+type Metric2[T1, T2 cmp2] struct {
+ mu sync.Mutex
+ m map[key2[T1, T2]]int
+}
+
+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[key[T1, T2]{v1, v2}]++
+}
+
+type key3[T1, T2, T3 comparable] struct {
+ f1 T1
+ f2 T2
+ f3 T3
+}
+
+type Metric3[T1, T2, T3 comparable] struct {
+ mu sync.Mutex
+ m map[key3[T1, T2, T3]]int
+}
+
+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]int)
+ }
+ m[key[T1, T2, T3]{v1, v2, v3}]++
+}
+
+// Repeat for the maximum number of permitted arguments.
diff --git a/src/go/parser/testdata/resolution/issue45136.src b/src/go/parser/testdata/resolution/issue45136.src
new file mode 100644
index 0000000..e1d63d8
--- /dev/null
+++ b/src/go/parser/testdata/resolution/issue45136.src
@@ -0,0 +1,27 @@
+// 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 issue45136
+
+type obj /* =@obj */ struct {
+ name /*=@name */ string
+}
+
+func _() {
+ var foo /* =@foo */ = "foo"
+ obj /* @obj */ ["foo"]
+ obj /* @obj */ .run()
+ obj /* @obj */ {
+ name: foo /* @foo */,
+ }
+ obj /* @obj */ {
+ name: "bar",
+ }.run()
+
+ var _ = File{key: obj /* @obj */ {}}
+ var _ = File{obj /* @obj */ {}}
+
+ []obj /* @obj */ {foo /* @foo */}
+ x /* =@x1 */ := obj /* @obj */{}
+}
diff --git a/src/go/parser/testdata/resolution/issue45160.src b/src/go/parser/testdata/resolution/issue45160.src
new file mode 100644
index 0000000..6be933b
--- /dev/null
+++ b/src/go/parser/testdata/resolution/issue45160.src
@@ -0,0 +1,25 @@
+// 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 issue45160
+
+func mklink1 /* =@mklink1func */() {}
+
+func _() {
+ var tests /* =@tests */ = []dirLinkTest /* @dirLinkTest */ {
+ {
+ mklink1 /* @mklink1func */: func() {},
+ mklink2: func(link /* =@link */, target /* =@target */ string) error {
+ return nil
+ },
+ },
+ }
+}
+
+type dirLinkTest /* =@dirLinkTest */ struct {
+ mklink1 /* =@mklink1field */ func(string, string) error
+ mklink2 /* =@mklink2field */ func(string, string) error
+}
+
+func mklink2 /* =@mklink2func */() {}
diff --git a/src/go/parser/testdata/resolution/resolution.src b/src/go/parser/testdata/resolution/resolution.src
new file mode 100644
index 0000000..a880dd1
--- /dev/null
+++ b/src/go/parser/testdata/resolution/resolution.src
@@ -0,0 +1,63 @@
+// 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 resolution
+
+func f /* =@fdecl */(n /* =@narg */ ast.Node) bool {
+ if n /* =@ninit */, ok /* =@ok */ := n /* @narg */ .(*ast.SelectorExpr); ok /* @ok */ {
+ sel = n /* @ninit */
+ }
+}
+
+type c /* =@cdecl */ map[token.Pos]resolvedObj
+
+func (v /* =@vdecl */ c /* @cdecl */) Visit(node /* =@nodearg */ ast.Node) (w /* =@w */ ast.Visitor) {}
+
+const (
+ basic /* =@basic */ = iota
+ labelOk // =@labelOk
+)
+
+type T /* =@T */ int
+
+func _(count /* =@count */ T /* @T */) {
+ x /* =@x1 */ := c /* @cdecl */{}
+ switch x /* =@x2 */ := x /* @x1 */; x /* =@x3 */ := x /* @x2 */.(type) {
+ case c /* @cdecl */:
+ default:
+ }
+loop /* =@loop */:
+ for {
+ if true {
+ break loop /* @loop */
+ }
+ }
+ select {
+ case err /* =@err1 */ := <-_:
+ return err /* @err1 */
+ case err /* =@err2 */ := <-_:
+ return err /* @err2 */
+ }
+
+ _ = func(p1 /* =@p1 */ int, p2 /* =@p2 */ p1) {
+ closed /* =@closed */ := p1 // @p1
+ shadowed /* =@shadowed1 */ := p2 // @p2
+ _ = func(shadowed /* =@shadowed2 */ p2 /* @p2 */) {
+ closed /* @closed */ = 1
+ shadowed /* @shadowed2 */ = 2
+ }
+ }
+}
+
+func (r /* =@r */ c /* @cdecl */) m(_ r) c /* @cdecl */ { return r /* @r */ }
+
+var cycle /* =@cycle */ = cycle /* @cycle */ + 1
+
+type chain /* =@chain */ struct {
+ next /* =@next */ *chain /* @chain */
+}
+
+func recursive /* =@recursive */() {
+ recursive /* @recursive */ ()
+}
diff --git a/src/go/parser/testdata/resolution/typeparams.go2 b/src/go/parser/testdata/resolution/typeparams.go2
new file mode 100644
index 0000000..0ffecd6
--- /dev/null
+++ b/src/go/parser/testdata/resolution/typeparams.go2
@@ -0,0 +1,43 @@
+// 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 resolution
+
+type List /* =@List */ [E /* =@E */ any] []E // @E
+
+type Pair /* =@Pair */ [L /* =@L */, R /* =@R */ any] struct {
+ Left /* =@Left */ L // @L
+ Right /* =@Right */ R // @R
+ L /* =@Lfield */ int
+}
+
+var _ = Pair /* @Pair */ [int, string]{}
+
+type Addable /* =@Addable */ interface {
+ type int64, float64
+}
+
+func Add /* =@AddDecl */[T /* =@T */ Addable /* @Addable */](l /* =@l */, r /* =@r */ T /* @T */) T /* @T */ {
+ var t /* =@t */ T /* @T */
+ return l /* @l */ + r /* @r */ + t /* @t */
+}
+
+type Receiver /* =@Receiver */[P /* =@P */ any] struct {}
+
+// TODO(rFindley): make a decision on how/whether to resolve identifiers that
+// refer to receiver type parameters, as is the case for the 'P' result
+// parameter below.
+func (r /* =@recv */ Receiver /* @Receiver */ [P]) m() P {}
+
+func f /* =@f */[T1 /* =@T1 */ interface{type []T2 /* @T2 */}, T2 /* =@T2 */ any](
+ x /* =@x */ T1 /* @T1 */, T1 /* =@T1_duplicate */ y, // Note that this is a bug:
+ // the duplicate T1 should
+ // not be allowed.
+ ){
+ // Note that duplicate short var declarations resolve to their alt declaration.
+ x /* @x */ := 0
+ y /* =@y */ := 0
+ T1 /* @T1 */ := 0
+ var t1var /* =@t1var */ T1 /* @T1 */
+}
diff --git a/src/go/parser/testdata/set.go2 b/src/go/parser/testdata/set.go2
new file mode 100644
index 0000000..0da6377
--- /dev/null
+++ b/src/go/parser/testdata/set.go2
@@ -0,0 +1,31 @@
+// Package set implements sets of any type.
+package set
+
+type Set[Elem comparable] map[Elem]struct{}
+
+func Make[Elem comparable]() Set[Elem] {
+ return make(Set(Elem))
+}
+
+func (s Set[Elem]) Add(v Elem) {
+ s[v] = struct{}{}
+}
+
+func (s Set[Elem]) Delete(v Elem) {
+ delete(s, v)
+}
+
+func (s Set[Elem]) Contains(v Elem) bool {
+ _, ok := s[v]
+ return ok
+}
+
+func (s Set[Elem]) Len() int {
+ return len(s)
+}
+
+func (s Set[Elem]) Iterate(f func(Elem)) {
+ for v := range s {
+ f(v)
+ }
+}
diff --git a/src/go/parser/testdata/slices.go2 b/src/go/parser/testdata/slices.go2
new file mode 100644
index 0000000..e060212
--- /dev/null
+++ b/src/go/parser/testdata/slices.go2
@@ -0,0 +1,31 @@
+// Package slices implements various slice algorithms.
+package slices
+
+// Map turns a []T1 to a []T2 using a mapping function.
+func Map[T1, T2 any](s []T1, f func(T1) T2) []T2 {
+ r := make([]T2, len(s))
+ for i, v := range s {
+ r[i] = f(v)
+ }
+ return r
+}
+
+// Reduce reduces a []T1 to a single value using a reduction function.
+func Reduce[T1, T2 any](s []T1, initializer T2, f func(T2, T1) T2) T2 {
+ r := initializer
+ for _, v := range s {
+ r = f(r, v)
+ }
+ return r
+}
+
+// Filter filters values from a slice using a filter function.
+func Filter[T any](s []T, f func(T) bool) []T {
+ var r []T
+ for _, v := range s {
+ if f(v) {
+ r = append(r, v)
+ }
+ }
+ return r
+}
diff --git a/src/go/parser/testdata/sort.go2 b/src/go/parser/testdata/sort.go2
new file mode 100644
index 0000000..88be79f
--- /dev/null
+++ b/src/go/parser/testdata/sort.go2
@@ -0,0 +1,27 @@
+package sort
+
+type orderedSlice[Elem comparable] []Elem
+
+func (s orderedSlice[Elem]) Len() int { return len(s) }
+func (s orderedSlice[Elem]) Less(i, j int) bool { return s[i] < s[j] }
+func (s orderedSlice[Elem]) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+// OrderedSlice sorts the slice s in ascending order.
+// The elements of s must be ordered using the < operator.
+func OrderedSlice[Elem comparable](s []Elem) {
+ sort.Sort(orderedSlice[Elem](s))
+}
+
+type sliceFn[Elem any] struct {
+ s []Elem
+ f 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.f(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 the slice s according to the function f.
+func SliceFn[Elem any](s []Elem, f func(Elem, Elem) bool) {
+ Sort(sliceFn[Elem]{s, f})
+}
diff --git a/src/go/parser/testdata/typeparams.src b/src/go/parser/testdata/typeparams.src
new file mode 100644
index 0000000..1fea23f
--- /dev/null
+++ b/src/go/parser/testdata/typeparams.src
@@ -0,0 +1,17 @@
+// 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 cases for error messages produced while parsing code that uses type
+// parameters, without ParseTypeParams being enabled.
+
+package p
+
+type List[E any /* ERROR "expected ']', found any" */ ] []E
+
+type Pair[L, /* ERROR "expected ']', found ','" */ R any] struct {
+ Left L
+ Right R
+}
+
+var _ = Pair[int, /* ERROR "expected ']' or ':', found ','" */ string]{}