You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
setField offers the tag to the type's own unmarshaler before parsing by kind. That happens in unmarshalByInterface, which returns a bool and drops the error:
So when UnmarshalText rejects the tag, one of two things follows.
1. The kind-based parse succeeds, and the rejection is invisible.TestSet_FailingUnmarshalerFallsBackToKind pins this: a string-kinded type whose UnmarshalText always fails ends up holding the raw tag, parsed as a plain string, with no error.
2. The kind-based parse also fails, and the error reported since #59 is the kind path's — not the unmarshaler's. For a time.ParseDuration-backed wrapper:
field Timeout: invalid default "garbage": invalid character 'g' looking for beginning of value
where the cause the author wants is time: invalid duration "garbage". The JSON parser gets reported because the type is struct-kinded and json.Unmarshal was the fall-back — a parser that never had a chance on this input, and one the author never opted into.
Why it matters
Two closed PRs were written to get that error out. #45 proposed a new TaggedSetter interface whose method returns an error; #56 proposed calling UnmarshalText from Set and returning its error directly. Both were declined on other grounds, but the complaint underneath them is real, and this is the narrow version of it.
Options
Keep the fall-back; report the unmarshaler's error when the kind path also fails. Remember the error instead of discarding it, and prefer it in the message. No case that succeeds today changes, and TestSet_FailingUnmarshalerFallsBackToKind keeps passing — only the message when everything fails.
What happens
setFieldoffers the tag to the type's own unmarshaler before parsing by kind. That happens inunmarshalByInterface, which returns a bool and drops the error:https://github.com/creasty/defaults/blob/272ac74/defaults.go#L268-L284
So when
UnmarshalTextrejects the tag, one of two things follows.1. The kind-based parse succeeds, and the rejection is invisible.
TestSet_FailingUnmarshalerFallsBackToKindpins this: a string-kinded type whoseUnmarshalTextalways fails ends up holding the raw tag, parsed as a plain string, with no error.2. The kind-based parse also fails, and the error reported since #59 is the kind path's — not the unmarshaler's. For a
time.ParseDuration-backed wrapper:Setreportswhere the cause the author wants is
time: invalid duration "garbage". The JSON parser gets reported because the type is struct-kinded andjson.Unmarshalwas the fall-back — a parser that never had a chance on this input, and one the author never opted into.Why it matters
Two closed PRs were written to get that error out. #45 proposed a new
TaggedSetterinterface whose method returns an error; #56 proposed callingUnmarshalTextfromSetand returning its error directly. Both were declined on other grounds, but the complaint underneath them is real, and this is the narrow version of it.Options
TestSet_FailingUnmarshalerFallsBackToKindkeeps passing — only the message when everything fails.TestSet_FailingUnmarshalerFallsBackToKind: the fall-back is load-bearing for a type whoseUnmarshalTextis stricter than its kind, so tags that work today would start failing.I would take 1. The fall-back is deliberate and worth keeping; it is the misattributed cause that actually misleads.