From 6f512375999f48e920f99d3ce51a914db95eb38f Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 18 Mar 2026 11:58:57 +0100 Subject: [PATCH 1/4] Add unsafe evolution attributes --- .../CodeAnalysis/RequiresUnsafeAttribute.cs | 19 +++++++++--------- .../MemorySafetyRulesAttribute.cs | 20 +++++++++++++++++++ .../System.Runtime/ref/System.Runtime.cs | 12 +++++++++++ 3 files changed, 42 insertions(+), 9 deletions(-) create mode 100644 src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/MemorySafetyRulesAttribute.cs diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresUnsafeAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresUnsafeAttribute.cs index 5f893b5048e91f..bfa9bc8a0f0128 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresUnsafeAttribute.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/CodeAnalysis/RequiresUnsafeAttribute.cs @@ -4,16 +4,17 @@ namespace System.Diagnostics.CodeAnalysis { /// - /// Indicates that the specified method requires unsafe code that may not be available - /// in all execution environments. + /// Indicates that the specified member requires the caller to be in an unsafe context. /// - /// - /// This allows tools to understand which methods are unsafe to call when targeting - /// environments that do not support unsafe code. - /// - [AttributeUsage(AttributeTargets.Method | AttributeTargets.Constructor, Inherited = false)] - [Conditional("DEBUG")] - internal sealed class RequiresUnsafeAttribute : Attribute + [AttributeUsage( + AttributeTargets.Constructor | AttributeTargets.Event | AttributeTargets.Method | AttributeTargets.Property, + Inherited = false, + AllowMultiple = false)] + public sealed class RequiresUnsafeAttribute : Attribute { + /// + /// Initializes a new instance of the class. + /// + public RequiresUnsafeAttribute() { } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/MemorySafetyRulesAttribute.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/MemorySafetyRulesAttribute.cs new file mode 100644 index 00000000000000..54597d38373cd9 --- /dev/null +++ b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/MemorySafetyRulesAttribute.cs @@ -0,0 +1,20 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.ComponentModel; + +namespace System.Runtime.CompilerServices +{ + /// Indicates the version of the memory safety rules used when the module was compiled. + [EditorBrowsable(EditorBrowsableState.Never)] + [AttributeUsage(AttributeTargets.Module, Inherited = false, AllowMultiple = false)] + public sealed class MemorySafetyRulesAttribute : Attribute + { + /// Initializes a new instance of the class. + /// The version of the memory safety rules used when the module was compiled. + public MemorySafetyRulesAttribute(int version) => Version = version; + + /// Gets the version of the memory safety rules used when the module was compiled. + public int Version { get; } + } +} diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index ccc217672ebad4..76639dfe3d447c 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -9110,6 +9110,11 @@ public RequiresUnreferencedCodeAttribute(string message) { } public string Message { get { throw null; } } public string? Url { get { throw null; } set { } } } + [System.AttributeUsageAttribute(System.AttributeTargets.Constructor | System.AttributeTargets.Event | System.AttributeTargets.Method | System.AttributeTargets.Property, AllowMultiple=false, Inherited=false)] + public sealed partial class RequiresUnsafeAttribute : System.Attribute + { + public RequiresUnsafeAttribute() { } + } [System.AttributeUsageAttribute(System.AttributeTargets.Constructor, AllowMultiple=false, Inherited=false)] public sealed partial class SetsRequiredMembersAttribute : System.Attribute { @@ -14028,6 +14033,13 @@ public enum LoadHint Always = 1, Sometimes = 2, } + [System.AttributeUsageAttribute(System.AttributeTargets.Module, AllowMultiple=false, Inherited=false)] + [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] + public sealed partial class MemorySafetyRulesAttribute : System.Attribute + { + public MemorySafetyRulesAttribute(int version) { } + public int Version { get { throw null; } } + } public enum MethodCodeType { IL = 0, From 7ab7854ce0155c9633abea544cf12260621d986e Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 18 Mar 2026 14:43:50 +0100 Subject: [PATCH 2/4] Add suppressions --- .../CompatibilitySuppressions.xml | 14 +++++++++++++- .../src/CompatibilitySuppressions.xml | 12 ++++++++++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/coreclr/System.Private.CoreLib/CompatibilitySuppressions.xml b/src/coreclr/System.Private.CoreLib/CompatibilitySuppressions.xml index 141210a166bc8f..4a50b1806f6552 100644 --- a/src/coreclr/System.Private.CoreLib/CompatibilitySuppressions.xml +++ b/src/coreclr/System.Private.CoreLib/CompatibilitySuppressions.xml @@ -1,10 +1,16 @@ - + CP0001 T:Internal.Console + + CP0001 + T:System.Runtime.CompilerServices.MemorySafetyRulesAttribute + ref/net11.0/System.Private.CoreLib.dll + lib/net11.0/System.Private.CoreLib.dll + CP0002 F:System.Resources.ResourceManager.BaseNameField @@ -29,4 +35,10 @@ CP0008 T:System.Collections.BitArray + + CP0015 + T:System.Diagnostics.CodeAnalysis.RequiresUnsafeAttribute:[T:System.AttributeUsageAttribute] + ref/net11.0/System.Private.CoreLib.dll + lib/net11.0/System.Private.CoreLib.dll + diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml index b85912e6cf1ff0..1c7a01380b6047 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml @@ -825,4 +825,16 @@ CP0001 T:Internal.NativeFormat.TypeHashingAlgorithms + + CP0001 + T:System.Runtime.CompilerServices.MemorySafetyRulesAttribute + ref/net11.0/System.Private.CoreLib.dll + lib/net11.0/System.Private.CoreLib.dll + + + CP0015 + T:System.Diagnostics.CodeAnalysis.RequiresUnsafeAttribute:[T:System.AttributeUsageAttribute] + ref/net11.0/System.Private.CoreLib.dll + lib/net11.0/System.Private.CoreLib.dll + From ed25edb8423617edac6d7e276ff1064999edf41d Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 18 Mar 2026 14:49:49 +0100 Subject: [PATCH 3/4] Add tests --- .../CodeAnalysis/RequiresUnsafeAttributeTests.cs | 15 +++++++++++++++ .../Runtime/CompilerServices/AttributesTests.cs | 11 +++++++++++ 2 files changed, 26 insertions(+) create mode 100644 src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Diagnostics/CodeAnalysis/RequiresUnsafeAttributeTests.cs diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Diagnostics/CodeAnalysis/RequiresUnsafeAttributeTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Diagnostics/CodeAnalysis/RequiresUnsafeAttributeTests.cs new file mode 100644 index 00000000000000..bf07e6e23a3d59 --- /dev/null +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Diagnostics/CodeAnalysis/RequiresUnsafeAttributeTests.cs @@ -0,0 +1,15 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using Xunit; + +namespace System.Diagnostics.CodeAnalysis.Tests; + +public class RequiresUnsafeAttributeTests +{ + [Fact] + public static void TestConstructor() + { + new RequiresUnsafeAttribute(); + } +} diff --git a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/AttributesTests.cs b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/AttributesTests.cs index e80943edf58551..431c72b61c7ce6 100644 --- a/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/AttributesTests.cs +++ b/src/libraries/System.Runtime/tests/System.Runtime.Tests/System/Runtime/CompilerServices/AttributesTests.cs @@ -235,6 +235,17 @@ public static void RefSafetyRulesAttributeTests(int version) Assert.Equal(version, attr.Version); } + [Theory] + [InlineData(-1)] + [InlineData(0)] + [InlineData(2)] + [InlineData(42)] + public static void MemorySafetyRulesAttributeTests(int version) + { + var attr = new MemorySafetyRulesAttribute(version); + Assert.Equal(version, attr.Version); + } + [Theory] [InlineData("1")] [InlineData("2")] From 6703970412c61e431ec5cf7330f32df9a057cb7a Mon Sep 17 00:00:00 2001 From: Jan Jones Date: Wed, 18 Mar 2026 16:47:09 +0100 Subject: [PATCH 4/4] Fix api compat --- .../CompatibilitySuppressions.xml | 14 +------------- .../src/CompatibilitySuppressions.xml | 12 ------------ .../src/System.Private.CoreLib.Shared.projitems | 1 + src/libraries/System.Runtime/ref/System.Runtime.cs | 4 ++-- 4 files changed, 4 insertions(+), 27 deletions(-) diff --git a/src/coreclr/System.Private.CoreLib/CompatibilitySuppressions.xml b/src/coreclr/System.Private.CoreLib/CompatibilitySuppressions.xml index 4a50b1806f6552..141210a166bc8f 100644 --- a/src/coreclr/System.Private.CoreLib/CompatibilitySuppressions.xml +++ b/src/coreclr/System.Private.CoreLib/CompatibilitySuppressions.xml @@ -1,16 +1,10 @@ - + CP0001 T:Internal.Console - - CP0001 - T:System.Runtime.CompilerServices.MemorySafetyRulesAttribute - ref/net11.0/System.Private.CoreLib.dll - lib/net11.0/System.Private.CoreLib.dll - CP0002 F:System.Resources.ResourceManager.BaseNameField @@ -35,10 +29,4 @@ CP0008 T:System.Collections.BitArray - - CP0015 - T:System.Diagnostics.CodeAnalysis.RequiresUnsafeAttribute:[T:System.AttributeUsageAttribute] - ref/net11.0/System.Private.CoreLib.dll - lib/net11.0/System.Private.CoreLib.dll - diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml index 1c7a01380b6047..b85912e6cf1ff0 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/CompatibilitySuppressions.xml @@ -825,16 +825,4 @@ CP0001 T:Internal.NativeFormat.TypeHashingAlgorithms - - CP0001 - T:System.Runtime.CompilerServices.MemorySafetyRulesAttribute - ref/net11.0/System.Private.CoreLib.dll - lib/net11.0/System.Private.CoreLib.dll - - - CP0015 - T:System.Diagnostics.CodeAnalysis.RequiresUnsafeAttribute:[T:System.AttributeUsageAttribute] - ref/net11.0/System.Private.CoreLib.dll - lib/net11.0/System.Private.CoreLib.dll - diff --git a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems index cf031056c51f8f..1475134b521b96 100644 --- a/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems +++ b/src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems @@ -896,6 +896,7 @@ + diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index 76639dfe3d447c..20eb121fddf1f3 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -9110,7 +9110,7 @@ public RequiresUnreferencedCodeAttribute(string message) { } public string Message { get { throw null; } } public string? Url { get { throw null; } set { } } } - [System.AttributeUsageAttribute(System.AttributeTargets.Constructor | System.AttributeTargets.Event | System.AttributeTargets.Method | System.AttributeTargets.Property, AllowMultiple=false, Inherited=false)] + [System.AttributeUsageAttribute(System.AttributeTargets.Constructor | System.AttributeTargets.Event | System.AttributeTargets.Method | System.AttributeTargets.Property, Inherited=false, AllowMultiple=false)] public sealed partial class RequiresUnsafeAttribute : System.Attribute { public RequiresUnsafeAttribute() { } @@ -14033,7 +14033,7 @@ public enum LoadHint Always = 1, Sometimes = 2, } - [System.AttributeUsageAttribute(System.AttributeTargets.Module, AllowMultiple=false, Inherited=false)] + [System.AttributeUsageAttribute(System.AttributeTargets.Module, Inherited=false, AllowMultiple=false)] [System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)] public sealed partial class MemorySafetyRulesAttribute : System.Attribute {