From 8709d8aa900927e4eacd464e17e63b6fc0661937 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Mart=C3=AD?= Date: Thu, 14 Sep 2023 12:00:44 +0100 Subject: [PATCH] cue: simplify the reflect checks in Value.Decode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit reflect.Value.CanSet is documented as: A Value can be changed only if it is addressable and was not obtained by the use of unexported struct fields. We call reflect.ValueOf ourselves here, so we cannot have reached for an unexported struct field via reflect.Value.Field. The only other requirement is that the value must be addressable, which can only be met if x was a non-nil pointer that we dereferenced. This was already the expectation that Decode had on x; it just wasn't documented very clearly, but now it is. We can then replace the CanSet check with a check for a non-nil pointer, which exactly matches the logic from APIs like encoding/json.Unmarshal. Signed-off-by: Daniel Martí Change-Id: I919026530c683a2c9b10f1484910f9cb66fee861 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1168928 Unity-Result: CUE porcuepine Reviewed-by: Roger Peppe TryBot-Result: CUEcueckoo --- cue/decode.go | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/cue/decode.go b/cue/decode.go index 03e807376c1..f7a26afbbcd 100644 --- a/cue/decode.go +++ b/cue/decode.go @@ -30,21 +30,18 @@ import ( "cuelang.org/go/internal/core/adt" ) -// Decode initializes x with Value v. If x is a struct, it will validate the -// constraints specified in the field tags. +// Decode initializes the value pointed to by x with Value v. +// An error is returned if x is nil or not a pointer. +// +// If x is a struct, Decode will validate the constraints specified in the field tags. func (v Value) Decode(x interface{}) error { var d decoder w := reflect.ValueOf(x) - switch { - case !reflect.Indirect(w).CanSet(): + if w.Kind() != reflect.Pointer || w.IsNil() { d.addErr(errors.Newf(v.Pos(), "cannot decode into unsettable value")) - - default: - if w.Kind() == reflect.Ptr { - w = w.Elem() - } - d.decode(w, v, false) + return d.errs } + d.decode(w.Elem(), v, false) return d.errs }