From c45c32b1cd6ba635fda3add12f48766fd6aef5d8 Mon Sep 17 00:00:00 2001 From: Matthew Dempsky Date: Tue, 2 Nov 2021 11:23:34 -0700 Subject: [PATCH] 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 Run-TryBot: Matthew Dempsky TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/go/types/mono.go | 42 +++++++++++++++++++++------------------ src/go/types/mono_test.go | 2 +- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/src/go/types/mono.go b/src/go/types/mono.go index fb1127e959f..d4d884393b9 100644 --- a/src/go/types/mono.go +++ b/src/go/types/mono.go @@ -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, }) } diff --git a/src/go/types/mono_test.go b/src/go/types/mono_test.go index c4c52824276..5df3d493f8a 100644 --- a/src/go/types/mono_test.go +++ b/src/go/types/mono_test.go @@ -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]() }",