diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp
index fae0605d0b0bd5..f7846628f5a3e4 100644
--- a/src/coreclr/vm/methodtablebuilder.cpp
+++ b/src/coreclr/vm/methodtablebuilder.cpp
@@ -8732,29 +8732,30 @@ MethodTableBuilder::HandleExplicitLayout(
if (pMT->IsByRefLike())
return CheckByRefLikeValueClassLayout(pMT, pFieldLayout);
- // This method assumes there is a GC desc associated with the MethodTable.
- _ASSERTE(pMT->ContainsPointers());
-
// Build a layout of the value class (vc). Don't know the sizes of all the fields easily, but
// do know (a) vc is already consistent so don't need to check it's overlaps and
// (b) size and location of all objectrefs. So build it by setting all non-oref
- // then fill in the orefs later
+ // then fill in the orefs later if present.
UINT fieldSize = pMT->GetNumInstanceFieldBytes();
CQuickBytes qb;
bmtFieldLayoutTag *vcLayout = (bmtFieldLayoutTag*) qb.AllocThrows(fieldSize * sizeof(bmtFieldLayoutTag));
memset((void*)vcLayout, nonoref, fieldSize);
- // use pointer series to locate the orefs
- CGCDesc* map = CGCDesc::GetCGCDescFromMT(pMT);
- CGCDescSeries *pSeries = map->GetLowestSeries();
-
- for (SIZE_T j = 0; j < map->GetNumSeries(); j++)
+ // If the type contains pointers fill it out from the GC data
+ if (pMT->ContainsPointers())
{
- CONSISTENCY_CHECK(pSeries <= map->GetHighestSeries());
+ // use pointer series to locate the orefs
+ CGCDesc* map = CGCDesc::GetCGCDescFromMT(pMT);
+ CGCDescSeries *pSeries = map->GetLowestSeries();
- memset((void*)&vcLayout[pSeries->GetSeriesOffset() - OBJECT_SIZE], oref, pSeries->GetSeriesSize() + pMT->GetBaseSize());
- pSeries++;
+ for (SIZE_T j = 0; j < map->GetNumSeries(); j++)
+ {
+ CONSISTENCY_CHECK(pSeries <= map->GetHighestSeries());
+
+ memset((void*)&vcLayout[pSeries->GetSeriesOffset() - OBJECT_SIZE], oref, pSeries->GetSeriesSize() + pMT->GetBaseSize());
+ pSeries++;
+ }
}
ExplicitClassTrust explicitClassTrust;
diff --git a/src/tests/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case13.cs b/src/tests/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case13.cs
new file mode 100644
index 00000000000000..99ca59fdd47e7a
--- /dev/null
+++ b/src/tests/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case13.cs
@@ -0,0 +1,92 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+using Xunit;
+
+public class Test
+{
+ public struct WithORefs
+ {
+ public object F;
+ }
+
+ public struct WithNoORefs
+ {
+ public int F;
+ }
+
+ public ref struct WithByRefs
+ {
+ public ref int F;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public ref struct Explicit1
+ {
+ [FieldOffset(0)] public Inner1 Field1;
+ public ref struct Inner1
+ {
+ public WithORefs Field2;
+ }
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public ref struct Explicit2
+ {
+ [FieldOffset(0)] public Inner2 Field1;
+ public ref struct Inner2
+ {
+ public WithNoORefs Field2;
+ }
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public ref struct Explicit3
+ {
+ [FieldOffset(0)] public Inner3 Field1;
+ public ref struct Inner3
+ {
+ public WithByRefs Field2;
+ }
+ }
+
+ [Fact]
+ public static void Validate_Explicit1()
+ {
+ Load1();
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static string Load1()
+ {
+ return typeof(Explicit1).ToString();
+ }
+ }
+
+ [Fact]
+ public static void Validate_Explicit2()
+ {
+ Load2();
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static string Load2()
+ {
+ return typeof(Explicit2).ToString();
+ }
+ }
+
+ [Fact]
+ public static void Validate_Explicit3()
+ {
+ Load3();
+
+ [MethodImpl(MethodImplOptions.NoInlining)]
+ static string Load3()
+ {
+ return typeof(Explicit3).ToString();
+ }
+ }
+}
diff --git a/src/tests/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case13.csproj b/src/tests/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case13.csproj
new file mode 100644
index 00000000000000..0de2ecf447373d
--- /dev/null
+++ b/src/tests/Loader/classloader/explicitlayout/objrefandnonobjrefoverlap/case13.csproj
@@ -0,0 +1,10 @@
+
+
+ true
+ Exe
+ false
+
+
+
+
+
diff --git a/src/tests/issues.targets b/src/tests/issues.targets
index dadea0c4b59e30..cd2f7e35636b99 100644
--- a/src/tests/issues.targets
+++ b/src/tests/issues.targets
@@ -2976,10 +2976,10 @@
https://github.com/dotnet/runtime/issues/57350
-
+
https://github.com/dotnet/runtime/issues/57350
-
+
https://github.com/dotnet/runtime/issues/57350
@@ -2988,10 +2988,10 @@
https://github.com/dotnet/runtime/issues/57350
-
+
https://github.com/dotnet/runtime/issues/57350
-
+
https://github.com/dotnet/runtime/issues/57350
@@ -3179,7 +3179,7 @@
-
+
https://github.com/dotnet/runtime/issues/57350