Skip to content

Commit c45c32b

Browse files
committed
go/types: avoid closure allocations in mono check
This CL replaces monoEdge's "report" field with fields "pos" and "typ", and pushes the logic for formatting them into the report loop. This avoids needing to allocate a function closure for each edge. Also tweak a test case so the two type parameters involved in the cycle aren't both "T" so they're easier to understand. Change-Id: I9d392ad1d99a4c5e89da4613084e885149ebad07 Reviewed-on: https://go-review.googlesource.com/c/go/+/360815 Trust: Matthew Dempsky <[email protected]> Run-TryBot: Matthew Dempsky <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Robert Griesemer <[email protected]>
1 parent 1011e26 commit c45c32b

File tree

2 files changed

+24
-20
lines changed

2 files changed

+24
-20
lines changed

src/go/types/mono.go

+23-19
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,11 @@ type monoVertex struct {
7171
}
7272

7373
type monoEdge struct {
74-
dst int
75-
src int
76-
weight int
74+
dst, src int
75+
weight int
7776

78-
// report emits an error describing why this edge exists.
79-
//
80-
// TODO(mdempsky): Avoid requiring a function closure for each edge.
81-
report func(check *Checker)
77+
pos token.Pos
78+
typ Type
8279
}
8380

8481
func (check *Checker) monomorph() {
@@ -139,12 +136,22 @@ func (check *Checker) reportInstanceLoop(v int) {
139136

140137
// TODO(mdempsky): Pivot stack so we report the cycle from the top?
141138

142-
obj := check.mono.vertices[v].obj
143-
check.errorf(obj, _InvalidInstanceCycle, "instantiation cycle:")
139+
obj0 := check.mono.vertices[v].obj
140+
check.errorf(obj0, _InvalidInstanceCycle, "instantiation cycle:")
144141

142+
qf := RelativeTo(check.pkg)
145143
for _, v := range stack {
146144
edge := check.mono.edges[check.mono.vertices[v].pre]
147-
edge.report(check)
145+
obj := check.mono.vertices[edge.dst].obj
146+
147+
switch obj.Type().(type) {
148+
default:
149+
panic("unexpected type")
150+
case *Named:
151+
check.errorf(atPos(edge.pos), _InvalidInstanceCycle, "\t%s implicitly parameterized by %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented
152+
case *TypeParam:
153+
check.errorf(atPos(edge.pos), _InvalidInstanceCycle, "\t%s instantiated as %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented
154+
}
148155
}
149156
}
150157

@@ -190,10 +197,7 @@ func (w *monoGraph) assign(pkg *Package, pos token.Pos, tpar *TypeParam, targ Ty
190197
weight = 0
191198
}
192199

193-
w.addEdge(w.typeParamVertex(tpar), src, weight, func(check *Checker) {
194-
qf := RelativeTo(check.pkg)
195-
check.errorf(atPos(pos), _InvalidInstanceCycle, "\t%s instantiated as %s", tpar.Obj().Name(), TypeString(targ, qf)) // secondary error, \t indented
196-
})
200+
w.addEdge(w.typeParamVertex(tpar), src, weight, pos, targ)
197201
}
198202

199203
// Recursively walk the type argument to find any defined types or
@@ -283,9 +287,7 @@ func (w *monoGraph) localNamedVertex(pkg *Package, named *Named) int {
283287
w.vertices = append(w.vertices, monoVertex{obj: obj})
284288
}
285289

286-
w.addEdge(idx, w.typeParamVertex(tpar), 1, func(check *Checker) {
287-
check.errorf(obj, _InvalidInstanceCycle, "\t%s implicitly parameterized by %s", obj.Name(), elem.Name())
288-
})
290+
w.addEdge(idx, w.typeParamVertex(tpar), 1, obj.Pos(), tpar)
289291
}
290292
}
291293
}
@@ -320,12 +322,14 @@ func (w *monoGraph) typeParamVertex(tpar *TypeParam) int {
320322
return idx
321323
}
322324

323-
func (w *monoGraph) addEdge(dst, src, weight int, report func(check *Checker)) {
325+
func (w *monoGraph) addEdge(dst, src, weight int, pos token.Pos, typ Type) {
324326
// TODO(mdempsky): Deduplicate redundant edges?
325327
w.edges = append(w.edges, monoEdge{
326328
dst: dst,
327329
src: src,
328330
weight: weight,
329-
report: report,
331+
332+
pos: pos,
333+
typ: typ,
330334
})
331335
}

src/go/types/mono_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ var bads = []string{
8484
"func F[T any]() { type U int; F[*U]() }",
8585
"type U[T any] int; func (U[T]) m() { var _ U[*T] }",
8686
"type U[T any] int; func (*U[T]) m() { var _ U[*T] }",
87-
"type U[T any] [unsafe.Sizeof(F[*T])]byte; func F[T any]() { var _ U[T] }",
87+
"type U[T1 any] [unsafe.Sizeof(F[*T1])]byte; func F[T2 any]() { var _ U[T2] }",
8888
"func F[A, B, C, D, E any]() { F[B, C, D, E, *A]() }",
8989
"type U[_ any] int; const X = unsafe.Sizeof(func() { type A[T any] U[A[*T]] })",
9090
"func F[T any]() { type A = *T; F[A]() }",

0 commit comments

Comments
 (0)