From 198cae37294c48f180c54b9f66617d821e185fdc Mon Sep 17 00:00:00 2001
From: Tim King <taking@google.com>
Date: Wed, 9 Mar 2022 18:36:09 -0800
Subject: [PATCH] go/ssa: split pkg() into different cases for *Package and
 *types.Package

Splits (*Function).pkg() into different cases for returning a *Package and the *types.Package.

Updates golang/go#48525

Change-Id: I1c59679c5acd898cf2009a2e3a0ea96b62f82a06
Reviewed-on: https://go-review.googlesource.com/c/tools/+/391334
Reviewed-by: Zvonimir Pavlinovic <zpavlinovic@google.com>
Run-TryBot: Tim King <taking@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Trust: Tim King <taking@google.com>
---
 go/ssa/func.go   | 27 ++++++++++++++++++++++-----
 go/ssa/print.go  | 18 +++++++++---------
 go/ssa/sanity.go |  4 ++--
 3 files changed, 33 insertions(+), 16 deletions(-)

diff --git a/go/ssa/func.go b/go/ssa/func.go
index 03eb86929e0..8fc089e5d18 100644
--- a/go/ssa/func.go
+++ b/go/ssa/func.go
@@ -414,7 +414,7 @@ func (f *Function) RelString(from *types.Package) string {
 
 	// Package-level function?
 	// Prefix with package name for cross-package references only.
-	if p := f.pkg(); p != nil && p != from {
+	if p := f.relPkg(); p != nil && p != from {
 		return fmt.Sprintf("%s.%s", p.Path(), f.name)
 	}
 
@@ -442,9 +442,26 @@ func writeSignature(buf *bytes.Buffer, from *types.Package, name string, sig *ty
 	types.WriteSignature(buf, sig, types.RelativeTo(from))
 }
 
-func (f *Function) pkg() *types.Package {
-	if f.Pkg != nil {
-		return f.Pkg.Pkg
+// declaredPackage returns the package fn is declared in or nil if the
+// function is not declared in a package.
+func (fn *Function) declaredPackage() *Package {
+	switch {
+	case fn.Pkg != nil:
+		return fn.Pkg // non-generic function
+		// generics:
+	// case fn.Origin != nil:
+	// 	return fn.Origin.pkg // instance of a named generic function
+	case fn.parent != nil:
+		return fn.parent.declaredPackage() // instance of an anonymous [generic] function
+	default:
+		return nil // function is not declared in a package, e.g. a wrapper.
+	}
+}
+
+// relPkg returns types.Package fn is printed in relationship to.
+func (fn *Function) relPkg() *types.Package {
+	if p := fn.declaredPackage(); p != nil {
+		return p.Pkg
 	}
 	return nil
 }
@@ -479,7 +496,7 @@ func WriteFunction(buf *bytes.Buffer, f *Function) {
 		fmt.Fprintf(buf, "# Recover: %s\n", f.Recover)
 	}
 
-	from := f.pkg()
+	from := f.relPkg()
 
 	if f.FreeVars != nil {
 		buf.WriteString("# Free variables:\n")
diff --git a/go/ssa/print.go b/go/ssa/print.go
index 5995f83af70..d0f3bbf7e11 100644
--- a/go/ssa/print.go
+++ b/go/ssa/print.go
@@ -28,7 +28,7 @@ import (
 func relName(v Value, i Instruction) string {
 	var from *types.Package
 	if i != nil {
-		from = i.Parent().pkg()
+		from = i.Parent().relPkg()
 	}
 	switch v := v.(type) {
 	case Member: // *Function or *Global
@@ -66,12 +66,12 @@ func relString(m Member, from *types.Package) string {
 // It never appears in disassembly, which uses Value.Name().
 
 func (v *Parameter) String() string {
-	from := v.Parent().pkg()
+	from := v.Parent().relPkg()
 	return fmt.Sprintf("parameter %s : %s", v.Name(), relType(v.Type(), from))
 }
 
 func (v *FreeVar) String() string {
-	from := v.Parent().pkg()
+	from := v.Parent().relPkg()
 	return fmt.Sprintf("freevar %s : %s", v.Name(), relType(v.Type(), from))
 }
 
@@ -86,7 +86,7 @@ func (v *Alloc) String() string {
 	if v.Heap {
 		op = "new"
 	}
-	from := v.Parent().pkg()
+	from := v.Parent().relPkg()
 	return fmt.Sprintf("%s %s (%s)", op, relType(deref(v.Type()), from), v.Comment)
 }
 
@@ -160,7 +160,7 @@ func (v *UnOp) String() string {
 }
 
 func printConv(prefix string, v, x Value) string {
-	from := v.Parent().pkg()
+	from := v.Parent().relPkg()
 	return fmt.Sprintf("%s %s <- %s (%s)",
 		prefix,
 		relType(v.Type(), from),
@@ -191,7 +191,7 @@ func (v *MakeClosure) String() string {
 }
 
 func (v *MakeSlice) String() string {
-	from := v.Parent().pkg()
+	from := v.Parent().relPkg()
 	return fmt.Sprintf("make %s %s %s",
 		relType(v.Type(), from),
 		relName(v.Len, v),
@@ -223,12 +223,12 @@ func (v *MakeMap) String() string {
 	if v.Reserve != nil {
 		res = relName(v.Reserve, v)
 	}
-	from := v.Parent().pkg()
+	from := v.Parent().relPkg()
 	return fmt.Sprintf("make %s %s", relType(v.Type(), from), res)
 }
 
 func (v *MakeChan) String() string {
-	from := v.Parent().pkg()
+	from := v.Parent().relPkg()
 	return fmt.Sprintf("make %s %s", relType(v.Type(), from), relName(v.Size, v))
 }
 
@@ -273,7 +273,7 @@ func (v *Next) String() string {
 }
 
 func (v *TypeAssert) String() string {
-	from := v.Parent().pkg()
+	from := v.Parent().relPkg()
 	return fmt.Sprintf("typeassert%s %s.(%s)", commaOk(v.CommaOk), relName(v.X, v), relType(v.AssertedType, from))
 }
 
diff --git a/go/ssa/sanity.go b/go/ssa/sanity.go
index 1d4e20f6a2d..6e65d760d78 100644
--- a/go/ssa/sanity.go
+++ b/go/ssa/sanity.go
@@ -409,8 +409,8 @@ func (s *sanity) checkFunction(fn *Function) bool {
 		s.errorf("nil Prog")
 	}
 
-	_ = fn.String()            // must not crash
-	_ = fn.RelString(fn.pkg()) // must not crash
+	_ = fn.String()               // must not crash
+	_ = fn.RelString(fn.relPkg()) // must not crash
 
 	// All functions have a package, except delegates (which are
 	// shared across packages, or duplicated as weak symbols in a