internal/core/convert: fix panic when encoding pointer-receiver marshalers
When a value type's pointer implements an interface like json.Marshaler,
the implements function correctly returns needAddr=true, but fromGoValue
ignored that return value. The subsequent reflect.TypeAssert on the
non-pointer value returned nil, causing a panic on the method call.
Use the needAddr return from implements to take the address of the value
before the type assertion, matching the intent of the implements API.
Note that encoding/json/v1 does not call pointer-receiver methods on
non-pointer values which are not addressable,
but encoding/json/v2 fixes this inconsistency and always calls them,
even when this incurs an extra allocation. We follow the v2 behavior.
While this is technically a behavior change, it is one where we are
aligning with Go's json/v2 design, and fixing an edge case inconsistency
which very few users should be running into.
If a user really does want the old behavior, they can do so by
wrapping the value in a type which hides the encoding method.
This regression was introduced by me in https://cuelang.org/cl/1226577,
where I did a refactor to reflect.Value by borrowing ideas from json/v2,
but I had forgotten about this edge case of addressable values.
All three non-pointer test cases panic without the fix.
Fixes #4303.
Signed-off-by: Daniel Martí <mvdan@mvdan.cc>
Change-Id: Iee398ffa7d5b8788f6f70bd7e6897cd75a31cdab
Reviewed-on: https://cue.gerrithub.io/c/cue-lang/cue/+/1233358
Unity-Result: CUE porcuepine <cue.porcuepine@gmail.com>
Reviewed-by: Roger Peppe <rogpeppe@gmail.com>
TryBot-Result: CUEcueckoo <cueckoo@cuelang.org>