diff --git a/docs/coding-guidelines/breaking-change-rules.md b/docs/coding-guidelines/breaking-change-rules.md index 4b8c396d57c15a..dd5ac5d550d0b9 100644 --- a/docs/coding-guidelines/breaking-change-rules.md +++ b/docs/coding-guidelines/breaking-change-rules.md @@ -169,6 +169,8 @@ Breaking Change Rules * Changing a `struct` type to a `ref struct` type and vice versa +* Changing a `struct` type to an `enum` type and 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. 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 0c350206e0b48d..3fb54a73887dfb 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 d8f5707fd0d927..548d5751971375 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/JitInterface/CorInfoImpl.ReadyToRun.cs @@ -3972,8 +3972,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