You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@thrift.apache.org by "Sylwester Lachiewicz (Jira)" <ji...@apache.org> on 2026/09/06 18:43:00 UTC

[jira] [Resolved] (THRIFT-6175) Go maps keyed by a struct use pointer identity, so decoded keys never match and Equals compares by address

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