compiler: fix issue with methods on generic structs
Этот коммит содержится в:
родитель
5026047cde
коммит
58072a5167
2 изменённых файлов: 18 добавлений и 6 удалений
|
@ -18,6 +18,7 @@ import (
|
||||||
"github.com/tinygo-org/tinygo/compiler/llvmutil"
|
"github.com/tinygo-org/tinygo/compiler/llvmutil"
|
||||||
"github.com/tinygo-org/tinygo/loader"
|
"github.com/tinygo-org/tinygo/loader"
|
||||||
"golang.org/x/tools/go/ssa"
|
"golang.org/x/tools/go/ssa"
|
||||||
|
"golang.org/x/tools/go/types/typeutil"
|
||||||
"tinygo.org/x/go-llvm"
|
"tinygo.org/x/go-llvm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ type compilerContext struct {
|
||||||
cu llvm.Metadata
|
cu llvm.Metadata
|
||||||
difiles map[string]llvm.Metadata
|
difiles map[string]llvm.Metadata
|
||||||
ditypes map[types.Type]llvm.Metadata
|
ditypes map[types.Type]llvm.Metadata
|
||||||
llvmTypes map[types.Type]llvm.Type
|
llvmTypes typeutil.Map
|
||||||
machine llvm.TargetMachine
|
machine llvm.TargetMachine
|
||||||
targetData llvm.TargetData
|
targetData llvm.TargetData
|
||||||
intType llvm.Type
|
intType llvm.Type
|
||||||
|
@ -95,7 +96,6 @@ func newCompilerContext(moduleName string, machine llvm.TargetMachine, config *C
|
||||||
DumpSSA: dumpSSA,
|
DumpSSA: dumpSSA,
|
||||||
difiles: make(map[string]llvm.Metadata),
|
difiles: make(map[string]llvm.Metadata),
|
||||||
ditypes: make(map[types.Type]llvm.Metadata),
|
ditypes: make(map[types.Type]llvm.Metadata),
|
||||||
llvmTypes: make(map[types.Type]llvm.Type),
|
|
||||||
machine: machine,
|
machine: machine,
|
||||||
targetData: machine.CreateTargetData(),
|
targetData: machine.CreateTargetData(),
|
||||||
astComments: map[string]*ast.CommentGroup{},
|
astComments: map[string]*ast.CommentGroup{},
|
||||||
|
@ -329,12 +329,16 @@ func (c *compilerContext) getLLVMRuntimeType(name string) llvm.Type {
|
||||||
// important for named struct types (which should only be created once).
|
// important for named struct types (which should only be created once).
|
||||||
func (c *compilerContext) getLLVMType(goType types.Type) llvm.Type {
|
func (c *compilerContext) getLLVMType(goType types.Type) llvm.Type {
|
||||||
// Try to load the LLVM type from the cache.
|
// Try to load the LLVM type from the cache.
|
||||||
if t, ok := c.llvmTypes[goType]; ok {
|
// Note: *types.Named isn't unique when working with generics.
|
||||||
return t
|
// See https://github.com/golang/go/issues/53914
|
||||||
|
// This is the reason for using typeutil.Map to lookup LLVM types for Go types.
|
||||||
|
ival := c.llvmTypes.At(goType)
|
||||||
|
if ival != nil {
|
||||||
|
return ival.(llvm.Type)
|
||||||
}
|
}
|
||||||
// Not already created, so adding this type to the cache.
|
// Not already created, so adding this type to the cache.
|
||||||
llvmType := c.makeLLVMType(goType)
|
llvmType := c.makeLLVMType(goType)
|
||||||
c.llvmTypes[goType] = llvmType
|
c.llvmTypes.Set(goType, llvmType)
|
||||||
return llvmType
|
return llvmType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,7 +395,7 @@ func (c *compilerContext) makeLLVMType(goType types.Type) llvm.Type {
|
||||||
// self-referencing types such as linked lists.
|
// self-referencing types such as linked lists.
|
||||||
llvmName := typ.Obj().Pkg().Path() + "." + typ.Obj().Name()
|
llvmName := typ.Obj().Pkg().Path() + "." + typ.Obj().Name()
|
||||||
llvmType := c.ctx.StructCreateNamed(llvmName)
|
llvmType := c.ctx.StructCreateNamed(llvmName)
|
||||||
c.llvmTypes[goType] = llvmType // avoid infinite recursion
|
c.llvmTypes.Set(goType, llvmType) // avoid infinite recursion
|
||||||
underlying := c.getLLVMType(st)
|
underlying := c.getLLVMType(st)
|
||||||
llvmType.StructSetBody(underlying.StructElementTypes(), false)
|
llvmType.StructSetBody(underlying.StructElementTypes(), false)
|
||||||
return llvmType
|
return llvmType
|
||||||
|
|
8
testdata/generics.go
предоставленный
8
testdata/generics.go
предоставленный
|
@ -3,6 +3,9 @@ package main
|
||||||
func main() {
|
func main() {
|
||||||
println("add:", Add(3, 5))
|
println("add:", Add(3, 5))
|
||||||
println("add:", Add(int8(3), 5))
|
println("add:", Add(int8(3), 5))
|
||||||
|
|
||||||
|
var c C[int]
|
||||||
|
c.F() // issue 2951
|
||||||
}
|
}
|
||||||
|
|
||||||
type Integer interface {
|
type Integer interface {
|
||||||
|
@ -12,3 +15,8 @@ type Integer interface {
|
||||||
func Add[T Integer](a, b T) T {
|
func Add[T Integer](a, b T) T {
|
||||||
return a + b
|
return a + b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test for https://github.com/tinygo-org/tinygo/issues/2951
|
||||||
|
type C[V any] struct{}
|
||||||
|
|
||||||
|
func (c *C[V]) F() {}
|
||||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче