traefik / yaegi

Yaegi is Another Elegant Go Interpreter
https://pkg.go.dev/github.com/traefik/yaegi
Apache License 2.0
7.1k stars 351 forks source link

generic declaration with multiple type parameters #1460

Closed mvertes closed 2 years ago

mvertes commented 2 years ago

The following program sample.go triggers an unexpected result

package main

import (
    "bytes"
    "encoding/json"
    "errors"
    "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)
}   

type StructView[T any] interface {
    Valid() bool
    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 SliceOfViews[T ViewCloner[T, V], V StructView[T]](x []T) SliceView[T, V] {
    return SliceView[T, V]{x}
}   

func (v SliceView[T, V]) MarshalJSON() ([]byte, error) { return json.Marshal(v.ж) }

func (v *SliceView[T, V]) UnmarshalJSON(b []byte) error { return unmarshalJSON(b, &v.ж) }

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 SliceOf[T any](x []T) Slice[T] {
    return Slice[T]{x}
}   

type viewStruct struct {
    Int        int
    Strings    Slice[string]
    StringsPtr *Slice[string] `json:",omitempty"`
}   

func main() {
    ss := SliceOf([]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))
}

Expected result

$ go run ./sample.go
true true true

Got

$ yaegi ./sample.go
run: ./sample.go:34:21: type definition not implemented: indexListExpr

Yaegi Version

v0.14.2

Additional Notes

No response