Fix KeyValuePair nullability detection on Mono - #120910
#120910Fix KeyValuePair nullability detection on Mono#120910
Conversation
This sounds like a bug in Mono-specific reflection implementation. Instead of adding workaround for this to shared NullabilityInfoContext.cs, could you please fix the Mono reflection implementation instead? |
e84c119 to
5f4df1c
Compare
You're absolutely right - I've fixed this at the Mono native level instead. The reflection APIs are actually working correctly; the issue was metadata token corruption in |
|
/azp run runtime |
|
Azure Pipelines successfully started running 1 pipeline(s). |
|
Could we please update the PR description to match the actual fix? Ideally we would also fix the commit message - both describe the fix in a way which doesn't match the code change at all. |
I’ve updated the PR description to reflect the native fix in Mono's metadata initialization, Please let me know if it looks good now |
|
Thanks a lot! |
Fix KeyValuePair nullability detection on Mono
Summary
Fixed a bug in the Mono runtime where NullableAttribute metadata was being lost for generic parameters. This was specifically causing KeyValuePair<TKey, TValue> to incorrectly report NotNull nullability in ASP.NET Core DataAnnotations tests.
Problem
On Mono, the reflection API failed to detect nullability attributes on generic parameters (like TKey and TValue). While CoreCLR correctly identified these as Nullable, Mono defaulted to NotNull
Failing Tests
Microsoft.AspNetCore.Mvc.DataAnnotations.DataAnnotationsMetadataProviderTest.IsNullableReferenceType_ReturnsFalse_ForKeyValuePairWithoutNullableConstraintsMicrosoft.AspNetCore.Mvc.DataAnnotations.DataAnnotationsMetadataProviderTest.IsNullableReferenceType_ReturnsTrue_ForKeyValuePairWithNullableConstraintsRoot Cause
The issue was located in the Mono native metadata initialization (src/mono/mono/metadata/class-init.c). In the MonoClass structure,
MonoClassSizesis a union whereclass_sizeandgeneric_param_tokenshare the same memory location.During the execution of
mono_class_layout_fields(), the runtime was explicitly assigning class_size = 0. Because of the union, this assignment was overwriting and zeroing out thegeneric_param_tokenthat had been correctly initialized earlier. When the reflection system later tried to look up custom attributes using that token, it failed because the token was now 0x0.Solution
The fix modifies mono_class_layout_fields to skip the class_size assignment for types that are generic parameters (
MONO_TYPE_VARandMONO_TYPE_MVAR). This preserves the metadata token, allowing mono_custom_attrs_from_class_checked() to correctly retrieve the NullableAttribute.Reproduction Case
Test Results
Files Changed
src/mono/mono/metadata/class-init.ccc: @giritrivedi