From 9023784da3d35379b606168f8bafd8b1a27551c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Petr=20Balv=C3=ADn?= Date: Sat, 19 Sep 2026 02:40:51 +0200 Subject: [PATCH] fix(decode): decode into a defined string or bool type Assisted-by: DeepSeek V4.1 Flash --- CHANGELOG.md | 7 +++++++ decode.go | 5 ++++- decode_test.go | 22 ++++++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8923205..1eb3480 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -23,6 +23,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 every major version 2 module: imports change to `sourcedock.dev/petrbalvin/interpres/v2`. +### Fixed + +- Decoding into a defined type whose underlying kind is string or bool, such + as `type Name string`, panicked instead of storing the value, because a + value of the predeclared type is not assignable to a defined type and the + decoder assigned it without a conversion. + ## [1.1.0] - 2026-09-18 ### Added diff --git a/decode.go b/decode.go index 39ee1fe..e9cd0cd 100644 --- a/decode.go +++ b/decode.go @@ -202,7 +202,10 @@ func setBasic(dst, val reflect.Value, kind string) error { if dst.Kind() != val.Kind() { return fmt.Errorf("interpres: cannot assign %s to %s", kind, dst.Type()) } - dst.Set(val) + // Convert rather than assign: a value of the predeclared type is not + // assignable to a defined type of the same kind, so a plain Set panics on + // a destination such as `type Name string`. + dst.Set(val.Convert(dst.Type())) return nil } diff --git a/decode_test.go b/decode_test.go index 99cacc3..4e29b83 100644 --- a/decode_test.go +++ b/decode_test.go @@ -725,3 +725,25 @@ func TestDecodeErrorOnMapDestination(t *testing.T) { t.Fatalf("Path = %v", de.Path) } } + +func TestUnmarshalIntoDefinedScalarTypes(t *testing.T) { + // A defined type whose underlying kind is string or bool takes the value. + // A bare reflect Set panics on such a type, because a string is not + // assignable to a defined string type without a conversion. + type Name string + type Flag bool + type Cfg struct { + N Name `toml:"n"` + F Flag `toml:"f"` + } + var cfg Cfg + if err := Unmarshal([]byte("n = \"x\"\nf = true\n"), &cfg); err != nil { + t.Fatalf("unmarshal: %v", err) + } + if cfg.N != "x" { + t.Errorf("N = %q, want \"x\"", cfg.N) + } + if !cfg.F { + t.Error("F = false, want true") + } +}