[ 
https://issues.apache.org/jira/browse/THRIFT-6198?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Jens Geyer updated THRIFT-6198:
-------------------------------
    Description: 
h3. Problem Description

In {{{}t_netstd_generator.cc{}}}, {{collect_extensions_types(t_type* ttype)}} 
gathers types requiring generated extension methods ({{{}DeepCopy{}}}, 
{{{}Equals{}}}, {{{}GetHashCode{}}}).

While struct recursion is guarded by a program-ownership check to prevent 
duplicate signatures (lines 750–758):
{code:cpp}
// Only recurse into structs defined in the current program. Structs from
// included programs are processed by those programs' own generators, which
// generate extension methods for their internal container types. Recursing
// into them here would duplicate those extension method signatures (CS0121).
>if (ttype->get_program() == program_)
{
    t_struct* tstruct = static_cast<t_struct*>(ttype);
    collect_extensions_types(tstruct);
}
{code}
The container branch (lines 763–792) lacks an equivalent guard:
{code:cpp}
if (ttype->is_container())
{
    if( collected_extension_types.find(key) == collected_extension_types.end())
    {
        collected_extension_types[key] = ttype;   // prevent recursion
        ...
{code}
When Program B includes Program A, and both programs define container types 
over a struct from Program A (or typedefs resolving to it):
 # {{ProgramA.Extensions.cs}} generates {{public static List<InnerStruct> 
DeepCopy(this List<InnerStruct> source)}}
 # {{ProgramB.Extensions.cs}} also generates {{public static List<InnerStruct> 
DeepCopy(this List<InnerStruct> source)}}

If both programs share the default namespace (or are imported into the same 
scope / project), C# compilation fails with:
{noformat}
error CS0121: The call is ambiguous between the following methods or 
properties: 'ProgramAExtensions.DeepCopy(List<InnerStruct>)' and 
'ProgramBExtensions.DeepCopy(List<InnerStruct>)'
{noformat}
h3. Steps to Reproduce

1. IDL A ({{{}TypedefStructTest.thrift{}}}):
{code}
InnerStruct { 1: string s }
typedef InnerStruct InnerAlias
struct Outer { 1: list<InnerAlias> inners }
{code}
2. IDL B ({{{}TypedefIncludeTest.thrift{}}}):
{code}
include "TypedefStructTest.thrift"
typedef TypedefStructTest.InnerStruct IncludedAlias
struct HoldsIncluded { 1: list<IncludedAlias> values }
{code}
3. Compile with {{--gen netstd}} and compile the resulting C# code into a 
single assembly/solution.
h3. Expected Behavior

Extension methods for container types should not be duplicated across included 
program extension classes, or container ownership should follow the program 
owning the underlying element type.

  was:
h3. Problem Description
In {{t_netstd_generator.cc}}, {{collect_extensions_types(t_type* ttype)}} 
gathers types requiring generated extension methods ({{DeepCopy}}, {{Equals}}, 
{{GetHashCode}}).

While struct recursion is guarded by a program-ownership check to prevent 
duplicate signatures (lines 750–758):
{code:cpp}
// Only recurse into structs defined in the current program. Structs from
// included programs are processed by those programs' own generators, which
// generate extension methods for their internal container types. Recursing
// into them here would duplicate those extension method signatures (CS0121).
if (ttype->get_program() == program_)
{
    t_struct* tstruct = static_cast<t_struct*>(ttype);
    collect_extensions_types(tstruct);
}
{code}

The container branch (lines 763–792) lacks an equivalent guard:
{code:cpp}
if (ttype->is_container())
{
    if( collected_extension_types.find(key) == collected_extension_types.end())
    {
        collected_extension_types[key] = ttype;   // prevent recursion
        ...
{code}

When Program B includes Program A, and both programs define container types 
over a struct from Program A (or typedefs resolving to it):
# {{ProgramA.Extensions.cs}} generates {{public static List<InnerStruct> 
DeepCopy(this List<InnerStruct> source)}}
# {{ProgramB.Extensions.cs}} also generates {{public static List<InnerStruct> 
DeepCopy(this List<InnerStruct> source)}}

