From 479f5c690dbddecd7cf0b961fb0f2eb035b499b4 Mon Sep 17 00:00:00 2001 From: Tim King Date: Tue, 2 May 2023 15:13:33 -0700 Subject: [PATCH] go/ssa: Origin is only available after building Origin of an instantiation is only available after the origin function is done being built. Build the origin on demand if not yet built. Fixes golang/go#59427 Change-Id: I930ae496ce0d814890ea2d947100cdfe6ede059f Reviewed-on: https://go-review.googlesource.com/c/tools/+/491755 gopls-CI: kokoro Reviewed-by: Alan Donovan TryBot-Result: Gopher Robot Run-TryBot: Tim King --- go/ssa/ssa.go | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/go/ssa/ssa.go b/go/ssa/ssa.go index c3471c15673..eeb968130f8 100644 --- a/go/ssa/ssa.go +++ b/go/ssa/ssa.go @@ -1535,12 +1535,25 @@ func (fn *Function) TypeParams() *typeparams.TypeParamList { // from fn.Origin(). func (fn *Function) TypeArgs() []types.Type { return fn.typeargs } -// Origin is the function fn is an instantiation of. Returns nil if fn is not -// an instantiation. +// Origin returns the generic function from which fn was instantiated, +// or nil if fn is not an instantiation. func (fn *Function) Origin() *Function { if fn.parent != nil && len(fn.typeargs) > 0 { - // Nested functions are BUILT at a different time than there instances. - return fn.parent.Origin().AnonFuncs[fn.anonIdx] + // Nested functions are BUILT at a different time than their instances. + // Build declared package if not yet BUILT. This is not an expected use + // case, but is simple and robust. + fn.declaredPackage().Build() + } + return origin(fn) +} + +// origin is the function that fn is an instantiation of. Returns nil if fn is +// not an instantiation. +// +// Precondition: fn and the origin function are done building. +func origin(fn *Function) *Function { + if fn.parent != nil && len(fn.typeargs) > 0 { + return origin(fn.parent).AnonFuncs[fn.anonIdx] } return fn.topLevelOrigin }