mirror of
https://github.com/golang/go
synced 2024-11-26 20:21:25 -07:00
cmd/compile: avoid re-instantiating method that is already imported
We can import an shape-instantiated function/method for inlining purposes. If we are instantiating the methods of a instantiated type that we have seen, and it happens to need a shape instantiation that we have imported, then don't re-create the instantiation, since we will end up with conflicting/duplicate definitions for the instantiation symbol. Instead, we can just use the existing imported instantation, and enter it in the instInfoMap[]. Fixes #50121 Change-Id: I6eeb8786faad71106e261e113048b579afad04fa Reviewed-on: https://go-review.googlesource.com/c/go/+/371414 Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
67917c3d78
commit
5b9207ff67
@ -684,7 +684,22 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe
|
|||||||
}
|
}
|
||||||
info.dictInfo.shapeToBound = make(map[*types.Type]*types.Type)
|
info.dictInfo.shapeToBound = make(map[*types.Type]*types.Type)
|
||||||
|
|
||||||
// genericSubst fills in info.dictParam and info.tparamToBound.
|
if sym.Def != nil {
|
||||||
|
// This instantiation must have been imported from another
|
||||||
|
// package (because it was needed for inlining), so we should
|
||||||
|
// not re-generate it and have conflicting definitions for the
|
||||||
|
// symbol (issue #50121). It will have already gone through the
|
||||||
|
// dictionary transformations of dictPass, so we don't actually
|
||||||
|
// need the info.dictParam and info.shapeToBound info filled in
|
||||||
|
// below. We just set the imported instantiation as info.fun.
|
||||||
|
assert(sym.Pkg != types.LocalPkg)
|
||||||
|
info.fun = sym.Def.(*ir.Name).Func
|
||||||
|
assert(info.fun != nil)
|
||||||
|
g.instInfoMap[sym] = info
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
|
||||||
|
// genericSubst fills in info.dictParam and info.shapeToBound.
|
||||||
st := g.genericSubst(sym, nameNode, shapes, isMeth, info)
|
st := g.genericSubst(sym, nameNode, shapes, isMeth, info)
|
||||||
info.fun = st
|
info.fun = st
|
||||||
g.instInfoMap[sym] = info
|
g.instInfoMap[sym] = info
|
||||||
@ -722,7 +737,7 @@ type subster struct {
|
|||||||
// args shapes. For a method with a generic receiver, it returns an instantiated
|
// args shapes. For a method with a generic receiver, it returns an instantiated
|
||||||
// function type where the receiver becomes the first parameter. For either a generic
|
// function type where the receiver becomes the first parameter. For either a generic
|
||||||
// method or function, a dictionary parameter is the added as the very first
|
// method or function, a dictionary parameter is the added as the very first
|
||||||
// parameter. genericSubst fills in info.dictParam and info.tparamToBound.
|
// parameter. genericSubst fills in info.dictParam and info.shapeToBound.
|
||||||
func (g *genInst) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*types.Type, isMethod bool, info *instInfo) *ir.Func {
|
func (g *genInst) genericSubst(newsym *types.Sym, nameNode *ir.Name, shapes []*types.Type, isMethod bool, info *instInfo) *ir.Func {
|
||||||
var tparams []*types.Type
|
var tparams []*types.Type
|
||||||
if isMethod {
|
if isMethod {
|
||||||
|
22
test/typeparam/issue50121.dir/a.go
Normal file
22
test/typeparam/issue50121.dir/a.go
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// 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
|
||||||
|
|
||||||
|
import (
|
||||||
|
"constraints"
|
||||||
|
"math/rand"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Builder[T constraints.Integer] struct{}
|
||||||
|
|
||||||
|
func (r Builder[T]) New() T {
|
||||||
|
return T(rand.Int())
|
||||||
|
}
|
||||||
|
|
||||||
|
var IntBuilder = Builder[int]{}
|
||||||
|
|
||||||
|
func BuildInt() int {
|
||||||
|
return IntBuilder.New()
|
||||||
|
}
|
18
test/typeparam/issue50121.dir/main.go
Normal file
18
test/typeparam/issue50121.dir/main.go
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
// 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 main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"a"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:noinline
|
||||||
|
func BuildInt() int {
|
||||||
|
return a.BuildInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
BuildInt()
|
||||||
|
}
|
7
test/typeparam/issue50121.go
Normal file
7
test/typeparam/issue50121.go
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// rundir -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
|
Loading…
Reference in New Issue
Block a user