]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix panic when refer to method of imported instantiated type
authorCuong Manh Le <cuong.manhle.vn@gmail.com>
Sun, 31 Oct 2021 19:04:13 +0000 (02:04 +0700)
committerCuong Manh Le <cuong.manhle.vn@gmail.com>
Tue, 2 Nov 2021 03:09:01 +0000 (03:09 +0000)
In case of reference to method call of an imported fully-instantiated
type, nameNode.Func will be nil causes checkFetchBody panic. To fix
this, make sure checkFetchBody is only called when Func is not nil.

Fixes #49246

Change-Id: I32e9208385a86d4600d8ebf6f5efd8fca571ea16
Reviewed-on: https://go-review.googlesource.com/c/go/+/360056
Trust: Cuong Manh Le <cuong.manhle.vn@gmail.com>
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Dan Scales <danscales@google.com>
src/cmd/compile/internal/noder/stencil.go
test/typeparam/issue49246.dir/a.go [new file with mode: 0644]
test/typeparam/issue49246.dir/b.go [new file with mode: 0644]
test/typeparam/issue49246.go [new file with mode: 0644]

index 56010a356e685b85b0be03254aa15fed3a528ee7..74281bc479135f0bb1e3e3985c8c9367d98394fb 100644 (file)
@@ -624,7 +624,7 @@ func (g *genInst) getDictOrSubdict(declInfo *instInfo, n ir.Node, nameNode *ir.N
 // yet. If so, it imports the body.
 func checkFetchBody(nameNode *ir.Name) {
        if nameNode.Func.Body == nil && nameNode.Func.Inl != nil {
-               // If there is no body yet but Func.Inl exists, then we can can
+               // If there is no body yet but Func.Inl exists, then we can
                // import the whole generic body.
                assert(nameNode.Func.Inl.Cost == 1 && nameNode.Sym().Pkg != types.LocalPkg)
                typecheck.ImportBody(nameNode.Func)
@@ -638,7 +638,18 @@ func checkFetchBody(nameNode *ir.Name) {
 // with the type arguments shapes. If the instantiated function is not already
 // cached, then it calls genericSubst to create the new instantiation.
 func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth bool) *instInfo {
-       checkFetchBody(nameNode)
+       if nameNode.Func == nil {
+               // If nameNode.Func is nil, this must be a reference to a method of
+               // an imported instantiated type. We will have already called
+               // g.instantiateMethods() on the fully-instantiated type, so
+               // g.instInfoMap[sym] will be non-nil below.
+               rcvr := nameNode.Type().Recv()
+               if rcvr == nil || !deref(rcvr.Type).IsFullyInstantiated() {
+                       base.FatalfAt(nameNode.Pos(), "Unexpected function instantiation %v with no body", nameNode)
+               }
+       } else {
+               checkFetchBody(nameNode)
+       }
 
        // Convert any non-shape type arguments to their shape, so we can reduce the
        // number of instantiations we have to generate. You can actually have a mix
diff --git a/test/typeparam/issue49246.dir/a.go b/test/typeparam/issue49246.dir/a.go
new file mode 100644 (file)
index 0000000..97459ee
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package a
+
+type R[T any] struct{ v T }
+
+func (r R[T]) Self() R[T] { return R[T]{} }
+
+type Fn[T any] func() R[T]
+
+func X() (r R[int]) { return r.Self() }
+
+func Y[T any](a Fn[T]) Fn[int] {
+       return func() (r R[int]) {
+               // No crash: return R[int]{}
+               return r.Self()
+       }
+}
diff --git a/test/typeparam/issue49246.dir/b.go b/test/typeparam/issue49246.dir/b.go
new file mode 100644 (file)
index 0000000..5141b72
--- /dev/null
@@ -0,0 +1,9 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package b
+
+import "./a"
+
+func Crash() { a.Y(a.X)() }
diff --git a/test/typeparam/issue49246.go b/test/typeparam/issue49246.go
new file mode 100644 (file)
index 0000000..87b4ff4
--- /dev/null
@@ -0,0 +1,7 @@
+// compiledir -G=3
+
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package ignored