Skip to content

Support open generics in polymorphic serialization in System.Text.Json#127318

Draft
Copilot wants to merge 1 commit into
mainfrom
copilot/support-open-generics-serialization
Draft

Support open generics in polymorphic serialization in System.Text.Json#127318
Copilot wants to merge 1 commit into
mainfrom
copilot/support-open-generics-serialization

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 23, 2026

  • Add SYSLIB1227 source generator diagnostic tests for open generic derived types
  • OpenGenericDerivedType_SupportedPattern_CompileSuccessfully
  • OpenGenericDerivedType_WrappedTypeArgs_WarnsWithSYSLIB1227
  • OpenGenericDerivedType_ArityMismatch_WarnsWithSYSLIB1227
  • OpenGenericDerivedType_NonGenericBase_WarnsWithSYSLIB1227
  • OpenGenericDerivedType_SYSLIB1227_IsPragmaSuppressible
  • All reviewer feedback addressed
  • All review threads resolved

Copilot AI requested review from Copilot and removed request for Copilot April 23, 2026 11:43
Copilot AI requested review from Copilot and removed request for Copilot April 23, 2026 12:23
Copilot AI changed the title [WIP] Support open generics in polymorphic serialization Support open generics in polymorphic serialization in System.Text.Json Apr 23, 2026
Copilot AI requested a review from eiriktsarpalis April 23, 2026 12:34
Copy link
Copy Markdown
Member

@eiriktsarpalis eiriktsarpalis left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comment thread docs/project/list-of-diagnostics.md Outdated
Comment thread src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs Outdated
Copilot AI requested review from Copilot and removed request for Copilot April 23, 2026 17:14
Copilot AI requested a review from eiriktsarpalis April 23, 2026 17:16
Copilot AI requested review from Copilot and removed request for Copilot April 24, 2026 17:21
Copilot AI requested a review from eiriktsarpalis April 24, 2026 17:23
Copilot AI review requested due to automatic review settings April 27, 2026 14:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 58 out of 58 changed files in this pull request and generated 1 comment.

Comment thread src/libraries/System.Text.Json/gen/JsonSourceGenerator.Parser.cs
@eiriktsarpalis
Copy link
Copy Markdown
Member

@copilot Separately, please add a test explicitly prohibiting use of Derived<T> : Base<T, int> which is an invalid derived type declaration.

Copilot AI requested review from Copilot and removed request for Copilot April 27, 2026 16:16
Copy link
Copy Markdown
Contributor Author

Copilot AI commented Apr 27, 2026

@copilot Separately, please add a test explicitly prohibiting use of Derived<T> : Base<T, int> which is an invalid derived type declaration.

Added in 28e3282. OpenGenericDerivedType_ArityMismatch_ThrowsInvalidOperationException validates that Derived<T> : Base<T, int> throws InvalidOperationException. The arity check at matchingBaseArgs.Length != derivedTypeParams.Length in TryResolveOpenGenericDerivedType rejects this — the matching base has 2 type args but the derived type has only 1 type parameter.

@dotnet-policy-service
Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @dotnet/area-system-text-json
See info in area-owners.md if you want to be subscribed.

Copilot AI requested review from Copilot and removed request for Copilot May 28, 2026 13:36
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 23 out of 23 changed files in this pull request and generated 4 comments.

