diff --git a/examples/178-any-to-string-optional.sx b/examples/178-any-to-string-optional.sx new file mode 100644 index 0000000..3fb45c4 --- /dev/null +++ b/examples/178-any-to-string-optional.sx @@ -0,0 +1,31 @@ +// any_to_string didn't handle optionals. A struct field of type `?T` +// printed as `` (any_to_string's "no case matched" default) +// because there was no `case optional:` arm, and no dispatch table +// entry mapping `?T` TypeIds to the optional category. +// +// The variadic auto-unwrap path (packVariadicCallArgs) papered over +// this for direct `print("{}\n", opt)` calls — it stringified +// optionals to either the inner value's repr or `"null"` BEFORE +// boxing as Any. But anywhere else that boxes an optional and reads +// it back through any_to_string (struct field printing, +// `xx opt : Any`, future user code) hit the `` floor. +// +// Locks in the fix: each ?T variant routes through `case optional:` +// → `optional_to_string(cast(type) val)` → either the inner value's +// `any_to_string` representation or the literal `"null"`. + +#import "modules/std.sx"; + +S :: struct { + a: ?s64; + b: ?string; + c: ?bool; +} + +main :: () { + s1 := S.{ a = 42, b = "hi", c = true }; + print("{}\n", s1); + s2 := S.{ a = null, b = null, c = null }; + print("{}\n", s2); + 0; +} diff --git a/tests/expected/178-any-to-string-optional.exit b/tests/expected/178-any-to-string-optional.exit new file mode 100644 index 0000000..573541a --- /dev/null +++ b/tests/expected/178-any-to-string-optional.exit @@ -0,0 +1 @@ +0 diff --git a/tests/expected/178-any-to-string-optional.txt b/tests/expected/178-any-to-string-optional.txt new file mode 100644 index 0000000..af1e77f --- /dev/null +++ b/tests/expected/178-any-to-string-optional.txt @@ -0,0 +1,2 @@ +S{a: 42, b: hi, c: true} +S{a: null, b: null, c: null}