From f9fbc49afbd0a5612d101c4889e5755c037882dd Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Nov 2026 18:19:39 +0000 Subject: [PATCH 1/5] Initial plan From b92f07651127511f0a7772525bce8b4e31c58ff0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 6 Nov 2026 19:03:10 +0000 Subject: [PATCH 2/5] Apply remaining changes Co-authored-by: AaronRobinsonMSFT <30635565+AaronRobinsonMSFT@users.noreply.github.com> --- docs/coding-guidelines/breaking-change-rules.md | 2 ++ .../TestCases/CastFolding/CastFolding.cs | 3 +++ .../ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs | 1 + .../JitInterface/CorInfoImpl.ReadyToRun.cs | 4 ++-- 4 files changed, 8 insertions(+), 2 deletions(-) diff --git a/docs/coding-guidelines/breaking-change-rules.md b/docs/coding-guidelines/breaking-change-rules.md index 4b8c396d57c15a..d2290f61e16b2d 100644 --- a/docs/coding-guidelines/breaking-change-rules.md +++ b/docs/coding-guidelines/breaking-change-rules.md @@ -163,6 +163,8 @@ Breaking Change Rules * Removing one or more base classes for a type, including changing `struct` to `class` and vice versa +* Changing a `struct` to an `enum` or vice versa + * Changing the namespace or name of a type * Changing a `readonly struct` type to a `struct` type diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/CastFolding/CastFolding.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/CastFolding/CastFolding.cs index 4999c441c37b51..db5767f789e6ba 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/CastFolding/CastFolding.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/CastFolding/CastFolding.cs @@ -86,6 +86,9 @@ public static class CastFolding [MethodImpl(MethodImplOptions.NoInlining)] public static bool StructIsOtherStruct(SourceStruct s) => (object)s is TargetStruct; + [MethodImpl(MethodImplOptions.NoInlining)] + public static bool StructIsEnum(SourceStruct s) => (object)s is Enum; + [MethodImpl(MethodImplOptions.NoInlining)] public static bool StructIsInterface(ControlStruct s) => (object)s is INotImplemented; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs index 10ef008d90c8f8..b191cad83a9ad5 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun.Tests/TestCases/R2RTestSuites.cs @@ -649,6 +649,7 @@ void Validate(ReadyToRunReader reader) Assert.False(importedTypes.Contains("byte"), diagnostic); Assert.False(importedTypes.Contains("SourceStruct"), diagnostic); Assert.False(importedTypes.Contains("TargetStruct"), diagnostic); + Assert.False(importedTypes.Contains("System.Enum"), diagnostic); // Casts to interfaces fold only when every type in the hierarchy is in the version bubble, // which includes System.Object and System.ValueType only with the framework in the bubble. diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs index 6b593c675a5d18..f5c8ee17f79e18 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -3970,8 +3970,8 @@ private bool IsNegativeCastResultVersionResilient(TypeDesc fromType, TypeDesc to if (fromType.HasTypeEquivalence || toType.HasTypeEquivalence) return false; - // A value type can gain interfaces (or become an enum), but its other cast targets are fixed. - if (fromType.IsValueType && !toType.IsInterface && !toType.IsWellKnownType(WellKnownType.Enum)) + // A value type can gain interfaces, but its other cast targets are fixed. + if (fromType.IsValueType && !toType.IsInterface) return true; // Otherwise every type that decides the cast must version with this code. Array and variant casts From 087be5ee5d4983d8dabb3875462fa6a9fc42949e Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Fri, 6 Nov 2026 19:39:47 -0800 Subject: [PATCH 3/5] Update breaking change rules to include struct-enum change Added changing a struct to an enum or vice versa as a breaking change. --- docs/coding-guidelines/breaking-change-rules.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/coding-guidelines/breaking-change-rules.md b/docs/coding-guidelines/breaking-change-rules.md index d2290f61e16b2d..87768dd16e65d1 100644 --- a/docs/coding-guidelines/breaking-change-rules.md +++ b/docs/coding-guidelines/breaking-change-rules.md @@ -163,14 +163,14 @@ Breaking Change Rules * Removing one or more base classes for a type, including changing `struct` to `class` and vice versa -* Changing a `struct` to an `enum` or vice versa - * Changing the namespace or name of a type * Changing a `readonly struct` type to a `struct` type * Changing a `struct` type to a `ref struct` type and vice versa +* Changing a `struct` to an `enum` or vice versa + * Changing the underlying type of an enum This is a compile-time and behavioral breaking change as well as a binary breaking change which can make attribute arguments unparsable. From b33bc96bc7e2558565e954b627ec83956218b4ce Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 7 Nov 2026 03:52:05 +0000 Subject: [PATCH 4/5] Align breaking-change rule wording Co-authored-by: AaronRobinsonMSFT <30635565+AaronRobinsonMSFT@users.noreply.github.com> --- docs/coding-guidelines/breaking-change-rules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/coding-guidelines/breaking-change-rules.md b/docs/coding-guidelines/breaking-change-rules.md index 87768dd16e65d1..3a611b41017ecb 100644 --- a/docs/coding-guidelines/breaking-change-rules.md +++ b/docs/coding-guidelines/breaking-change-rules.md @@ -169,7 +169,7 @@ Breaking Change Rules * Changing a `struct` type to a `ref struct` type and vice versa -* Changing a `struct` to an `enum` or vice versa +* Changing a `struct` type to an `enum` type or vice versa * Changing the underlying type of an enum From bc4cf457101964e47960abdac6909cf852d622fd Mon Sep 17 00:00:00 2001 From: Aaron R Robinson Date: Fri, 6 Nov 2026 19:58:37 -0800 Subject: [PATCH 5/5] Apply suggestion from @AaronRobinsonMSFT --- docs/coding-guidelines/breaking-change-rules.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/coding-guidelines/breaking-change-rules.md b/docs/coding-guidelines/breaking-change-rules.md index 3a611b41017ecb..dd5ac5d550d0b9 100644 --- a/docs/coding-guidelines/breaking-change-rules.md +++ b/docs/coding-guidelines/breaking-change-rules.md @@ -169,7 +169,7 @@ Breaking Change Rules * Changing a `struct` type to a `ref struct` type and vice versa -* Changing a `struct` type to an `enum` type or vice versa +* Changing a `struct` type to an `enum` type and vice versa * Changing the underlying type of an enum