[ 
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)

Reply via email to