From 84c0ea9325c69aad0a23aa55001488352d869ac7 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Thu, 16 May 2024 17:18:19 -0700 Subject: [PATCH 1/3] Propose relaxed ordering for partial and ref modifiers --- proposals/partial-properties.md | 137 ++++++++++++++++++++++++++++++-- 1 file changed, 131 insertions(+), 6 deletions(-) diff --git a/proposals/partial-properties.md b/proposals/partial-properties.md index 54051a5c1a..04169fda9e 100644 --- a/proposals/partial-properties.md +++ b/proposals/partial-properties.md @@ -3,16 +3,28 @@ https://github.com/dotnet/csharplang/issues/6420 ### Grammar -The *property_declaration* grammar [(§14.7.1)](https://github.com/dotnet/csharpstandard/blob/draft-v7/standard/classes.md#1471-general) is updated as follows: +The partial modifier on properties is treated just like any other modifier and can be included in any position in a modifier list. + +The property grammar [(§15.7.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1571-general) is updated as follows: ```diff -property_declaration -- : attributes? property_modifier* type member_name property_body -+ : attributes? property_modifier* 'partial'? type member_name property_body - ; + property_modifier + : 'new' + | 'public' + | 'protected' + | 'internal' + | 'private' + | 'static' + | 'virtual' + | 'sealed' + | 'override' + | 'abstract' + | 'extern' ++ | 'partial' + ; ``` -**Remarks**: This is somewhat similar to how *method_header* [(§15.6.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1561-general) and *class_declaration* [(§15.2.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1521-general) are specified. (Note that [Issue #946](https://github.com/dotnet/csharplang/issues/946) proposes to relax the ordering requirement, and would probably apply to all declarations which allow the `partial` modifier. We intend to specify such an ordering relaxation in the near future, and implement it in the same release that this feature is implemented.) +See also [Relaxed ordering requirement](#relaxed-ordering-requirement) for similar changes to the method, class, struct and interface grammars. ### Defining and implementing declarations When a property declaration includes a *partial* modifier, that property is said to be a *partial property*. Partial properties may only be declared as members of partial types. @@ -226,6 +238,119 @@ partial class C } ``` +### Relaxed ordering requirement + +- https://github.com/dotnet/csharplang/issues/946 +- https://github.com/dotnet/csharplang/blob/main/meetings/2020/LDM-2020-09-09.md#champion-relax-ordering-constraints-around-ref-and-partial-modifiers-on-type-declarations + +In C# 12 and prior, `partial` can only be used as the last modifier before a method return type, or as the last modifier before type declaration keywords `class`, `struct`, or `interface`. Similar restrictions are in place for the `ref` modifier on a `struct` declaration. + +In C# 13, `partial` will become just like any other modifier on the above-mentioned declarations, and can appear in any order in the modifier list. The same behavior will apply for properties. The `ref` modifier will be similarly relaxed on `struct` declarations. + +#### Detailed design + +The property grammar is given in [Grammar](#grammar). + +The method grammar [(§15.6.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1561-general) is updated as follows: + +```diff + method_modifiers +- : method_modifier* 'partial'? ++ : method_modifier* + ; + + method_modifier + : ref_method_modifier + | 'async' + ; + + ref_method_modifier + : 'new' + | 'public' + | 'protected' + | 'internal' + | 'private' + | 'static' + | 'virtual' + | 'sealed' + | 'override' + | 'abstract' + | 'extern' ++ | 'partial' + | unsafe_modifier // unsafe code support + ; +``` + +The classes grammar [(§15.2.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1521-general) is updated as follows: + +```diff + class_declaration +- : attributes? class_modifier* 'partial'? 'class' identifier ++ : attributes? class_modifier* 'class' identifier + type_parameter_list? class_base? type_parameter_constraints_clause* + class_body ';'? + ; + + class_modifier + : 'new' + | 'public' + | 'protected' + | 'internal' + | 'private' + | 'abstract' + | 'sealed' + | 'static' ++ | 'partial' + | unsafe_modifier // unsafe code support + ; +``` + +The interfaces grammar [(§18.2.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/interfaces.md#1821-general) is updated as follows: + +```diff + interface_declaration +- : attributes? interface_modifier* 'partial'? 'interface' ++ : attributes? interface_modifier* 'interface' + identifier variant_type_parameter_list? interface_base? + type_parameter_constraints_clause* interface_body ';'? + ; + + interface_modifier + : 'new' + | 'public' + | 'protected' + | 'internal' + | 'private' ++ | 'partial' + | unsafe_modifier // unsafe code support + ; +``` + +The structs grammar [(§18.2.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/structs.md#1621-general) is updated as follows: + +```diff + struct_declaration +- : attributes? struct_modifier* 'ref'? 'partial'? 'struct' ++ : attributes? struct_modifier* 'struct' + identifier type_parameter_list? struct_interfaces? + type_parameter_constraints_clause* struct_body ';'? + ; +``` + +```diff + struct_modifier + : 'new' + | 'public' + | 'protected' + | 'internal' + | 'private' + | 'readonly' ++ | 'ref' ++ | 'partial' + | unsafe_modifier // unsafe code support + ; +``` + ## Open Issues ### Other member kinds From bffe5baea805672bc9caeeed848c14f2c28bd228 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Mon, 3 Nov 2025 10:44:40 -0800 Subject: [PATCH 2/3] Extract to new proposal --- proposals/csharp-13.0/partial-properties.md | 137 +--------- proposals/relaxed-partial-ref-ordering.md | 265 ++++++++++++++++++++ 2 files changed, 271 insertions(+), 131 deletions(-) create mode 100644 proposals/relaxed-partial-ref-ordering.md diff --git a/proposals/csharp-13.0/partial-properties.md b/proposals/csharp-13.0/partial-properties.md index adb304e28a..cbe6867f02 100644 --- a/proposals/csharp-13.0/partial-properties.md +++ b/proposals/csharp-13.0/partial-properties.md @@ -6,28 +6,16 @@ Champion issue: ### Grammar -The partial modifier on properties is treated just like any other modifier and can be included in any position in a modifier list. - -The property grammar [(§15.7.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1571-general) is updated as follows: +The *property_declaration* grammar [(§14.7.1)](https://github.com/dotnet/csharpstandard/blob/draft-v7/standard/classes.md#1471-general) is updated as follows: ```diff - property_modifier - : 'new' - | 'public' - | 'protected' - | 'internal' - | 'private' - | 'static' - | 'virtual' - | 'sealed' - | 'override' - | 'abstract' - | 'extern' -+ | 'partial' - ; +property_declaration +- : attributes? property_modifier* type member_name property_body ++ : attributes? property_modifier* 'partial'? type member_name property_body + ; ``` -See also [Relaxed ordering requirement](#relaxed-ordering-requirement) for similar changes to the method, class, struct and interface grammars. +**Remarks**: This is somewhat similar to how *method_header* [(§15.6.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1561-general) and *class_declaration* [(§15.2.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1521-general) are specified. (Note that [Issue #946](https://github.com/dotnet/csharplang/issues/946) proposes to relax the ordering requirement, and would probably apply to all declarations which allow the `partial` modifier. We intend to specify such an ordering relaxation in the near future, and implement it in the same release that this feature is implemented.) ### Defining and implementing declarations When a property declaration includes a *partial* modifier, that property is said to be a *partial property*. Partial properties may only be declared as members of partial types. @@ -286,119 +274,6 @@ partial class C } ``` -### Relaxed ordering requirement - -- https://github.com/dotnet/csharplang/issues/946 -- https://github.com/dotnet/csharplang/blob/main/meetings/2020/LDM-2020-09-09.md#champion-relax-ordering-constraints-around-ref-and-partial-modifiers-on-type-declarations - -In C# 12 and prior, `partial` can only be used as the last modifier before a method return type, or as the last modifier before type declaration keywords `class`, `struct`, or `interface`. Similar restrictions are in place for the `ref` modifier on a `struct` declaration. - -In C# 13, `partial` will become just like any other modifier on the above-mentioned declarations, and can appear in any order in the modifier list. The same behavior will apply for properties. The `ref` modifier will be similarly relaxed on `struct` declarations. - -#### Detailed design - -The property grammar is given in [Grammar](#grammar). - -The method grammar [(§15.6.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1561-general) is updated as follows: - -```diff - method_modifiers -- : method_modifier* 'partial'? -+ : method_modifier* - ; - - method_modifier - : ref_method_modifier - | 'async' - ; - - ref_method_modifier - : 'new' - | 'public' - | 'protected' - | 'internal' - | 'private' - | 'static' - | 'virtual' - | 'sealed' - | 'override' - | 'abstract' - | 'extern' -+ | 'partial' - | unsafe_modifier // unsafe code support - ; -``` - -The classes grammar [(§15.2.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1521-general) is updated as follows: - -```diff - class_declaration -- : attributes? class_modifier* 'partial'? 'class' identifier -+ : attributes? class_modifier* 'class' identifier - type_parameter_list? class_base? type_parameter_constraints_clause* - class_body ';'? - ; - - class_modifier - : 'new' - | 'public' - | 'protected' - | 'internal' - | 'private' - | 'abstract' - | 'sealed' - | 'static' -+ | 'partial' - | unsafe_modifier // unsafe code support - ; -``` - -The interfaces grammar [(§18.2.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/interfaces.md#1821-general) is updated as follows: - -```diff - interface_declaration -- : attributes? interface_modifier* 'partial'? 'interface' -+ : attributes? interface_modifier* 'interface' - identifier variant_type_parameter_list? interface_base? - type_parameter_constraints_clause* interface_body ';'? - ; - - interface_modifier - : 'new' - | 'public' - | 'protected' - | 'internal' - | 'private' -+ | 'partial' - | unsafe_modifier // unsafe code support - ; -``` - -The structs grammar [(§18.2.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/structs.md#1621-general) is updated as follows: - -```diff - struct_declaration -- : attributes? struct_modifier* 'ref'? 'partial'? 'struct' -+ : attributes? struct_modifier* 'struct' - identifier type_parameter_list? struct_interfaces? - type_parameter_constraints_clause* struct_body ';'? - ; -``` - -```diff - struct_modifier - : 'new' - | 'public' - | 'protected' - | 'internal' - | 'private' - | 'readonly' -+ | 'ref' -+ | 'partial' - | unsafe_modifier // unsafe code support - ; -``` - ## Open Issues ### Other member kinds diff --git a/proposals/relaxed-partial-ref-ordering.md b/proposals/relaxed-partial-ref-ordering.md new file mode 100644 index 0000000000..339e675e5d --- /dev/null +++ b/proposals/relaxed-partial-ref-ordering.md @@ -0,0 +1,265 @@ +# Relaxed ordering for `partial` and `ref` modifiers + +Champion issue: https://github.com/dotnet/csharplang/issues/946 + +## Summary +[summary]: #summary + +- https://github.com/dotnet/csharplang/issues/946 +- https://github.com/dotnet/csharplang/blob/main/meetings/2020/LDM-2020-09-09.md#champion-relax-ordering-constraints-around-ref-and-partial-modifiers-on-type-declarations + +Allow the `partial` modifier to appear in any position in a modifier list on a type or member declaration. +Allow the `ref` modifier to appear in any position in a modifier list on a struct declaration. + +```cs +// All errors in this sample would be removed by adopting the proposal: +internal partial class C { } +partial internal class C { } // error + +internal ref struct RS { } +ref internal struct RS { } // error + +internal ref partial struct RS { } +internal partial ref struct RS { } // error +partial ref internal struct RS { } // error + +partial class Program +{ + public partial Program(); + partial public Program() { } // error + + public partial int Prop { get; set; } + partial public int Prop { get => field; set; } // error + + public partial void Method(); + partial public void Method() { } // error + + partial public event Action Event; // error + public partial event Action Event { add { } remove { } } +} +``` + +## Motivation +[motivation]: #motivation + +Most modifiers in the language can be written in any order. It feels arbitrary that `partial` and `ref` use a more stringent rule, and need to come at the end of the modifier list. This is especially cumbersome in the case of `ref partial` on structs, where even the opposite order `partial ref` is not permitted. + +In order to avoid getting in the user's way needlessly, we should allow `partial` and `ref` modifiers to appear in any position in a modifier list, just like the other modifiers. + +## Detailed design +[design]: #detailed-design + +Note that some of the below grammars are from C# 7 and are missing more recent modifiers such as `required` and `file.` +Since we have a precedent for contextual keywords `required` and `file` being modifiers, we believe we know how to parse `partial` as a modifier in any valid position it could appear in. + +The method grammar [(§15.6.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1561-general) is updated as follows: + +```diff + method_modifiers +- : method_modifier* 'partial'? ++ : method_modifier* + ; + + method_modifier + : ref_method_modifier + | 'async' + ; + + ref_method_modifier + : 'new' + | 'public' + | 'protected' + | 'internal' + | 'private' + | 'static' + | 'virtual' + | 'sealed' + | 'override' + | 'abstract' + | 'extern' ++ | 'partial' + | unsafe_modifier // unsafe code support + ; +``` + +The property grammar [(§15.7.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1571-general) is updated as follows: + +```diff +property_declaration +- : attributes? property_modifier* 'partial'? type member_name property_body ++ : attributes? property_modifier* type member_name property_body + ; + + property_modifier + : 'new' + | 'public' + | 'protected' + | 'internal' + | 'private' + | 'static' + | 'virtual' + | 'sealed' + | 'override' + | 'abstract' + | 'extern' ++ | 'partial' + ; +``` + +The event grammar [(§15.8.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1581-general) is updated as follows: + +```diff + event_declaration +- : attributes? event_modifier* 'partial'? 'event' type variable_declarators ';' ++ : attributes? event_modifier* 'event' type variable_declarators ';' +- | attributes? event_modifier* 'partial'? 'event' type member_name ++ | attributes? event_modifier* 'event' type member_name + '{' event_accessor_declarations '}' + ; + + event_modifier + : 'new' + | 'public' + | 'protected' + | 'internal' + | 'private' + | 'static' + | 'virtual' + | 'sealed' + | 'override' + | 'abstract' + | 'extern' ++ | 'partial' + | unsafe_modifier // unsafe code support + ; +``` + +The indexer grammar [(§15.9.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1591-general) is updated as follows: + +```diff +indexer_declaration +- : attributes? indexer_modifier* 'partial'? indexer_declarator indexer_body ++ : attributes? indexer_modifier* indexer_declarator indexer_body +- | attributes? indexer_modifier* 'partial'? ref_kind indexer_declarator ref_indexer_body ++ | attributes? indexer_modifier* ref_kind indexer_declarator ref_indexer_body + ; + + indexer_modifier + : 'new' + | 'public' + | 'protected' + | 'internal' + | 'private' + | 'virtual' + | 'sealed' + | 'override' + | 'abstract' + | 'extern' ++ | 'partial' + | unsafe_modifier // unsafe code support + ; +``` + +Instance constructor declaration syntax [(§15.11.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#15111-general) is updated as follows: + +```diff + constructor_declaration +- : attributes? constructor_modifier* 'partial'? constructor_declarator constructor_body ++ : attributes? constructor_modifier* constructor_declarator constructor_body + ; + + constructor_modifier + : 'public' + | 'protected' + | 'internal' + | 'private' + | 'extern' ++ | 'partial' + | unsafe_modifier // unsafe code support + ; +``` + +The classes grammar [(§15.2.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1521-general) is updated as follows: + +```diff + class_declaration +- : attributes? class_modifier* 'partial'? 'class' identifier ++ : attributes? class_modifier* 'class' identifier + type_parameter_list? class_base? type_parameter_constraints_clause* + class_body ';'? + ; + + class_modifier + : 'new' + | 'public' + | 'protected' + | 'internal' + | 'private' + | 'abstract' + | 'sealed' + | 'static' ++ | 'partial' + | unsafe_modifier // unsafe code support + ; +``` + +The interfaces grammar [(§18.2.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/interfaces.md#1821-general) is updated as follows: + +```diff + interface_declaration +- : attributes? interface_modifier* 'partial'? 'interface' ++ : attributes? interface_modifier* 'interface' + identifier variant_type_parameter_list? interface_base? + type_parameter_constraints_clause* interface_body ';'? + ; + + interface_modifier + : 'new' + | 'public' + | 'protected' + | 'internal' + | 'private' ++ | 'partial' + | unsafe_modifier // unsafe code support + ; +``` + +The structs grammar [(§18.2.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/structs.md#1621-general) is updated as follows: + +```diff + struct_declaration +- : attributes? struct_modifier* 'ref'? 'partial'? 'struct' ++ : attributes? struct_modifier* 'struct' + identifier type_parameter_list? struct_interfaces? + type_parameter_constraints_clause* struct_body ';'? + ; +``` + +```diff + struct_modifier + : 'new' + | 'public' + | 'protected' + | 'internal' + | 'private' + | 'readonly' ++ | 'ref' ++ | 'partial' + | unsafe_modifier // unsafe code support + ; +``` + +## Drawbacks +[drawbacks]: #drawbacks + +N/A + +## Alternatives +[alternatives]: #alternatives + +We could decide that we don't want to change this. In that case, the next time we spec allowing a new declaration kind to be `partial` or `ref`, we won't have to spend time thinking about whether now is the time to remove the ordering restriction. + +## Open questions +[open]: #open-questions + +N/A From 591a2b18cd261d7128e7fc5075c9788f1830abd5 Mon Sep 17 00:00:00 2001 From: Rikki Gibson Date: Tue, 4 Nov 2025 08:36:28 -0800 Subject: [PATCH 3/3] Update proposals/relaxed-partial-ref-ordering.md Co-authored-by: Jan Jones --- proposals/relaxed-partial-ref-ordering.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/proposals/relaxed-partial-ref-ordering.md b/proposals/relaxed-partial-ref-ordering.md index 339e675e5d..9e4a57ce11 100644 --- a/proposals/relaxed-partial-ref-ordering.md +++ b/proposals/relaxed-partial-ref-ordering.md @@ -49,7 +49,7 @@ In order to avoid getting in the user's way needlessly, we should allow `partial ## Detailed design [design]: #detailed-design -Note that some of the below grammars are from C# 7 and are missing more recent modifiers such as `required` and `file.` +Note that some of the below grammars are from C# 7 and are missing more recent modifiers such as `required` and `file`. Since we have a precedent for contextual keywords `required` and `file` being modifiers, we believe we know how to parse `partial` as a modifier in any valid position it could appear in. The method grammar [(§15.6.1)](https://github.com/dotnet/csharpstandard/blob/standard-v7/standard/classes.md#1561-general) is updated as follows: