Skip to content

Commit

Permalink
cmd/compile: avoid re-instantiating method that is already imported
Browse files Browse the repository at this point in the history
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 golang#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>
  • Loading branch information
danscales committed Dec 13, 2021
1 parent 67917c3 commit 5b9207f
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 2 deletions.
19 changes: 17 additions & 2 deletions src/cmd/compile/internal/noder/stencil.go
Original file line number Diff line number Diff line change
Expand Up @@ -684,7 +684,22 @@ func (g *genInst) getInstantiation(nameNode *ir.Name, shapes []*types.Type, isMe
}
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)
info.fun = st
g.instInfoMap[sym] = info
Expand Down Expand Up @@ -722,7 +737,7 @@ type subster struct {
// 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
// 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 {
var tparams []*types.Type
if isMethod {
Expand Down
22 changes: 22 additions & 0 deletions test/typeparam/issue50121.dir/a.go
Original file line number Diff line number Diff line change
@@ -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 changes: 18 additions & 0 deletions test/typeparam/issue50121.dir/main.go
Original file line number Diff line number Diff line change
@@ -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 changes: 7 additions & 0 deletions test/typeparam/issue50121.go
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 5b9207f

Please sign in to comment.