Sylwester Lachiewicz created THRIFT-6198:
--------------------------------------------
Summary: netstd: 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
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.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)