diff --git a/standard/classes.md b/standard/classes.md index 12e4484cf..b44ad36a4 100644 --- a/standard/classes.md +++ b/standard/classes.md @@ -49,6 +49,7 @@ class_modifier | 'abstract' | 'sealed' | 'static' + | 'file' | unsafe_modifier // unsafe code support ; ``` @@ -61,10 +62,22 @@ The `new` modifier is permitted on nested classes. It specifies that the class h The `public`, `protected`, `internal`, and `private` modifiers control the accessibility of the class. Depending on the context in which the class declaration occurs, some of these modifiers might not be permitted ([§7.4.2](basic-concepts.md#742-declared-accessibility)). +It is a compile-time error for any of the `public`, `protected`, `internal`, and `private` modifiers to be combined with the `file` modifier. + When a partial type declaration ([§15.2.7](classes.md#1527-partial-type-declarations)) includes an accessibility specification (via the `public`, `protected`, `internal`, and `private` modifiers), that specification shall agree with all other parts that include an accessibility specification. If no part of a partial type includes an accessibility specification, the type is given the appropriate default accessibility ([§7.4.2](basic-concepts.md#742-declared-accessibility)). The `abstract`, `sealed`, and `static` modifiers are discussed in the following subclauses. +The `file` modifier specifies that the type being declared is local to its parent compilation unit. A compilation unit containing a `file`-modified type shall not also contain a type declaration having the same name but without the `file` modifier. (`file` is a contextual keyword (§6.4.4) that has special meaning when used as a top-level type modifier.) + +The `file` modifier shall only appear in a type declaration for a top-level type. + +When a type declaration contains the `file` modifier, that type is said to be a ***file-local type***. + +The implementation shall guarantee that two type declarations are distinct at runtime when either both are file-local types with the same name declared in different compilation units, or one is a file-local type and the other is a non-file-local type with the same name. + +A file-local class that is an attribute type may be used as an attribute within both file-local types and non-file-local types, just as if the attribute type were a non-file-local class. + #### 15.2.2.2 Abstract classes The `abstract` modifier is used to indicate that a class is incomplete and that it is intended to be used only as a base class. An ***abstract class*** differs from a ***non-abstract class*** in the following ways: @@ -249,6 +262,8 @@ The direct base class of a class type shall be at least as accessible as the cla The direct base class of a class type shall not be any of the following types: `System.Array`, `System.Delegate`, `System.Enum`, `System.ValueType` or the `dynamic` type. Furthermore, a generic class declaration shall not use `System.Attribute` as a direct or indirect base class ([§23.2.1](attributes.md#2321-general)). +A file-local class shall not be used as a base type of a non-file-local class. + In determining the meaning of the direct base class specification `A` of a class `B`, the direct base class of `B` is temporarily assumed to be `object`, which ensures that the meaning of a base class specification cannot recursively depend on itself. Given this definition, the complete set of types upon which a class depends is the transitive closure of the *directly depends on* relationship. > *Example*: The following @@ -783,6 +798,8 @@ The modifier `partial` is used when defining a class, struct, or interface type Each part of a ***partial type*** declaration shall include a `partial` modifier and shall be declared in the same namespace or containing type as the other parts. The `partial` modifier indicates that additional parts of the type declaration might exist elsewhere, but the existence of such additional parts is not a requirement; it is valid for the only declaration of a type to include the `partial` modifier. It is valid for only one declaration of a partial type to include the base class or implemented interfaces. However, all declarations of a base class or implemented interfaces shall match, including the nullability of any specified type arguments. +For a partial type, either all parts shall include the `file` modifier and be declared in the same compilation unit, or no part shall include the `file` modifier. + All parts of a partial type shall be compiled together such that the parts can be merged at compile-time. Partial types specifically do not allow already compiled types to be extended. Nested types may be declared in multiple parts by using the `partial` modifier. Typically, the containing type is declared using `partial` as well, and each part of the nested type is declared in a different part of the containing type. @@ -861,6 +878,8 @@ class_member_declaration ; ``` +The signature of a member in a non-file-local type shall not contain a file-local type. + The members of a class are divided into the following categories: - Constants, which represent constant values associated with the class ([§15.4](classes.md#154-constants)). diff --git a/standard/delegates.md b/standard/delegates.md index e22563e71..8cb8e8407 100644 --- a/standard/delegates.md +++ b/standard/delegates.md @@ -29,6 +29,7 @@ delegate_modifier | 'protected' | 'internal' | 'private' + | 'file' | unsafe_modifier // unsafe code support ; ``` @@ -41,7 +42,9 @@ A delegate declaration that supplies a *variant_type_parameter_list* is a generi The `new` modifier is only permitted on delegates declared within another type, in which case it specifies that such a delegate hides an inherited member by the same name, as described in [§15.3.5](classes.md#1535-the-new-modifier). -The `public`, `protected`, `internal`, and `private` modifiers control the accessibility of the delegate type. Depending on the context in which the delegate declaration occurs, some of these modifiers might not be permitted ([§7.4.2](basic-concepts.md#742-declared-accessibility)). +The `public`, `protected`, `internal`, and `private` modifiers control the accessibility of the delegate type. Depending on the context in which the delegate declaration occurs, some of these modifiers might not be permitted ([§7.4.2](basic-concepts.md#742-declared-accessibility)). It is a compile-time error for any of the `public`, `protected`, `internal`, and `private` modifiers to be combined with the `file` modifier. + +The modifier `file` has the same meaning as that for a class declaration ([§15.2.2](classes.md#1522-class-modifiers)). The delegate’s type name is *identifier*. diff --git a/standard/enums.md b/standard/enums.md index 8c397bb23..f44b53f91 100644 --- a/standard/enums.md +++ b/standard/enums.md @@ -85,11 +85,14 @@ enum_modifier | 'protected' | 'internal' | 'private' + | 'file' ; ``` It is a compile-time error for the same modifier to appear multiple times in an enum declaration. +It is a compile-time error for any of the `public`, `protected`, `internal`, and `private` modifiers to be combined with the `file` modifier. + The modifiers of an enum declaration have the same meaning as those of a class declaration ([§15.2.2](classes.md#1522-class-modifiers)). However, the `abstract`, and `sealed`, and `static` modifiers are not permitted in an enum declaration. Enums cannot be abstract and do not permit derivation. ## 20.4 Enum members diff --git a/standard/expressions.md b/standard/expressions.md index 8bef27ddf..c64fbe50f 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -378,6 +378,8 @@ A member lookup of a name `N` with `K` type arguments in a type `T` is proces - If `T` is a type parameter, then the set is the union of the sets of accessible members named `N` in each of the types specified as a primary constraint or secondary constraint ([§15.2.5](classes.md#1525-type-parameter-constraints)) for `T`, along with the set of accessible members named `N` in `object`. - Otherwise, the set consists of all accessible ([§7.4](basic-concepts.md#74-member-access)) members named `N` in `T`, including inherited members and the accessible members named `N` in `object`. If `T` is a constructed type, the set of members is obtained by substituting type arguments as described in [§15.3.3](classes.md#1533-members-of-constructed-types). Members that include an `override` modifier are excluded from the set. - Next, if `K` is zero, all nested types whose declarations include type parameters are removed. If `K` is not zero, all members with a different number of type parameters are removed. When `K` is zero, methods having type parameters are not removed, since the type inference process ([§12.6.3](expressions.md#1263-type-inference)) might be able to infer the type arguments. +- Next, let *F* be the compilation unit that contains the expression where member lookup is occurring. All members that are file-local types and are not declared in *F* are removed from the set. +- Next, if the set of accessible members contains file-local types, all members that are not file-local types are removed from the set. - Next, if the member is invoked, all non-invocable members are removed from the set. - Next, members that are hidden by other members are removed from the set. For every member `S.M` in the set, where `S` is the type in which the member `M` is declared, the following rules are applied: - If `M` is a constant, field, property, event, or enumeration member, then all members declared in a base type of `S` are removed from the set. diff --git a/standard/interfaces.md b/standard/interfaces.md index 467f648bc..62e0b8d36 100644 --- a/standard/interfaces.md +++ b/standard/interfaces.md @@ -40,6 +40,7 @@ interface_modifier | 'protected' | 'internal' | 'private' + | 'file' | unsafe_modifier // unsafe code support ; ``` @@ -52,6 +53,10 @@ The `new` modifier is only permitted on interfaces defined within a class. It sp The `public`, `protected`, `internal`, and `private` modifiers control the accessibility of the interface. Depending on the context in which the interface declaration occurs, only some of these modifiers might be permitted ([§7.4.2](basic-concepts.md#742-declared-accessibility)). When a partial type declaration ([§15.2.7](classes.md#1527-partial-type-declarations)) includes an accessibility specification (via the `public`, `protected`, `internal`, and `private` modifiers), the rules in [§15.2.2](classes.md#1522-class-modifiers) apply. +It is a compile-time error for any of the `public`, `protected`, `internal`, and `private` modifiers to be combined with the `file` modifier. + +The modifier `file` is described in [§15.2.2](classes.md#1522-class-modifiers). + ### 19.2.3 Variant type parameter lists #### 19.2.3.1 General diff --git a/standard/lexical-structure.md b/standard/lexical-structure.md index 707b3a5b0..697a3a3c4 100644 --- a/standard/lexical-structure.md +++ b/standard/lexical-structure.md @@ -78,9 +78,10 @@ These productions occur in contexts where a value can occur in an expression, an If a sequence of tokens can be parsed, in context, as one of the disambiguated productions including an optional *type_argument_list* ([§8.4.2](types.md#842-type-arguments)), then the token immediately following the closing `>` token shall be examined and if it is: -- one of `( ) ] } : ; , . ? == != | ^ && || & [`; or +- one of `( ) ] } : ; , . ? == != | ^ && || & [ =>`; or - one of the relational operators `< <= >= is as`; or - a contextual query keyword appearing inside a query expression. +- In certain contexts, *identifier* is treated as a disambiguating token. Those contexts are where the sequence of tokens being disambiguated is immediately preceded by one of the keywords `is`, `case` or `out`, or arises while parsing the first element of a tuple literal (in which case the tokens are preceded by `(` or `:` and the identifier is followed by a `,`) or a subsequent element of a tuple literal. then the *type_argument_list* shall be retained as part of the disambiguated production and any other possible parse of the sequence of tokens discarded. Otherwise, the tokens parsed as a *type_argument_list* shall not be considered to be part of the disambiguated production, even if there is no other possible parse of those tokens. @@ -134,24 +135,6 @@ then the *type_argument_list* shall be retained as part of the disambiguated pro > > *end example* -When recognising a *relational_expression* ([§12.15.1](expressions.md#12151-general)) if both the “*relational_expression* `is` *type*” and “*relational_expression* `is` *pattern*” alternatives are applicable, and *type* resolves to an accessible type, then the “*relational_expression* `is` *type*” alternative shall be chosen. - -To differentiate a collection initializer ([§12.8.17.2.3](expressions.md#1281723-collection-initializers)) with an element assignment, from a collection initializer with a lambda expression, the parser shall look ahead. Consider the following: - -```csharp -var y = new C { [A] = x }; // OK: y[A] = x -var z = new C { [A] x => x }; // OK: z[0] = [A] x => x -``` - -The parser shall treat `?[` as the start of a *null_conditional_element_access* ([[§12.8.13](expressions.md#12813-null-conditional-element-access)): - -```csharp -x = b ? [A]; // OK -y = b ? [A] () => { } : z; // error -``` - -To differentiate a method call `T()` from a lambda expression `T () => e`, the parser shall look ahead. - ## 6.3 Lexical analysis ### 6.3.1 General @@ -377,7 +360,7 @@ token ### 6.4.2 Unicode character escape sequences -A Unicode character escape sequence represents a Unicode code point. Unicode character escape sequences are processed in identifiers ([§6.4.3](lexical-structure.md#643-identifiers)), character literals ([§6.4.5.5](lexical-structure.md#6455-character-literals)), regular string literals ([§6.4.5.6](lexical-structure.md#6456-string-literals)), and interpolated regular string expressions ([§12.8.3](expressions.md#1283-interpolated-string-expressions)). A Unicode character escape sequence is not processed in any other location (for example, to form an operator, punctuator, keyword or contextual keyword). +A Unicode character escape sequence represents a Unicode code point. Unicode character escape sequences are processed in identifiers ([§6.4.3](lexical-structure.md#643-identifiers)), character literals ([§6.4.5.5](lexical-structure.md#6455-character-literals)), regular string literals ([§6.4.5.6](lexical-structure.md#6456-string-literals)), and interpolated regular string expressions ([§12.8.3](expressions.md#1283-interpolated-string-expressions)). A Unicode character escape sequence is not processed in any other location (for example, to form an operator, punctuator, or keyword). ```ANTLR fragment Unicode_Escape_Sequence @@ -622,14 +605,15 @@ A ***contextual keyword*** is an identifier-like sequence of characters that has ```ANTLR contextual_keyword - : 'add' | 'alias' | 'ascending' | 'async' | 'await' - | 'by' | 'Cdecl' | 'descending' | 'dynamic' | 'equals' - | 'Fastcall' | 'from' | 'get' | 'global' | 'group' - | 'init' | 'into' | 'join' | 'let' | 'managed' - | 'nameof' | 'nint' | 'notnull' | 'nuint' | 'on' - | 'orderby' | 'partial' | 'record' | 'remove' | 'select' - | 'set' | 'Stdcall' | 'Thiscall' | 'unmanaged' | 'value' - | 'var' | 'when' | 'where' | 'yield' + : 'add' | 'alias' | 'and' | 'ascending' | 'async' + | 'await' | 'by' | 'Cdecl' | 'descending'| 'dynamic' + | 'equals' | 'Fastcall' | 'file' | 'from' | 'get' + | 'global' | 'group' | 'init' | 'into' | 'join' + | 'let' | 'managed' | 'nameof' | 'nint' | 'not' + | 'notnull' | 'nuint' | 'on' | 'or' | 'orderby' + | 'partial' | 'record' | 'remove' | 'select' | 'set' + | 'Stdcall' | 'Thiscall' | 'unmanaged' | 'value' | 'var' + | 'when' | 'where' | 'yield' ; ``` diff --git a/standard/namespaces.md b/standard/namespaces.md index aa0af96dc..77ee407c3 100644 --- a/standard/namespaces.md +++ b/standard/namespaces.md @@ -289,6 +289,8 @@ A *global_using_static_directive* only imports members and types declared direct Ambiguities between multiple *global_using_namespace_directive*s and *global_using_static_directives* are discussed in [§14.5.3](namespaces.md#1453-global-using-namespace-directives). +It is a compile-time error to use a file-local type in a *global_using_static_directive*. + ## 14.6 Using directives ### 14.6.1 General diff --git a/standard/structs.md b/standard/structs.md index c7b4b8385..fa293666e 100644 --- a/standard/structs.md +++ b/standard/structs.md @@ -60,6 +60,7 @@ struct_modifier | 'internal' | 'private' | 'readonly' + | 'file' | unsafe_modifier // unsafe code support ; ``` @@ -68,6 +69,8 @@ struct_modifier It is a compile-time error for the same modifier to appear multiple times in a struct declaration. +It is a compile-time error for any of the `public`, `protected`, `internal`, and `private` modifiers to be combined with the `file` modifier. + Except for `readonly`, the modifiers of a struct declaration have the same meaning as those of a class declaration ([§15.2.2](classes.md#1522-class-modifiers)). The `readonly` modifier indicates that the *struct_declaration* declares a type whose instances are immutable.