If both programs share the default namespace (or are imported into the same 
scope / project), C# compilation fails with:
{noformat}
error CS0121: The call is ambiguous between the following methods or 
properties: 'ProgramAExtensions.DeepCopy(List<InnerStruct>)' and 
'ProgramBExtensions.DeepCopy(List<InnerStruct>)'
{noformat}

h3. Steps to Reproduce
1. IDL A ({{TypedefStructTest.thrift}}):
{code:thrift}
struct InnerStruct { 1: string s }
typedef InnerStruct InnerAlias
struct Outer { 1: list<InnerAlias> inners }
{code}

2. IDL B ({{TypedefIncludeTest.thrift}}):
{code:thrift}
include "TypedefStructTest.thrift"
typedef TypedefStructTest.InnerStruct IncludedAlias
struct HoldsIncluded { 1: list<IncludedAlias> values }
{code}

3. Compile with {{--gen netstd}} and compile the resulting C# code into a 
single assembly/solution.

h3. Expected Behavior
Extension methods for container types should not be duplicated across included 
program extension classes, or container ownership should follow the program 
owning the underlying element type.


> CS0121 ambiguous extension methods generated for container types referencing 
> included structs
> ---------------------------------------------------------------------------------------------
>
>                 Key: THRIFT-6198
>                 URL: https://issues.apache.org/jira/browse/THRIFT-6198
>             Project: Thrift
>          Issue Type: Bug
>          Components: netstd - Compiler
>            Reporter: Sylwester Lachiewicz
>            Assignee: Jens Geyer
>            Priority: Major
>
> h3. Problem Description
> In {{{}t_netstd_generator.cc{}}}, {{collect_extensions_types(t_type* ttype)}} 
> gathers types requiring generated extension methods ({{{}DeepCopy{}}}, 
> {{{}Equals{}}}, {{{}GetHashCode{}}}).
> While struct recursion is guarded by a program-ownership check to prevent 
> duplicate signatures (lines 750–758):
> {code:cpp}
> // Only recurse into structs defined in the current program. Structs from
> // included programs are processed by those programs' own generators, which
> // generate extension methods for their internal container types. Recursing
> // into them here would duplicate those extension method signatures (CS0121).
> >if (ttype->get_program() == program_)
> {
>     t_struct* tstruct = static_cast<t_struct*>(ttype);
>     collect_extensions_types(tstruct);
> }
> {code}
> The container branch (lines 763–792) lacks an equivalent guard:
> {code:cpp}
> if (ttype->is_container())
> {
>     if( collected_extension_types.find(key) == 
> collected_extension_types.end())
>     {
>         collected_extension_types[key] = ttype;   // prevent recursion
>         ...
> {code}
> When Program B includes Program A, and both programs define container types 
> over a struct from Program A (or typedefs resolving to it):
>  # {{ProgramA.Extensions.cs}} generates {{public static List<InnerStruct> 
> DeepCopy(this List<InnerStruct> source)}}
>  # {{ProgramB.Extensions.cs}} also generates {{public static 
> List<InnerStruct> DeepCopy(this List<InnerStruct> source)}}
> If both programs share the default namespace (or are imported into the same 
> scope / project), C# compilation fails with:
> {noformat}
> error CS0121: The call is ambiguous between the following methods or 
> properties: 'ProgramAExtensions.DeepCopy(List<InnerStruct>)' and 
> 'ProgramBExtensions.DeepCopy(List<InnerStruct>)'
> {noformat}
> h3. Steps to Reproduce
> 1. IDL A ({{{}TypedefStructTest.thrift{}}}):
> {code}
> InnerStruct { 1: string s }
> typedef InnerStruct InnerAlias
> struct Outer { 1: list<InnerAlias> inners }
> {code}
> 2. IDL B ({{{}TypedefIncludeTest.thrift{}}}):
> {code}
> include "TypedefStructTest.thrift"
> typedef TypedefStructTest.InnerStruct IncludedAlias
> struct HoldsIncluded { 1: list<IncludedAlias> values }
> {code}
> 3. Compile with {{--gen netstd}} and compile the resulting C# code into a 
> single assembly/solution.
> h3. Expected Behavior
> Extension methods for container types should not be duplicated across 
> included program extension classes, or container ownership should follow the 
> program owning the underlying element type.



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

Reply via email to