Support open generics in polymorphic serialization in System.Text.Json#127318
Support open generics in polymorphic serialization in System.Text.Json#127318Copilot wants to merge 1 commit into
Conversation
|
@copilot Separately, please add a test explicitly prohibiting use of |
Added in 28e3282. |
|
Tagging subscribers to this area: @dotnet/area-system-text-json |
| if (baseDef.TypeKind == TypeKind.Interface) | ||
| { | ||
| foreach (INamedTypeSymbol iface in derivedDef.AllInterfaces) | ||
| { | ||
| if (SymbolEqualityComparer.Default.Equals(iface.OriginalDefinition, baseDef)) |
| 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; | ||
| } |
| 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); | ||
| } |
| [Fact] | ||
| public void OpenGenericDerivedType_WrappedTypeArgs_WarnsWithSYSLIB1229() | ||
| { |
| 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); | ||
| } |
| 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; |
| <data name="Polymorphism_OpenGeneric_Reason_ConstraintViolation" xml:space="preserve"> | ||
| <value>the constraint on type parameter '{0}' is not satisfied by '{1}'</value> | ||
| </data> |
| | __`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>
Uh oh!
There was an error while loading. Please reload this page.