Comment on lines +1091 to +1095
if (baseDef.TypeKind == TypeKind.Interface)
{
foreach (INamedTypeSymbol iface in derivedDef.AllInterfaces)
{
if (SymbolEqualityComparer.Default.Equals(iface.OriginalDefinition, baseDef))
Comment on lines +196 to +220
static Type? FindMatchingBaseType(Type derivedType, Type baseTypeDefinition)
{
if (baseTypeDefinition.IsInterface)
{
foreach (Type iface in derivedType.GetInterfaces())
{
if (iface.IsGenericType && iface.GetGenericTypeDefinition() == baseTypeDefinition)
{
return iface;
}
}
}
else
{
for (Type? current = derivedType.BaseType; current is not null; current = current.BaseType)
{
if (current.IsGenericType && current.GetGenericTypeDefinition() == baseTypeDefinition)
{
return current;
}
}
}

return null;
}
Comment on lines +147 to +156
if (attr.DerivedType is { IsGenericTypeDefinition: true })
{
// Open generic derived types are resolved by the reflection resolver
// to closed types, so we can't compare them directly.
Assert.False(derivedType.DerivedType.IsGenericTypeDefinition);
}
else
{
Assert.Equal(attr.DerivedType, derivedType.DerivedType);
}
Comment on lines +1191 to +1193
[Fact]
public void OpenGenericDerivedType_WrappedTypeArgs_WarnsWithSYSLIB1229()
{
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 25 out of 25 changed files in this pull request and generated 4 comments.

Comment on lines +147 to +156
if (attr.DerivedType is { IsGenericTypeDefinition: true })
{
// Open generic derived types are resolved by the reflection resolver
// to closed types, so we can't compare them directly.
Assert.False(derivedType.DerivedType.IsGenericTypeDefinition);
}
else
{
Assert.Equal(attr.DerivedType, derivedType.DerivedType);
}
Comment on lines +349 to +357
if (type is IArrayTypeSymbol array)
{
ITypeSymbol substituted = compilation.SubstituteTypeParameters(array.ElementType, substitution);
return SymbolEqualityComparer.Default.Equals(substituted, array.ElementType)
? type
: compilation.CreateArrayTypeSymbol(substituted, array.Rank);
}

return type;
Comment on lines +683 to +685
<data name="Polymorphism_OpenGeneric_Reason_ConstraintViolation" xml:space="preserve">
<value>the constraint on type parameter '{0}' is not satisfied by '{1}'</value>
</data>
Comment thread docs/project/list-of-diagnostics.md Outdated
Comment on lines +274 to +277
| __`SYSLIB1226`__ | 'JsonIgnoreCondition.Always' is not valid on type-level 'JsonIgnoreAttribute' annotations. |
| __`SYSLIB1227`__ | Union case types cannot be unambiguously classified by JSON value type. |
| __`SYSLIB1228`__ | Union type shape is not a valid C# union. |
| __`SYSLIB1229`__ | _`SYSLIB1220`-`SYSLIB1229` reserved for System.Text.Json.SourceGeneration._ |
| __`SYSLIB1229`__ | Open generic derived type is not supported for the polymorphic base type. |
Implements expanded open-generic derived-type support in System.Text.Json,
aligned with the C# closed-hierarchies spec. Uses structural unification
in both the reflection resolver and the source generator to allow patterns
such as:

  - D<U> : C<U>           (matching arity)
  - D<V> : C<V[]>         (wrapped type argument)
  - D<U, T> : C<T, U>     (reordered)
  - Outer<T>.Derived      (parameters from enclosing types)
  - D<T, U> : IFoo<T, U[]> (interface bases with nested compositions)

Behavior is stricter than C# exhaustiveness where determinism is required:
constraint violations and ambiguous unifications surface as errors rather
than being silently excluded.

Includes:
  * TryUnify orchestrator + structural unification in
    DefaultJsonTypeInfoResolver.Helpers.cs (reflection).
  * Equivalent unification, constraint validation, and parameter
    substitution (including into array element types) in
    JsonSourceGenerator.Parser.cs.
  * 5 new failure-reason resources (NotAssignable, UnificationFailed,
    UnboundParameter, ConstraintViolation, AmbiguousMatch) localized
    across all xlf files.
  * 17 new tests covering arrays, reordering, partial concretization,
    nested generics, ambiguous interface bases, constraint violations
    and constraint substitution into array element types.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support open generics in polymorphic serialization in System.Text.Json

5 participants