Sylwester Lachiewicz created THRIFT-6197:
--------------------------------------------

             Summary: Go generator mishandles typedefs, so aliased structs and 
forward-declared typedefs generate code that does not compile
                 Key: THRIFT-6197
                 URL: https://issues.apache.org/jira/browse/THRIFT-6197
             Project: Thrift
          Issue Type: Bug
          Components: Go - Compiler
            Reporter: Sylwester Lachiewicz


The Go generator does not resolve typedefs to their underlying definition when 
it emits field types, so any typedef of a struct, and any typedef used before 
it is declared, produces Go code that does not compile.

Verified with the released 0.24.0 compiler; the generated packages were built 
with Go 1.27 against the current lib/go/thrift.

h3. Case 1: typedef declared after first use

{code}
struct Bar {
  1: optional Foo foo,
}
typedef i32 Foo
{code}

The field takes the underlying type rather than the alias, and the read path 
then assigns a *Foo to it:

{code}
type Foo int32
type Bar struct {
  Foo *int32 `thrift:"foo,1" db:"foo" json:"foo,omitempty"`
}
{code}

{noformat}
t5601.go:108:11: cannot use &temp (value of type *Foo) as *int32 value in 
assignment
{noformat}

This is THRIFT-5601, and the field-type half of it is THRIFT-5489.

h3. Case 2: typedef of a struct in the same file

{code}
struct Inner { 1: required string s }
typedef Inner InnerAlias
struct Outer { 1: optional InnerAlias a }
service Svc { InnerAlias get(1: InnerAlias x) }
{code}

The alias is generated as a pointer type, and the field then adds a second 
pointer:

{code}
type InnerAlias *Inner
...
A *InnerAlias `thrift:"a,1" db:"a" json:"a,omitempty"`
{code}

{noformat}
t4901.go:247:8:  cannot use &Inner{} (value of type *Inner) as *InnerAlias 
value in assignment
t4901.go:248:16: p.A.Read undefined (type *InnerAlias has no field or method 
Read)
t4901.go:282:17: p.A.Write undefined (type *InnerAlias has no field or method 
Write)
t4901.go:298:10: p.A.Equals undefined (type *InnerAlias has no field or method 
Equals)
t4901.go:472:40: cannot use args.X (variable of type *InnerAlias) as InnerAlias 
value in argument to p.handler.Get
{noformat}

This is THRIFT-4901, and the service-signature errors are THRIFT-3491.

h3. Case 3: typedef of a struct from an included file

{code}
// Base.thrift
namespace go a.X.c
struct Foo { 1: required string s }

// Child.thrift
namespace go a.Y.c
include "Base.thrift"
typedef Base.Foo Foo
struct Bar { 1: Foo f }
{code}

{noformat}
Child.go:107:8:  cannot use &c.Foo{} (value of type *"a/X/c".Foo) as *Foo value 
in assignment
Child.go:108:16: p.F.Read undefined (type *Foo has no field or method Read)
Child.go:141:16: p.F.Write undefined (type *Foo has no field or method Write)
{noformat}

This is THRIFT-3037, open since 2015.

h3. Why one ticket

All three come from the same place: the generator decides a field's Go type 
from the typedef itself instead of from the type it resolves to, and separately 
emits a pointer alias for a struct typedef. THRIFT-5601, THRIFT-5489, 
THRIFT-4901, THRIFT-3491 and THRIFT-3037 are five views of that. THRIFT-5463 is 
likely the same, though it was not reproduced here.

A fix should cover, at minimum: a typedef declared after use, a typedef of a 
struct in the same file, a typedef of a struct across an include, and a typedef 
of a container. Note that the THRIFT-5601 fix was reverted once before, so the 
regression coverage matters as much as the fix.




--
This message was sent by Atlassian Jira
(v8.20.10#820010)

Reply via email to