[
https://issues.apache.org/jira/browse/THRIFT-6175?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Sylwester Lachiewicz resolved THRIFT-6175.
------------------------------------------
Fix Version/s: 0.25.0
Assignee: Sylwester Lachiewicz
Resolution: Fixed
Fixed on master by https://github.com/apache/thrift/pull/3788 (commit
29e4c2372).
The Go generator gains a {{struct_key_entries}} option. With it, a map whose
key is a struct, union or exception is generated as {{[]thrift.MapEntry[K, V]}}
instead of {{map[*K]V}}, so decoded keys compare by value rather than by
pointer identity. The option is opt-in because the generated field type
changes; existing code that does not pass it is unaffected.
Usage:
{code}
thrift --gen go:struct_key_entries my.thrift
{code}
Follow-up: THRIFT-6195 covers {{Equals}} being order-sensitive over these entry
slices and over sets.
> 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
> Assignee: Sylwester Lachiewicz
> Priority: Major
> Fix For: 0.25.0
>
> Time Spent: 1h 50m
> Remaining Estimate: 0h
>
> 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)