Sylwester Lachiewicz created THRIFT-6175:
--------------------------------------------
Summary: Go maps keyed by a struct use pointer identity, so
decoded keys never match and Equals compares by address
Key: THRIFT-6175
URL: https://issues.apache.org/jira/browse/THRIFT-6175
Project: Thrift
Issue Type: Bug
Components: Go - Compiler
Affects Versions: 0.24.0
Reporter: Sylwester Lachiewicz
The Go generator emits a thrift {{map}} whose key is a struct or exception as
{{map[*K]V}}. Because the key is a pointer, the map is keyed by address rather
than by the key's contents:
* Every key read from the wire is a fresh allocation, so a decoded map can
never be looked up by a value the caller constructs.
* The generated {{Equals}} indexes the other map by pointer, so two identical
messages decoded separately compare unequal.
Reproduce with:
{code}
struct K { 1: i32 a }
struct S { 1: map<K, string> m }
{code}
{{thrift --gen go}} produces {{M map[*K]string}} and an {{Equals}} that does
{{other.M[k]}} with the pointer {{k}}. A round-trip through {{TSerializer}} and
{{TDeserializer}} followed by {{src.Equals(dst)}} returns false.
This is the struct-key half of THRIFT-2063. That ticket's fix represents maps
with container keys (list, set, map) as {{[]thrift.MapEntry[K, V]}} and leaves
struct keys alone because changing them alters the Go type of fields that
compile today.
Proposed change: add a Go generator option {{struct_key_entries}} that routes
struct and exception keys through the same entry-slice representation, so such
a field becomes {{[]thrift.MapEntry[*K, V]}} and {{Equals}} compares key
contents via the key struct's own {{Equals}}. The default output stays
unchanged; a later major release can flip the default.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)