From d52a17619da7bade4e58901b2232e5a16ec9fea9 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 16 Jul 2026 13:16:51 +0200 Subject: [PATCH 1/8] Add a spec augment on escaping value type instances based on `RefSafetyRulesAttribute` Co-authored-by: Jan Kotas --- docs/design/specs/Ecma-335-Augments.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/docs/design/specs/Ecma-335-Augments.md b/docs/design/specs/Ecma-335-Augments.md index 1600e8e19ab6c3..e0b189bfb00efa 100644 --- a/docs/design/specs/Ecma-335-Augments.md +++ b/docs/design/specs/Ecma-335-Augments.md @@ -1032,6 +1032,22 @@ Changes to signatures: - Managed pointers which point at the address just past the end of an object, or the address where an element just past the end of an array would be stored, are permitted but not dereferenceable. - Null managed pointers are permitted to be dereferenced resulting in a `NullReferenceException`. +### III.1.7.7 +Add a new section "III.1.7.7 Opt-in restrictions" under section "III.1.7 Restrictions on CIL code sequences": + +Applying the custom attribute `System.Runtime.CompilerServices.RefSafetyRulesAttribute` on an assembly opts the assembly into further restrictions based on the encoded version specified in the attribute. These restrictions permit an optimizing compiler to further optimize certain code patterns. + +Languages may define more rules based on this attribute, but for the purpose of defining valid IL only the following restrictions must be satisfied. + +#### III.1.7.7.1 (Version 11 and above) Escaping `this` from value type instance methods +A pointer value is said to escape when it becomes accessible outside the given scope. A pointer escapes if the pointer itself, or pointer value derived from it (for example, by applying a field offset), is stored, returned, or otherwise propagated such that code executing outside the given scope can access it. + +Valid IL shall ensure that the `this` argument of an instance method on a value type does not escape the method unless at least one of the following conditions holds: +- The method is annotated with `System.Diagnostics.CodeAnalysis.UnscopedRefAttribute`. +- The value type instance resides in unmanaged memory, stack-allocated storage or pinned GC heap storage. + +This restriction permits an optimizing compiler to eliminate boxing of value types when it is safe to do so. + ## ByRefLike types in generics ByRefLike types, defined in C# with the `ref struct` syntax, represent types that cannot escape to the managed heap and must remain on the stack. It is possible for these types to be used as generic parameters, but in order to improve utility certain affordances are required. See [ref struct Generic Parameters](https://github.com/dotnet/csharplang/blob/main/proposals/csharp-13.0/ref-struct-interfaces.md#ref-struct-generic-parameters) for C# language counterpart. From 78c910ee827fa62a843cce20fdcd22d346bf7031 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 16 Jul 2026 13:28:04 +0200 Subject: [PATCH 2/8] Remove trailing space --- docs/design/specs/Ecma-335-Augments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design/specs/Ecma-335-Augments.md b/docs/design/specs/Ecma-335-Augments.md index e0b189bfb00efa..bcaa1ca3175ce3 100644 --- a/docs/design/specs/Ecma-335-Augments.md +++ b/docs/design/specs/Ecma-335-Augments.md @@ -1041,7 +1041,7 @@ Languages may define more rules based on this attribute, but for the purpose of #### III.1.7.7.1 (Version 11 and above) Escaping `this` from value type instance methods A pointer value is said to escape when it becomes accessible outside the given scope. A pointer escapes if the pointer itself, or pointer value derived from it (for example, by applying a field offset), is stored, returned, or otherwise propagated such that code executing outside the given scope can access it. - + Valid IL shall ensure that the `this` argument of an instance method on a value type does not escape the method unless at least one of the following conditions holds: - The method is annotated with `System.Diagnostics.CodeAnalysis.UnscopedRefAttribute`. - The value type instance resides in unmanaged memory, stack-allocated storage or pinned GC heap storage. From f5f9f818ef0f6731298042cb622a08e13aee5006 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 16 Jul 2026 13:32:43 +0200 Subject: [PATCH 3/8] Some copilot feedback --- docs/design/specs/Ecma-335-Augments.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/design/specs/Ecma-335-Augments.md b/docs/design/specs/Ecma-335-Augments.md index bcaa1ca3175ce3..04e13d805228bf 100644 --- a/docs/design/specs/Ecma-335-Augments.md +++ b/docs/design/specs/Ecma-335-Augments.md @@ -1032,10 +1032,10 @@ Changes to signatures: - Managed pointers which point at the address just past the end of an object, or the address where an element just past the end of an array would be stored, are permitted but not dereferenceable. - Null managed pointers are permitted to be dereferenced resulting in a `NullReferenceException`. -### III.1.7.7 +### III.1.7.7 Opt-in restrictions Add a new section "III.1.7.7 Opt-in restrictions" under section "III.1.7 Restrictions on CIL code sequences": -Applying the custom attribute `System.Runtime.CompilerServices.RefSafetyRulesAttribute` on an assembly opts the assembly into further restrictions based on the encoded version specified in the attribute. These restrictions permit an optimizing compiler to further optimize certain code patterns. +Applying the custom attribute `System.Runtime.CompilerServices.RefSafetyRulesAttribute` on an assembly opts the assembly into further restrictions based on the version value specified in the attribute. These restrictions permit an optimizing compiler to further optimize certain code patterns. Languages may define more rules based on this attribute, but for the purpose of defining valid IL only the following restrictions must be satisfied. From 4f3d8b22945305f577d017b70ac579b77d9a280b Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 16 Jul 2026 13:37:08 +0200 Subject: [PATCH 4/8] Apply suggestions from code review Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- docs/design/specs/Ecma-335-Augments.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/design/specs/Ecma-335-Augments.md b/docs/design/specs/Ecma-335-Augments.md index 04e13d805228bf..8d98417dbdafc2 100644 --- a/docs/design/specs/Ecma-335-Augments.md +++ b/docs/design/specs/Ecma-335-Augments.md @@ -1040,11 +1040,11 @@ Applying the custom attribute `System.Runtime.CompilerServices.RefSafetyRulesAtt Languages may define more rules based on this attribute, but for the purpose of defining valid IL only the following restrictions must be satisfied. #### III.1.7.7.1 (Version 11 and above) Escaping `this` from value type instance methods -A pointer value is said to escape when it becomes accessible outside the given scope. A pointer escapes if the pointer itself, or pointer value derived from it (for example, by applying a field offset), is stored, returned, or otherwise propagated such that code executing outside the given scope can access it. +A pointer value is said to escape when it becomes accessible outside the given scope. A pointer escapes if the pointer itself, or a pointer value derived from it (for example, by applying a field offset), is stored, returned, or otherwise propagated such that code executing outside the given scope can access it. Valid IL shall ensure that the `this` argument of an instance method on a value type does not escape the method unless at least one of the following conditions holds: - The method is annotated with `System.Diagnostics.CodeAnalysis.UnscopedRefAttribute`. -- The value type instance resides in unmanaged memory, stack-allocated storage or pinned GC heap storage. +- The value type instance resides in unmanaged memory, stack-allocated storage, or pinned GC heap storage. This restriction permits an optimizing compiler to eliminate boxing of value types when it is safe to do so. From f2f3ad1f3e5e82356f198bccf8379a41e16a5d2c Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 16 Jul 2026 13:42:56 +0200 Subject: [PATCH 5/8] assembly -> module --- docs/design/specs/Ecma-335-Augments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design/specs/Ecma-335-Augments.md b/docs/design/specs/Ecma-335-Augments.md index 8d98417dbdafc2..968c2a56f91f00 100644 --- a/docs/design/specs/Ecma-335-Augments.md +++ b/docs/design/specs/Ecma-335-Augments.md @@ -1035,7 +1035,7 @@ Changes to signatures: ### III.1.7.7 Opt-in restrictions Add a new section "III.1.7.7 Opt-in restrictions" under section "III.1.7 Restrictions on CIL code sequences": -Applying the custom attribute `System.Runtime.CompilerServices.RefSafetyRulesAttribute` on an assembly opts the assembly into further restrictions based on the version value specified in the attribute. These restrictions permit an optimizing compiler to further optimize certain code patterns. +Applying the custom attribute `System.Runtime.CompilerServices.RefSafetyRulesAttribute` on a module opts the module into further restrictions based on the version value specified in the attribute. These restrictions permit an optimizing compiler to further optimize certain code patterns. Languages may define more rules based on this attribute, but for the purpose of defining valid IL only the following restrictions must be satisfied. From 4417a5d91715c396f6cd45be31dfe063ac86b89a Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 16 Jul 2026 14:25:36 +0200 Subject: [PATCH 6/8] Apply suggestion from @jakobbotsch --- docs/design/specs/Ecma-335-Augments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design/specs/Ecma-335-Augments.md b/docs/design/specs/Ecma-335-Augments.md index 968c2a56f91f00..46963590b72cb1 100644 --- a/docs/design/specs/Ecma-335-Augments.md +++ b/docs/design/specs/Ecma-335-Augments.md @@ -1043,7 +1043,7 @@ Languages may define more rules based on this attribute, but for the purpose of A pointer value is said to escape when it becomes accessible outside the given scope. A pointer escapes if the pointer itself, or a pointer value derived from it (for example, by applying a field offset), is stored, returned, or otherwise propagated such that code executing outside the given scope can access it. Valid IL shall ensure that the `this` argument of an instance method on a value type does not escape the method unless at least one of the following conditions holds: -- The method is annotated with `System.Diagnostics.CodeAnalysis.UnscopedRefAttribute`. +- The method and any method overriden by it is annotated with `System.Diagnostics.CodeAnalysis.UnscopedRefAttribute`. - The value type instance resides in unmanaged memory, stack-allocated storage, or pinned GC heap storage. This restriction permits an optimizing compiler to eliminate boxing of value types when it is safe to do so. From df2622d36f4b0fb366973e91f571af7aa9abc403 Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 16 Jul 2026 14:26:21 +0200 Subject: [PATCH 7/8] Typo --- docs/design/specs/Ecma-335-Augments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design/specs/Ecma-335-Augments.md b/docs/design/specs/Ecma-335-Augments.md index 46963590b72cb1..4296ed4a516de5 100644 --- a/docs/design/specs/Ecma-335-Augments.md +++ b/docs/design/specs/Ecma-335-Augments.md @@ -1043,7 +1043,7 @@ Languages may define more rules based on this attribute, but for the purpose of A pointer value is said to escape when it becomes accessible outside the given scope. A pointer escapes if the pointer itself, or a pointer value derived from it (for example, by applying a field offset), is stored, returned, or otherwise propagated such that code executing outside the given scope can access it. Valid IL shall ensure that the `this` argument of an instance method on a value type does not escape the method unless at least one of the following conditions holds: -- The method and any method overriden by it is annotated with `System.Diagnostics.CodeAnalysis.UnscopedRefAttribute`. +- The method and any method overridden by it is annotated with `System.Diagnostics.CodeAnalysis.UnscopedRefAttribute`. - The value type instance resides in unmanaged memory, stack-allocated storage, or pinned GC heap storage. This restriction permits an optimizing compiler to eliminate boxing of value types when it is safe to do so. From eca6ddaf568370033ba28bef9a0960a2e4d0d21e Mon Sep 17 00:00:00 2001 From: Jakob Botsch Nielsen Date: Thu, 16 Jul 2026 14:32:25 +0200 Subject: [PATCH 8/8] Copilot's wording --- docs/design/specs/Ecma-335-Augments.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/design/specs/Ecma-335-Augments.md b/docs/design/specs/Ecma-335-Augments.md index 4296ed4a516de5..bfa99cff38f799 100644 --- a/docs/design/specs/Ecma-335-Augments.md +++ b/docs/design/specs/Ecma-335-Augments.md @@ -1043,7 +1043,7 @@ Languages may define more rules based on this attribute, but for the purpose of A pointer value is said to escape when it becomes accessible outside the given scope. A pointer escapes if the pointer itself, or a pointer value derived from it (for example, by applying a field offset), is stored, returned, or otherwise propagated such that code executing outside the given scope can access it. Valid IL shall ensure that the `this` argument of an instance method on a value type does not escape the method unless at least one of the following conditions holds: -- The method and any method overridden by it is annotated with `System.Diagnostics.CodeAnalysis.UnscopedRefAttribute`. +- The method and any method it overrides are annotated with `System.Diagnostics.CodeAnalysis.UnscopedRefAttribute`. - The value type instance resides in unmanaged memory, stack-allocated storage, or pinned GC heap storage. This restriction permits an optimizing compiler to eliminate boxing of value types when it is safe to do so.