mirror of
https://github.com/burrowers/garble.git
synced 2026-04-22 15:47:04 +08:00
fix fieldToStruct for generics instantiated across package boundaries (#1028)
When compiling a package that instantiates a generic type from another package, info.Types only contains the instantiated *types.Named. The *types.Struct case in recordFieldToStruct returns early on instantiated structs (field != field.Origin()), so the origin struct was never recorded in fieldToStruct. At rewrite time, looking up the origin field then failed with "could not find struct for field X". Fix by also recursing into typ.Origin() for instantiated named types, so the uninstantiated struct is visited and its fields are recorded. Fixes #1027.
This commit is contained in:
Vendored
+45
@@ -7,6 +7,15 @@ go 1.23
|
||||
-- garble_main.go --
|
||||
package main
|
||||
|
||||
import "test/main/lib"
|
||||
|
||||
type Blob []byte
|
||||
|
||||
func (b Blob) MarshalBinary() ([]byte, error) { return b, nil }
|
||||
func (b *Blob) UnmarshalBinary(d []byte) error { *b = append((*b)[:0], d...); return nil }
|
||||
|
||||
type Name string
|
||||
|
||||
func main() {
|
||||
GenericFunc[int, int](1, 2)
|
||||
var _ GenericVector[int]
|
||||
@@ -21,6 +30,11 @@ func main() {
|
||||
ga.list = nil
|
||||
var gan genericAliasNamed
|
||||
gan.list = nil
|
||||
|
||||
e := lib.Entry[Name, Blob, *Blob]{Key: "k", Data: Blob("v")}
|
||||
r := lib.Load[Name, Blob, *Blob](e)
|
||||
_ = r.Data.Key
|
||||
_ = r.Data.Value
|
||||
}
|
||||
|
||||
func GenericFunc[GenericParamA, B any](x GenericParamA, y B) {}
|
||||
@@ -97,3 +111,34 @@ func byKeys[T any](m map[string]T) []struct {
|
||||
}
|
||||
|
||||
var _ = byKeys(map[string]int{"one": 1})
|
||||
-- lib/lib.go --
|
||||
package lib
|
||||
|
||||
import "encoding"
|
||||
|
||||
type Pair[Key, Value any] struct {
|
||||
Key Key
|
||||
Value Value
|
||||
}
|
||||
|
||||
type Result[TData any] struct {
|
||||
Data TData
|
||||
Err error
|
||||
}
|
||||
|
||||
type Entry[TKey ~string, TData encoding.BinaryMarshaler, TPtr interface {
|
||||
*TData
|
||||
encoding.BinaryUnmarshaler
|
||||
}] struct {
|
||||
Key TKey
|
||||
Data TData
|
||||
}
|
||||
|
||||
func Load[TKey ~string, TData encoding.BinaryMarshaler, TPtr interface {
|
||||
*TData
|
||||
encoding.BinaryUnmarshaler
|
||||
}](e Entry[TKey, TData, TPtr]) Result[Pair[TKey, TData]] {
|
||||
return Result[Pair[TKey, TData]]{
|
||||
Data: Pair[TKey, TData]{Key: e.Key, Value: e.Data},
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -137,7 +137,7 @@ func recordFieldToStruct(typ types.Type, done map[*types.Named]bool, fieldToStru
|
||||
return
|
||||
}
|
||||
done[typ] = true
|
||||
recordFieldToStruct(typ.Underlying(), done, fieldToStruct)
|
||||
recordFieldToStruct(typ.Origin().Underlying(), done, fieldToStruct)
|
||||
case *types.Struct:
|
||||
for field := range typ.Fields() {
|
||||
if field != field.Origin() {
|
||||
|
||||
Reference in New Issue
Block a user