Skip to content

Commit 2c1bbe7

Browse files
committed
go/types: add go1.23 iterator methods for 10 exported types
These methods will not be mirrored in types2 until the bootstrap compiler reaches go1.23; therefore range-over-func statements must not be used in code common to types + types2. Fixes #66626 Change-Id: I3c2c15e3652ee95d9aff208d8a188b912ed5bc9a Reviewed-on: https://go-review.googlesource.com/c/go/+/575455 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Robert Findley <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent 0a4215c commit 2c1bbe7

File tree

4 files changed

+204
-3
lines changed

4 files changed

+204
-3
lines changed

api/next/66626.txt

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
pkg go/types, method (*Interface) EmbeddedTypes() iter.Seq[Type] #66626
2+
pkg go/types, method (*Interface) ExplicitMethods() iter.Seq[*Func] #66626
3+
pkg go/types, method (*Interface) Methods() iter.Seq[*Func] #66626
4+
pkg go/types, method (*MethodSet) Methods() iter.Seq[*Selection] #66626
5+
pkg go/types, method (*Named) Methods() iter.Seq[*Func] #66626
6+
pkg go/types, method (*Scope) Children() iter.Seq[*Scope] #66626
7+
pkg go/types, method (*Struct) Fields() iter.Seq[*Var] #66626
8+
pkg go/types, method (*Tuple) Variables() iter.Seq[*Var] #66626
9+
pkg go/types, method (*TypeList) Types() iter.Seq[Type] #66626
10+
pkg go/types, method (*TypeParamList) TypeParams() iter.Seq[*TypeParam] #66626
11+
pkg go/types, method (*Union) Terms() iter.Seq[*Term] #66626
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
2+
All `go/types` data structures that expose sequences using a pair of
3+
methods such as `Len() int` and `At(int) T` now also methods that
4+
return iterators, allowing you to simplify code such as this:
5+
6+
```go
7+
params := fn.Type.(*types.Signature).Params()
8+
for i := 0; i < params.Len(); i++ {
9+
use(params.At(i))
10+
}
11+
```
12+
13+
to this:
14+
15+
```go
16+
for param := range fn.Signature().Params().Variables() {
17+
use(param)
18+
}
19+
```
20+
21+
The methods are:
22+
[`Interface.EmbeddedTypes`](/pkg/go/types#Interface.EmbeddedTypes),
23+
[`Interface.ExplicitMethods`](/pkg/go/types#Interface.ExplicitMethods),
24+
[`Interface.Methods`](/pkg/go/types#Interface.Methods),
25+
[`MethodSet.Methods`](/pkg/go/types#MethodSet.Methods),
26+
[`Named.Methods`](/pkg/go/types#Named.Methods),
27+
[`Scope.Children`](/pkg/go/types#Scope.Children),
28+
[`Struct.Fields`](/pkg/go/types#Struct.Fields),
29+
[`Tuple.Variables`](/pkg/go/types#Tuple.Variables),
30+
[`TypeList.Types`](/pkg/go/types#TypeList.Types),
31+
[`TypeParamList.TypeParams`](/pkg/go/types#TypeParamList.TypeParams),
32+
[`Union.Terms`](/pkg/go/types#Union.Terms).

src/go/types/example_test.go

+2-3
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,8 @@ type I interface { m() byte }
136136
celsius := pkg.Scope().Lookup("Celsius").Type()
137137
for _, t := range []types.Type{celsius, types.NewPointer(celsius)} {
138138
fmt.Printf("Method set of %s:\n", t)
139-
mset := types.NewMethodSet(t)
140-
for i := 0; i < mset.Len(); i++ {
141-
fmt.Println(mset.At(i))
139+
for m := range types.NewMethodSet(t).Methods() {
140+
fmt.Println(m)
142141
}
143142
fmt.Println()
144143
}

src/go/types/iter.go

+159
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,159 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package types
6+
7+
import "iter"
8+
9+
// This file defines go1.23 iterator methods for a variety of data
10+
// types. They are not mirrored to cmd/compile/internal/types2, as
11+
// there is no point doing so until the bootstrap compiler it at least
12+
// go1.23; therefore go1.23-style range statements should not be used
13+
// in code common to types and types2, though clients of go/types are
14+
// free to use them.
15+
16+
// Methods returns a go1.23 iterator over all the methods of an
17+
// interface, ordered by Id.
18+
//
19+
// Example: for m := range t.Methods() { ... }
20+
func (t *Interface) Methods() iter.Seq[*Func] {
21+
return func(yield func(m *Func) bool) {
22+
for i := range t.NumMethods() {
23+
if !yield(t.Method(i)) {
24+
break
25+
}
26+
}
27+
}
28+
}
29+
30+
// ExplicitMethods returns a go1.23 iterator over the explicit methods of
31+
// an interface, ordered by Id.
32+
//
33+
// Example: for m := range t.ExplicitMethods() { ... }
34+
func (t *Interface) ExplicitMethods() iter.Seq[*Func] {
35+
return func(yield func(m *Func) bool) {
36+
for i := range t.NumExplicitMethods() {
37+
if !yield(t.ExplicitMethod(i)) {
38+
break
39+
}
40+
}
41+
}
42+
}
43+
44+
// EmbeddedTypes returns a go1.23 iterator over the types embedded within an interface.
45+
//
46+
// Example: for e := range t.EmbeddedTypes() { ... }
47+
func (t *Interface) EmbeddedTypes() iter.Seq[Type] {
48+
return func(yield func(e Type) bool) {
49+
for i := range t.NumEmbeddeds() {
50+
if !yield(t.EmbeddedType(i)) {
51+
break
52+
}
53+
}
54+
}
55+
}
56+
57+
// Methods returns a go1.23 iterator over the declared methods of a named type.
58+
//
59+
// Example: for m := range t.Methods() { ... }
60+
func (t *Named) Methods() iter.Seq[*Func] {
61+
return func(yield func(m *Func) bool) {
62+
for i := range t.NumMethods() {
63+
if !yield(t.Method(i)) {
64+
break
65+
}
66+
}
67+
}
68+
}
69+
70+
// Children returns a go1.23 iterator over the child scopes nested within scope s.
71+
//
72+
// Example: for child := range scope.Children() { ... }
73+
func (s *Scope) Children() iter.Seq[*Scope] {
74+
return func(yield func(child *Scope) bool) {
75+
for i := range s.NumChildren() {
76+
if !yield(s.Child(i)) {
77+
break
78+
}
79+
}
80+
}
81+
}
82+
83+
// Fields returns a go1.23 iterator over the fields of a struct type.
84+
//
85+
// Example: for field := range s.Fields() { ... }
86+
func (s *Struct) Fields() iter.Seq[*Var] {
87+
return func(yield func(field *Var) bool) {
88+
for i := range s.NumFields() {
89+
if !yield(s.Field(i)) {
90+
break
91+
}
92+
}
93+
}
94+
}
95+
96+
// Variables returns a go1.23 iterator over the variables of a tuple type.
97+
//
98+
// Example: for v := range tuple.Variables() { ... }
99+
func (t *Tuple) Variables() iter.Seq[*Var] {
100+
return func(yield func(v *Var) bool) {
101+
for i := range t.Len() {
102+
if !yield(t.At(i)) {
103+
break
104+
}
105+
}
106+
}
107+
}
108+
109+
// MethodSet returns a go1.23 iterator over the methods of a method set.
110+
//
111+
// Example: for method := range s.Methods() { ... }
112+
func (s *MethodSet) Methods() iter.Seq[*Selection] {
113+
return func(yield func(method *Selection) bool) {
114+
for i := range s.Len() {
115+
if !yield(s.At(i)) {
116+
break
117+
}
118+
}
119+
}
120+
}
121+
122+
// Terms returns a go1.23 iterator over the terms of a union.
123+
//
124+
// Example: for term := range union.Terms() { ... }
125+
func (u *Union) Terms() iter.Seq[*Term] {
126+
return func(yield func(term *Term) bool) {
127+
for i := range u.Len() {
128+
if !yield(u.Term(i)) {
129+
break
130+
}
131+
}
132+
}
133+
}
134+
135+
// TypeParams returns a go1.23 iterator over a list of type parameters.
136+
//
137+
// Example: for tparam := range l.TypeParams() { ... }
138+
func (l *TypeParamList) TypeParams() iter.Seq[*TypeParam] {
139+
return func(yield func(tparam *TypeParam) bool) {
140+
for i := range l.Len() {
141+
if !yield(l.At(i)) {
142+
break
143+
}
144+
}
145+
}
146+
}
147+
148+
// Types returns a go1.23 iterator over the elements of a list of types.
149+
//
150+
// Example: for t := range l.Types() { ... }
151+
func (l *TypeList) Types() iter.Seq[Type] {
152+
return func(yield func(t Type) bool) {
153+
for i := range l.Len() {
154+
if !yield(l.At(i)) {
155+
break
156+
}
157+
}
158+
}
159+
}

0 commit comments

Comments
 (0)