1
0
mirror of https://github.com/golang/go synced 2024-11-24 06:20:02 -07:00

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 <mdempsky@google.com>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Matthew Dempsky 2021-11-02 11:23:34 -07:00
parent 1011e26b9c
commit c45c32b1cd
2 changed files with 24 additions and 20 deletions

View File

@ -71,14 +71,11 @@ type monoVertex struct {
}
type monoEdge struct {
dst int
src int
weight int
dst, src int
weight int
// report emits an error describing why this edge exists.
//
// TODO(mdempsky): Avoid requiring a function closure for each edge.
report func(check *Checker)
pos token.Pos
typ Type
}
func (check *Checker) monomorph() {
@ -139,12 +136,22 @@ func (check *Checker) reportInstanceLoop(v int) {
// TODO(mdempsky): Pivot stack so we report the cycle from the top?
obj := check.mono.vertices[v].obj
check.errorf(obj, _InvalidInstanceCycle, "instantiation cycle:")
obj0 := check.mono.vertices[v].obj
check.errorf(obj0, _InvalidInstanceCycle, "instantiation cycle:")
qf := RelativeTo(check.pkg)
for _, v := range stack {
edge := check.mono.edges[check.mono.vertices[v].pre]
edge.report(check)
obj := check.mono.vertices[edge.dst].obj
switch obj.Type().(type) {
default:
panic("unexpected type")
case *Named:
check.errorf(atPos(edge.pos), _InvalidInstanceCycle, "\t%s implicitly parameterized by %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented
case *TypeParam:
check.errorf(atPos(edge.pos), _InvalidInstanceCycle, "\t%s instantiated as %s", obj.Name(), TypeString(edge.typ, qf)) // secondary error, \t indented
}
}
}
@ -190,10 +197,7 @@ func (w *monoGraph) assign(pkg *Package, pos token.Pos, tpar *TypeParam, targ Ty
weight = 0
}
w.addEdge(w.typeParamVertex(tpar), src, weight, func(check *Checker) {
qf := RelativeTo(check.pkg)
check.errorf(atPos(pos), _InvalidInstanceCycle, "\t%s instantiated as %s", tpar.Obj().Name(), TypeString(targ, qf)) // secondary error, \t indented
})
w.addEdge(w.typeParamVertex(tpar), src, weight, pos, targ)
}
// Recursively walk the type argument to find any defined types or
@ -283,9 +287,7 @@ func (w *monoGraph) localNamedVertex(pkg *Package, named *Named) int {
w.vertices = append(w.vertices, monoVertex{obj: obj})
}
w.addEdge(idx, w.typeParamVertex(tpar), 1, func(check *Checker) {
check.errorf(obj, _InvalidInstanceCycle, "\t%s implicitly parameterized by %s", obj.Name(), elem.Name())
})
w.addEdge(idx, w.typeParamVertex(tpar), 1, obj.Pos(), tpar)
}
}
}
@ -320,12 +322,14 @@ func (w *monoGraph) typeParamVertex(tpar *TypeParam) int {
return idx
}
func (w *monoGraph) addEdge(dst, src, weight int, report func(check *Checker)) {
func (w *monoGraph) addEdge(dst, src, weight int, pos token.Pos, typ Type) {
// TODO(mdempsky): Deduplicate redundant edges?
w.edges = append(w.edges, monoEdge{
dst: dst,
src: src,
weight: weight,
report: report,
pos: pos,
typ: typ,
})
}

View File

@ -84,7 +84,7 @@ var bads = []string{
"func F[T any]() { type U int; F[*U]() }",
"type U[T any] int; func (U[T]) m() { var _ U[*T] }",
"type U[T any] int; func (*U[T]) m() { var _ U[*T] }",
"type U[T any] [unsafe.Sizeof(F[*T])]byte; func F[T any]() { var _ U[T] }",
"type U[T1 any] [unsafe.Sizeof(F[*T1])]byte; func F[T2 any]() { var _ U[T2] }",
"func F[A, B, C, D, E any]() { F[B, C, D, E, *A]() }",
"type U[_ any] int; const X = unsafe.Sizeof(func() { type A[T any] U[A[*T]] })",
"func F[T any]() { type A = *T; F[A]() }",