Closed mpl closed 1 year ago
Interestingly, if I revert my "little changes" to the AsStruct method signature, we get a different failure, so they are more important than I thought:
package main
import (
"bytes"
"encoding/json"
"errors"
"net/netip"
"reflect"
)
func unmarshalJSON[T any](b []byte, x *[]T) error {
if *x != nil {
return errors.New("already initialized")
}
if len(b) == 0 {
return nil
}
return json.Unmarshal(b, x)
}
func SliceOfViews[T ViewCloner[T, V], V StructView[T]](x []T) SliceView[T, V] {
return SliceView[T, V]{x}
}
type StructView[T any] interface {
Valid() bool
// AsStruct(T) anystruct
AsStruct() T
}
type SliceView[T ViewCloner[T, V], V StructView[T]] struct {
ж []T
}
type ViewCloner[T any, V StructView[T]] interface {
View() V
Clone() T
}
func (s SliceView[T, V]) MarshalJSON() ([]byte, error) { return json.Marshal(s.ж) }
func (s *SliceView[T, V]) UnmarshalJSON(b []byte) error { return unmarshalJSON(b, &s.ж) }
type Slice[T any] struct {
ж []T
}
func (v Slice[T]) MarshalJSON() ([]byte, error) { return json.Marshal(v.ж) }
func (v *Slice[T]) UnmarshalJSON(b []byte) error { return unmarshalJSON(b, &v.ж) }
func StructOf[T any](x []T) Slice[T] {
return Slice[T]{x}
}
type IPPrefixSlice struct {
ж Slice[netip.Prefix]
}
type viewStruct struct {
Int int
Strings Slice[string]
StringsPtr *Slice[string] `json:",omitempty"`
}
type viewClonerImpl string
func (vci viewClonerImpl) View() structViewImpl {
return structViewImpl(vci)
}
func (vci viewClonerImpl) Clone() viewClonerImpl {
return vci + "-clone"
}
/*
type anyStruct struct {
f interface{}
}
*/
type structViewImpl string
func (sv structViewImpl) Valid() bool {
return true
}
/*
func (sv structViewImpl) AsStruct(T viewClonerImpl) anyStruct {
return anyStruct{
f: T,
}
}
*/
func (sv structViewImpl) AsStruct() viewClonerImpl {
return viewClonerImpl(sv)
}
func main() {
ss := StructOf([]string{"bar"})
in := viewStruct{
Int: 1234,
Strings: ss,
StringsPtr: &ss,
}
var buf bytes.Buffer
encoder := json.NewEncoder(&buf)
encoder.SetIndent("", "")
err1 := encoder.Encode(&in)
b := buf.Bytes()
var got viewStruct
err2 := json.Unmarshal(b, &got)
println(err1 == nil, err2 == nil, reflect.DeepEqual(got, in))
t := viewClonerImpl("hello2")
sov := SliceOfViews[viewClonerImpl, structViewImpl]([]viewClonerImpl{t})
println(sov.ж[0].View())
println(sov.ж[0].Clone().View())
}
// Output:
// true true true
// hello2
// hello2-clone
% yaegi run ./issue-1460.go
run: ./issue-1460.go:118:9: not a generic type: func([]main.T) main.SliceView
This is now fixed by #1489, including the last variant you proposed.
I'm sorry, I closed it too early as #1489 is not yet merged
The following program
sample.go
triggers an unexpected resultExpected result
Got
Yaegi Version
on top of https://github.com/traefik/yaegi/pull/1489
Additional Notes
I built upon the ./_test/issue-1460.go file in https://github.com/traefik/yaegi/pull/1489 , so that the defined generic types would actually be instantiated and used in the main.
I also changed some small details like the signature of the AsStruct func (just so that it would make more sense), but I do not think they are relevant to the failure.