diff --git a/src/coreclr/dlls/mscorrc/mscorrc.rc b/src/coreclr/dlls/mscorrc/mscorrc.rc index e85b88fcdd07aa..0fed12722a1139 100644 --- a/src/coreclr/dlls/mscorrc/mscorrc.rc +++ b/src/coreclr/dlls/mscorrc/mscorrc.rc @@ -308,6 +308,7 @@ BEGIN IDS_CLASSLOAD_INLINE_ARRAY_FIELD_COUNT "InlineArrayAttribute requires that the target type has a single instance field. Type: '%1'. Assembly: '%2'." IDS_CLASSLOAD_INLINE_ARRAY_LENGTH "InlineArrayAttribute requires that the length argument is greater than 0. Type: '%1'. Assembly: '%2'." IDS_CLASSLOAD_INLINE_ARRAY_EXPLICIT "InlineArrayAttribute cannot be applied to a type with explicit layout. Type: '%1'. Assembly: '%2'." + IDS_CLASSLOAD_INLINE_ARRAY_EXPLICIT_SIZE "InlineArrayAttribute cannot be applied to a type with explicit size. Type: '%1'. Assembly: '%2'." IDS_CLASSLOAD_BYREF_OF_BYREF "Could not create a ByRef of a ByRef. Type: '%1'. Assembly: '%2'." IDS_CLASSLOAD_POINTER_OF_BYREF "Could not create a pointer to a ByRef. Type: '%1'. Assembly: '%2'." diff --git a/src/coreclr/dlls/mscorrc/resource.h b/src/coreclr/dlls/mscorrc/resource.h index 397efa1f2ae768..f7ae1dea4a6259 100644 --- a/src/coreclr/dlls/mscorrc/resource.h +++ b/src/coreclr/dlls/mscorrc/resource.h @@ -160,6 +160,8 @@ #define IDS_CLASSLOAD_BYREF_OF_BYREF 0x17af #define IDS_CLASSLOAD_POINTER_OF_BYREF 0x17b0 +#define IDS_CLASSLOAD_INLINE_ARRAY_EXPLICIT_SIZE 0x17b1 + #define IDS_INVALID_REDIM 0x17c3 #define IDS_INVALID_PINVOKE_CALLCONV 0x17c4 #define IDS_CLASSLOAD_NSTRUCT_EXPLICIT_OFFSET 0x17c7 diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/TypeLoaderExceptionHelper.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/TypeLoaderExceptionHelper.cs index 70d17bb96989d7..e837f7c6c96518 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/TypeLoaderExceptionHelper.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/TypeLoaderExceptionHelper.cs @@ -92,6 +92,8 @@ private static string GetFormatString(ExceptionStringID id) return SR.ClassLoad_InlineArrayLength; case ExceptionStringID.ClassLoadInlineArrayExplicit: return SR.ClassLoad_InlineArrayExplicit; + case ExceptionStringID.ClassLoadInlineArrayExplicitSize: + return SR.ClassLoad_InlineArrayExplicitSize; case ExceptionStringID.InvalidProgramDefault: return SR.InvalidProgram_Default; case ExceptionStringID.InvalidProgramSpecific: diff --git a/src/coreclr/tools/Common/TypeSystem/Common/ExceptionStringID.cs b/src/coreclr/tools/Common/TypeSystem/Common/ExceptionStringID.cs index 923ec0da4316fb..97363c783f8a3e 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/ExceptionStringID.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/ExceptionStringID.cs @@ -19,6 +19,7 @@ public enum ExceptionStringID ClassLoadInlineArrayFieldCount, ClassLoadInlineArrayLength, ClassLoadInlineArrayExplicit, + ClassLoadInlineArrayExplicitSize, // MissingMethodException MissingMethod, diff --git a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs index 107d8dbffb87c4..604f76cd09442f 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs +++ b/src/coreclr/tools/Common/TypeSystem/Common/MetadataFieldLayoutAlgorithm.cs @@ -510,6 +510,12 @@ private static void AdjustForInlineArray( ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadInlineArrayFieldCount, type); } + var layoutMetadata = type.GetClassLayout(); + if (layoutMetadata.Size != 0) + { + ThrowHelper.ThrowTypeLoadException(ExceptionStringID.ClassLoadInlineArrayExplicitSize, type); + } + if (!instanceByteSizeAndAlignment.Size.IsIndeterminate) { long size = instanceByteSizeAndAlignment.Size.AsInt; diff --git a/src/coreclr/tools/Common/TypeSystem/Common/Properties/Resources.resx b/src/coreclr/tools/Common/TypeSystem/Common/Properties/Resources.resx index 6a2f012e012586..1ce5dcbd5e3333 100644 --- a/src/coreclr/tools/Common/TypeSystem/Common/Properties/Resources.resx +++ b/src/coreclr/tools/Common/TypeSystem/Common/Properties/Resources.resx @@ -138,6 +138,9 @@ InlineArrayAttribute cannot be applied to a type with explicit layout. Type: '{0}'. Assembly: '{1}'.' + + InlineArrayAttribute cannot be applied to a type with explicit size. Type: '{0}'. Assembly: '{1}'.' + Array of type '{0}' from assembly '{1}' cannot be created because base value type is too large diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 66d9199dcfc410..f8628b4197edc3 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -1771,6 +1771,12 @@ MethodTableBuilder::BuildMethodTableThrowing( { BuildMethodTableThrowException(IDS_CLASSLOAD_INLINE_ARRAY_EXPLICIT); } + + ULONG classSize; + if (SUCCEEDED(GetMDImport()->GetClassTotalSize(cl, &classSize)) && classSize != 0) + { + BuildMethodTableThrowException(IDS_CLASSLOAD_INLINE_ARRAY_EXPLICIT_SIZE); + } } } } diff --git a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx index 4b45d710bc3fd6..497a524ed303fa 100644 --- a/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx +++ b/src/libraries/System.Private.CoreLib/src/Resources/Strings.resx @@ -4202,6 +4202,9 @@ InlineArrayAttribute cannot be applied to a type with explicit layout. Type: '{0}'. Assembly: '{1}'. + + InlineArrayAttribute cannot be applied to a type with explicit size. Type: '{0}'. Assembly: '{1}'. + Could not load type '{0}' from assembly '{1}' because generic types cannot have explicit layout. diff --git a/src/mono/mono/metadata/class-init.c b/src/mono/mono/metadata/class-init.c index 6b8daf900f7494..52f108fc7cc9a0 100644 --- a/src/mono/mono/metadata/class-init.c +++ b/src/mono/mono/metadata/class-init.c @@ -317,6 +317,13 @@ mono_class_setup_fields (MonoClass *klass) if (explicit_size) instance_size += real_size; + if (explicit_size && real_size != 0 && m_class_is_inlinearray (klass)) { + if (mono_get_runtime_callbacks ()->mono_class_set_deferred_type_load_failure_callback) + mono_get_runtime_callbacks ()->mono_class_set_deferred_type_load_failure_callback (klass, "Inline array must not have explicit size."); + else + mono_class_set_type_load_failure (klass, "Inline array must not have explicit size."); + } + /* * This function can recursively call itself. * Prevent infinite recursion by using a list in TLS. diff --git a/src/tests/Loader/classloader/InlineArray/InlineArrayInvalid.cs b/src/tests/Loader/classloader/InlineArray/InlineArrayInvalid.cs index daa35af75c7502..0171c97429de56 100644 --- a/src/tests/Loader/classloader/InlineArray/InlineArrayInvalid.cs +++ b/src/tests/Loader/classloader/InlineArray/InlineArrayInvalid.cs @@ -22,6 +22,45 @@ public static void Explicit_Fails() }); } + [Fact] + public static void ExplicitSize_FailsInSequential() + { + Console.WriteLine($"{nameof(ExplicitSize_FailsInSequential)}..."); + + Assert.Throws(() => { var t = typeof(ExplicitSize); }); + + Assert.Throws(() => + { + return new ExplicitSize(); + }); + } + + [Fact] + public static void ExplicitSize_FailsInAuto() + { + Console.WriteLine($"{nameof(ExplicitSize_FailsInAuto)}..."); + + Assert.Throws(() => { var t = typeof(ExplicitSizeAuto); }); + + Assert.Throws(() => + { + return sizeof(ExplicitSizeAuto); + }); + } + + [Fact] + public static void ExplicitSize_FailsInGeneric() + { + Console.WriteLine($"{nameof(ExplicitSize_FailsInGeneric)}..."); + + Assert.Throws(() => { var t = typeof(ExplicitSizeGeneric); }); + + Assert.Throws(() => + { + return new ExplicitSizeGeneric(); + }); + } + [Fact] public static void ZeroLength_Fails() { diff --git a/src/tests/Loader/classloader/InlineArray/InlineArrayInvalid.csproj b/src/tests/Loader/classloader/InlineArray/InlineArrayInvalid.csproj index 098ebbb26a691a..c9e8dc0015fade 100644 --- a/src/tests/Loader/classloader/InlineArray/InlineArrayInvalid.csproj +++ b/src/tests/Loader/classloader/InlineArray/InlineArrayInvalid.csproj @@ -5,6 +5,7 @@ true false + 0 diff --git a/src/tests/Loader/classloader/InlineArray/InvalidCSharpInlineArray.il b/src/tests/Loader/classloader/InlineArray/InvalidCSharpInlineArray.il index 47e3e0a53d725a..ca71640f41fc37 100644 --- a/src/tests/Loader/classloader/InlineArray/InvalidCSharpInlineArray.il +++ b/src/tests/Loader/classloader/InlineArray/InvalidCSharpInlineArray.il @@ -14,6 +14,39 @@ .field [0] public valuetype [System.Runtime]System.Guid Guid } +.class public sequential ansi sealed beforefieldinit ExplicitSize + extends [System.Runtime]System.ValueType +{ + .custom instance void [System.Runtime]System.Runtime.CompilerServices.InlineArrayAttribute::.ctor(int32) = ( + 01 00 01 00 00 00 00 00 + ) + + .size 256 + .field [0] public valuetype [System.Runtime]System.Guid Guid +} + +.class public auto ansi sealed beforefieldinit ExplicitSizeAuto + extends [System.Runtime]System.ValueType +{ + .custom instance void [System.Runtime]System.Runtime.CompilerServices.InlineArrayAttribute::.ctor(int32) = ( + 01 00 01 00 00 00 00 00 + ) + + .size 256 + .field [0] public valuetype [System.Runtime]System.Guid Guid +} + +.class public auto ansi sealed beforefieldinit ExplicitSizeGeneric`1 + extends [System.Runtime]System.ValueType +{ + .custom instance void [System.Runtime]System.Runtime.CompilerServices.InlineArrayAttribute::.ctor(int32) = ( + 01 00 01 00 00 00 00 00 + ) + + .size 256 + .field [0] public valuetype [System.Runtime]System.Guid Guid +} + .class public sequential ansi sealed beforefieldinit ZeroLength extends [System.Runtime]System.ValueType {