Skip to content

Commit a45457d

Browse files
committed
cmd/compile: fix panic when refer to method of imported instantiated type
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 <[email protected]> Trust: Dan Scales <[email protected]> Run-TryBot: Cuong Manh Le <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Dan Scales <[email protected]>
1 parent a59e332 commit a45457d

File tree

4 files changed

+49
-2
lines changed

4 files changed

+49
-2
lines changed

src/cmd/compile/internal/noder/stencil.go

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -624,7 +624,7 @@ func (g *genInst) getDictOrSubdict(declInfo *instInfo, n ir.Node, nameNode *ir.N
624624
// yet. If so, it imports the body.
625625
func checkFetchBody(nameNode *ir.Name) {
626626
if nameNode.Func.Body == nil && nameNode.Func.Inl != nil {
627-
// If there is no body yet but Func.Inl exists, then we can can
627+
// If there is no body yet but Func.Inl exists, then we can
628628
// import the whole generic body.
629629
assert(nameNode.Func.Inl.Cost == 1 && nameNode.Sym().Pkg != types.LocalPkg)
630630
typecheck.ImportBody(nameNode.Func)
@@ -638,7 +638,18 @@ func checkFetchBody(nameNode *ir.Name) {
638638
// with the type arguments shapes. If the instantiated function is not already
639639
// cached, then it calls genericSubst to create the new instantiation.
640640
func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMeth bool) *instInfo {
641-
checkFetchBody(nameNode)
641+
if nameNode.Func == nil {
642+
// If nameNode.Func is nil, this must be a reference to a method of
643+
// an imported instantiated type. We will have already called
644+
// g.instantiateMethods() on the fully-instantiated type, so
645+
// g.instInfoMap[sym] will be non-nil below.
646+
rcvr := nameNode.Type().Recv()
647+
if rcvr == nil || !deref(rcvr.Type).IsFullyInstantiated() {
648+
base.FatalfAt(nameNode.Pos(), "Unexpected function instantiation %v with no body", nameNode)
649+
}
650+
} else {
651+
checkFetchBody(nameNode)
652+
}
642653

643654
// Convert any non-shape type arguments to their shape, so we can reduce the
644655
// number of instantiations we have to generate. You can actually have a mix

test/typeparam/issue49246.dir/a.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package a
6+
7+
type R[T any] struct{ v T }
8+
9+
func (r R[T]) Self() R[T] { return R[T]{} }
10+
11+
type Fn[T any] func() R[T]
12+
13+
func X() (r R[int]) { return r.Self() }
14+
15+
func Y[T any](a Fn[T]) Fn[int] {
16+
return func() (r R[int]) {
17+
// No crash: return R[int]{}
18+
return r.Self()
19+
}
20+
}

test/typeparam/issue49246.dir/b.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
// Copyright 2021 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
package b
6+
7+
import "./a"
8+
9+
func Crash() { a.Y(a.X)() }

test/typeparam/issue49246.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// compiledir -G=3
2+
3+
// Copyright 2021 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package ignored

0 commit comments

Comments
 (0)