Skip to content

Commit 58072a5

Browse files
pkedyaykevl
authored andcommitted
compiler: fix issue with methods on generic structs
1 parent 5026047 commit 58072a5

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

compiler/compiler.go

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"github.com/tinygo-org/tinygo/compiler/llvmutil"
1919
"github.com/tinygo-org/tinygo/loader"
2020
"golang.org/x/tools/go/ssa"
21+
"golang.org/x/tools/go/types/typeutil"
2122
"tinygo.org/x/go-llvm"
2223
)
2324

@@ -70,7 +71,7 @@ type compilerContext struct {
7071
cu llvm.Metadata
7172
difiles map[string]llvm.Metadata
7273
ditypes map[types.Type]llvm.Metadata
73-
llvmTypes map[types.Type]llvm.Type
74+
llvmTypes typeutil.Map
7475
machine llvm.TargetMachine
7576
targetData llvm.TargetData
7677
intType llvm.Type
@@ -95,7 +96,6 @@ func newCompilerContext(moduleName string, machine llvm.TargetMachine, config *C
9596
DumpSSA: dumpSSA,
9697
difiles: make(map[string]llvm.Metadata),
9798
ditypes: make(map[types.Type]llvm.Metadata),
98-
llvmTypes: make(map[types.Type]llvm.Type),
9999
machine: machine,
100100
targetData: machine.CreateTargetData(),
101101
astComments: map[string]*ast.CommentGroup{},
@@ -329,12 +329,16 @@ func (c *compilerContext) getLLVMRuntimeType(name string) llvm.Type {
329329
// important for named struct types (which should only be created once).
330330
func (c *compilerContext) getLLVMType(goType types.Type) llvm.Type {
331331
// Try to load the LLVM type from the cache.
332-
if t, ok := c.llvmTypes[goType]; ok {
333-
return t
332+
// Note: *types.Named isn't unique when working with generics.
333+
// See https://github.com/golang/go/issues/53914
334+
// This is the reason for using typeutil.Map to lookup LLVM types for Go types.
335+
ival := c.llvmTypes.At(goType)
336+
if ival != nil {
337+
return ival.(llvm.Type)
334338
}
335339
// Not already created, so adding this type to the cache.
336340
llvmType := c.makeLLVMType(goType)
337-
c.llvmTypes[goType] = llvmType
341+
c.llvmTypes.Set(goType, llvmType)
338342
return llvmType
339343
}
340344

@@ -391,7 +395,7 @@ func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {
391395
// self-referencing types such as linked lists.
392396
llvmName := typ.Obj().Pkg().Path() + "." + typ.Obj().Name()
393397
llvmType := c.ctx.StructCreateNamed(llvmName)
394-
c.llvmTypes[goType] = llvmType // avoid infinite recursion
398+
c.llvmTypes.Set(goType, llvmType) // avoid infinite recursion
395399
underlying := c.getLLVMType(st)
396400
llvmType.StructSetBody(underlying.StructElementTypes(), false)
397401
return llvmType

testdata/generics.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ package main
33
func main() {
44
println("add:", Add(3, 5))
55
println("add:", Add(int8(3), 5))
6+
7+
var c C[int]
8+
c.F() // issue 2951
69
}
710

811
type Integer interface {
@@ -12,3 +15,8 @@ type Integer interface {
1215
func Add[T Integer](a, b T) T {
1316
return a + b
1417
}
18+
19+
// Test for https://github.com/tinygo-org/tinygo/issues/2951
20+
type C[V any] struct{}
21+
22+
func (c *C[V]) F() {}

0 commit comments

Comments
 (0)