Closed dsnet closed 3 years ago
If you have closure variables in a range statement, this may be #47676.
func MarshalFuncV1[T any](fn func(T) ([]byte, error)) typedMarshaler {
t := reflect.TypeOf((*T)(nil)).Elem()
return typedMarshaler{
typ: t,
fnc: func(mo MarshalOptions, enc *Encoder, va addressableValue) error {
val, err := fn(va.Convert(t).Interface().(T))
if err != nil {
if err == SkipFunc {
err = errors.New("marshal function of type func(T) ([]byte, error) cannot be skipped")
}
// TODO: Avoid wrapping semantic errors.
return &SemanticError{action: "marshal", GoType: t, Err: err}
}
if err := enc.WriteValue(val); err != nil {
// TODO: Avoid wrapping semantic or I/O errors.
return &SemanticError{action: "marshal", JSONKind: RawValue(val).Kind(), GoType: t, Err: err}
}
return nil
},
}
}
func init() {
NewMarshalers(
MarshalFuncV1(func(string) ([]byte, error) {
return []byte("hello"), nil
}),
)
}
Closures are involved, but no range statements. Interestingly the compiler or crashes when calling MarshalFuncV1
in the init
function.
Works with GOEXPERIMENT=unified.
For those who aren't involved with generics work, what's the significance of GOEXPERIMENT=unified?
cmd/compile currently has three frontends: -G=0 is the legacy, pre-generics frontend; -G=3 is the first generics-aware frontend that's currently enabled by default and has some support for stenciling; GOEXPERIMENT=unified is the second generics-aware frontend that I wrote to minimize complexity and hopefully avoid compiler errors.
GOEXPERIMENT=unified is the second generics-aware frontend that I wrote to minimize complexity and hopefully avoid compiler errors.
Thanks for the explanation. Well, this seems like an example bug that favors your experiment :smile:
Here's a fairly minimized case:
package main
func test1[T any](fn func(T) int) {
fn1 := func() {
var i interface{}
val := fn(i.(T))
println(val)
}
println(fn1)
}
func main() {
test1(func(string) int {
return 5
})
}
The key is the function call with an arg that is the result of a '.(T)' type assert, but all inside a closure. Things work fine if the function call is not inside a closure.
@randall77
This is related/similar to issue #47676 . We probably need to do the substitution of the Defn nodes after the body of the function, since they often point into the body being stenciled.
Change https://golang.org/cl/346290 mentions this issue: cmd/compile: fix handling of Defn field during stenciling
Thanks @danscales for the fix! I'm unfortunately hitting another different internal compiler error: #48103.
Using
go version devel go1.18-2c60a99f72 Fri Aug 27 05:13:44 2021 +0000 linux/amd64
When trying to compile some generic code, I get:
Reproduction:
\cc @mdempsky @ianlancetaylor @griesemer