From 9e0a6725dad011a2de11eb2920538b84f2304c51 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Fri, 6 Feb 2026 15:53:26 -0500 Subject: [PATCH 1/5] support Global Using Directives --- standard/basic-concepts.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/standard/basic-concepts.md b/standard/basic-concepts.md index 294bd75a5..9ee849354 100644 --- a/standard/basic-concepts.md +++ b/standard/basic-concepts.md @@ -773,7 +773,8 @@ The ***scope*** of a name is the region of program text within which it is possi - The scope of a namespace member declared by a *namespace_member_declaration* ([§14.6](namespaces.md#146-namespace-member-declarations)) with no enclosing *namespace_declaration* is the entire program text. - The scope of a namespace member declared by a *namespace_member_declaration* within a *namespace_declaration* whose fully qualified name is `N`, is the *namespace_body* of every *namespace_declaration* whose fully qualified name is `N` or starts with `N`, followed by a period. -- The scope of a name defined by an *extern_alias_directive* ([§14.4](namespaces.md#144-extern-alias-directives)) extends over the *using_directive*s, *global_attributes* and *namespace_member_declaration*s of its immediately containing *compilation_unit* or *namespace_body*. An *extern_alias_directive* does not contribute any new members to the underlying declaration space. In other words, an *extern_alias_directive* is not transitive, but, rather, affects only the *compilation_unit* or *namespace_body* in which it occurs. +- The scope of a name defined by an *extern_alias_directive* ([§14.4](namespaces.md#144-extern-alias-directives)) extends over the *global_using_directive*s, *using_directive*s, *global_attributes* and *namespace_member_declaration*s of its immediately containing *compilation_unit* or *namespace_body*. An *extern_alias_directive* does not contribute any new members to the underlying declaration space. In other words, an *extern_alias_directive* is not transitive, but, rather, affects only the *compilation_unit* or *namespace_body* in which it occurs. +- The scope of a name defined or imported by a *global_using_directive* extends over the *global_attributes* and *namespace_member_declaration*s of all the *compilation_unit*s in the program. - The scope of a name defined or imported by a *using_directive* ([§14.5](namespaces.md#145-using-directives)) extends over the *global_attributes* and *namespace_member_declaration*s of the *compilation_unit* or *namespace_body* in which the *using_directive* occurs. A *using_directive* may make zero or more namespace or type names available within a particular *compilation_unit* or *namespace_body*, but does not contribute any new members to the underlying declaration space. In other words, a *using_directive* is not transitive but rather affects only the *compilation_unit* or *namespace_body* in which it occurs. - The scope of a type parameter declared by a *type_parameter_list* on a *class_declaration* ([§15.2](classes.md#152-class-declarations)) is the *class_base*, *type_parameter_constraints_clause*s, and *class_body* of that *class_declaration*. > *Note*: Unlike members of a class, this scope does not extend to derived classes. *end note* @@ -1098,15 +1099,15 @@ where: > *Note*: Non-type members (constants, fields, methods, properties, indexers, operators, instance constructors, finalizers, and static constructors) and type members with a different number of type parameters are ignored when determining the meaning of the *namespace_or_type_name*. *end note* - Otherwise, for each namespace `N`, starting with the namespace in which the *namespace_or_type_name* occurs, continuing with each enclosing namespace (if any), and ending with the global namespace, the following steps are evaluated until an entity is located: - If `x` is zero and `I` is the name of a namespace in `N`, then: - - If the location where the *namespace_or_type_name* occurs is enclosed by a namespace declaration for `N` and the namespace declaration contains an *extern_alias_directive* or *using_alias_directive* that associates the name `I` with a namespace or type, then the *namespace_or_type_name* is ambiguous and a compile-time error occurs. + - If the location where the *namespace_or_type_name* occurs is enclosed by a namespace declaration for `N` and the namespace declaration contains an *extern_alias_directive* or *using_alias_directive* that associates the name `I` with a namespace or type, or any namespace declaration for `N` in the program contains a *global_using_alias_directive* that associates the name `I` with a namespace or type, then the *namespace_or_type_name* is ambiguous and a compile-time error occurs. - Otherwise, `R₀` refers to the namespace named `I` in `N`. - Otherwise, if `N` contains an accessible type having name `I` and `x` type parameters, then: - - If `x` is zero and the location where the *namespace_or_type_name* occurs is enclosed by a namespace declaration for `N` and the namespace declaration contains an *extern_alias_directive* or *using_alias_directive* that associates the name `I` with a namespace or type, then the *namespace_or_type_name* is ambiguous and a compile-time error occurs. + - If `x` is zero and the location where the *namespace_or_type_name* occurs is enclosed by a namespace declaration for `N` and the namespace declaration contains an *extern_alias_directive* or *using_alias_directive* that associates the name `I` with a namespace or type, or any namespace declaration for `N` in the program contains a *global_using_alias_directive* that associates the name `I` with a namespace or type, then the *namespace_or_type_name* is ambiguous and a compile-time error occurs. - Otherwise, `R₀` refers to the type constructed with the given type arguments. - Otherwise, if the location where the *namespace_or_type_name* occurs is enclosed by a namespace declaration for `N`: - - If `x` is zero and the namespace declaration contains an *extern_alias_directive* or *using_alias_directive* that associates the name `I` with an imported namespace or type, then `R₀` refers to that namespace or type. - - Otherwise, if the namespaces imported by the *using_namespace_directive*s of the namespace declaration contain exactly one type having name `I` and `x` type parameters, then `R₀` refers to that type constructed with the given type arguments. - - Otherwise, if the namespaces imported by the *using_namespace_directive*s of the namespace declaration contain more than one type having name `I` and `x` type parameters, then the *namespace_or_type_name* is ambiguous and a compile-time error occurs. + - If `x` is zero and the namespace declaration contains an *extern_alias_directive* or *using_alias_directive* that associates the name `I` with an imported namespace or type, or any namespace declaration for `N` in the program contains a *global_using_alias_directive* that associates the name `I` with an imported namespace or type, then `R₀` refers to that namespace or type. + - Otherwise, if the namespaces imported by the *using_namespace_directive*s of the namespace declaration and the namespaces and type declarations imported by the *global_using_namespace_directive*s and *global_using_static_directive*s of any namespace declaration for `N` in the program contain exactly one type having name `I` and `x` type parameters, then `R₀` refers to that type constructed with the given type arguments. + - Otherwise, if the namespaces imported by the *using_namespace_directive*s of the namespace declaration and the namespaces and type declarations imported by the *global_using_namespace_directive*s and *global_using_static_directive*s of any namespace declaration for `N` in the program contain more than one type having name `I` and `x` type parameters, then the *namespace_or_type_name* is ambiguous and a compile-time error occurs. - Otherwise, the *namespace_or_type_name* is undefined and a compile-time error occurs. If `R₀` has been resolved successfully the trailing part of the *namespace_or_type_name* is resolved. The trailing grammar fragment consists of `k ≥ 0` repetitions, with each repetition further resolving the referenced namespace or type. From 80b835ad1ee6528604ef60bf1fd6c01a3b791cd8 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Fri, 6 Feb 2026 16:06:01 -0500 Subject: [PATCH 2/5] support Global Using Directives --- standard/expressions.md | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index d5bf99b47..8c17c4415 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -1593,15 +1593,15 @@ A *simple_name* is either of the form `I` or of the form `I`, - Otherwise, the result is the same as a member access ([§12.8.7](expressions.md#1287-member-access)) of the form `T.I` or `T.I`. - Otherwise, for each namespace `N`, starting with the namespace in which the *simple_name* occurs, continuing with each enclosing namespace (if any), and ending with the global namespace, the following steps are evaluated until an entity is located: - If `e` is zero and `I` is the name of a namespace in `N`, then: - - If the location where the *simple_name* occurs is enclosed by a namespace declaration for `N` and the namespace declaration contains an *extern_alias_directive* or *using_alias_directive* that associates the name `I` with a namespace or type, then the *simple_name* is ambiguous and a compile-time error occurs. + - If the location where the *simple_name* occurs is enclosed by a namespace declaration for `N` and the namespace declaration contains an *extern_alias_directive* or *using_alias_directive* that associates the name `I` with a namespace or type, or any namespace declaration for `N` in the program contains a *global_using_alias_directive* that associates the name `I` with a namespace or type, then the *simple_name* is ambiguous and a compile-time error occurs. - Otherwise, the *simple_name* refers to the namespace named `I` in `N`. - Otherwise, if `N` contains an accessible type having name `I` and `e` type parameters, then: - - If `e` is zero and the location where the *simple_name* occurs is enclosed by a namespace declaration for `N` and the namespace declaration contains an *extern_alias_directive* or *using_alias_directive* that associates the name `I` with a namespace or type, then the *simple_name* is ambiguous and a compile-time error occurs. + - If `e` is zero and the location where the *simple_name* occurs is enclosed by a namespace declaration for `N` and the namespace declaration contains an *extern_alias_directive* or *using_alias_directive* that associates the name `I` with a namespace or type, or any namespace declaration for `N` in the program contains a *global_using_alias_directive* that associates the name `I` with a namespace or type, then the *simple_name* is ambiguous and a compile-time error occurs. - Otherwise, the *namespace_or_type_name* refers to the type constructed with the given type arguments. - Otherwise, if the location where the *simple_name* occurs is enclosed by a namespace declaration for `N`: - - If `e` is zero and the namespace declaration contains an *extern_alias_directive* or *using_alias_directive* that associates the name `I` with an imported namespace or type, then the *simple_name* refers to that namespace or type. - - Otherwise, if the namespaces imported by the *using_namespace_directive*s of the namespace declaration contain exactly one type having name `I` and `e` type parameters, then the *simple_name* refers to that type constructed with the given type arguments. - - Otherwise, if the namespaces imported by the *using_namespace_directive*s of the namespace declaration contain more than one type having name `I` and `e` type parameters, then the *simple_name* is ambiguous and a compile-time error occurs. + - If `e` is zero and the namespace declaration contains an *extern_alias_directive* or *using_alias_directive* that associates the name `I` with an imported namespace or type, or any namespace declaration for `N` in the program contains a *global_using_alias_directive* that associates the name `I` with an imported namespace or type, then the *simple_name* refers to that namespace or type. + - Otherwise, if the namespaces imported by the *using_namespace_directive*s of the namespace declaration and the namespaces and type declarations imported by the *global_using_namespace_directive*s and *global_using_static_directive*s of any namespace declaration for `N` in the program contain exactly one type having name `I` and `e` type parameters, then the *simple_name* refers to that type constructed with the given type arguments. + - Otherwise, if the namespaces imported by the *using_namespace_directive*s of the namespace declaration and the namespaces and type declarations imported by the *global_using_namespace_directive*s and *global_using_static_directive*s of any namespace declaration for `N` in the program contain more than one type having name `I` and `e` type parameters, then the *simple_name* is ambiguous and a compile-time error occurs. > *Note*: This entire step is exactly parallel to the corresponding step in the processing of a *namespace_or_type_name* ([§7.8](basic-concepts.md#78-namespace-and-type-names)). *end note* - Otherwise, if `e` is zero and `I` is the identifier `_`, the *simple_name* is a *simple discard*, which is a form of declaration expression ([§12.20](expressions.md#1220-declaration-expressions)). - Otherwise, the *simple_name* is undefined and a compile-time error occurs. @@ -2120,7 +2120,8 @@ The search for `C` proceeds as follows: - Starting with the closest enclosing namespace declaration, continuing with each enclosing namespace declaration, and ending with the containing compilation unit, successive attempts are made to find a candidate set of extension methods: - If the given namespace or compilation unit directly contains non-generic type declarations `Cᵢ` with eligible extension methods `Mₑ`, then the set of those extension methods is the candidate set. - - If namespaces imported by using namespace directives in the given namespace or compilation unit directly contain non-generic type declarations `Cᵢ` with eligible extension methods `Mₑ`, then the set of those extension methods is the candidate set. + - If types `Ci` imported by *using_static_declarations* and directly declared in namespaces imported by *using_namespace_directive*s in the given namespace or compilation unit **and, if containing compilation unit is reached, imported by *global_using_static_declarations* and directly declared in namespaces imported by *global_using_namespace_directive*s in the program** directly contain eligible extension methods `Mₑ`, then the set of those extension methods is the candidate set. +- `Mₑ`, then the set of those extension methods is the candidate set. - If no candidate set is found in any enclosing namespace declaration or compilation unit, a compile-time error occurs. - Otherwise, overload resolution is applied to the candidate set as described in [§12.6.4](expressions.md#1264-overload-resolution). If no single best method is found, a compile-time error occurs. - `C` is the type within which the best method is declared as an extension method. From e441094df035253cc5547b08eb43c5f7c5b9b0a8 Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Fri, 6 Feb 2026 16:16:20 -0500 Subject: [PATCH 3/5] support Global Using Directives --- standard/namespaces.md | 92 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 86 insertions(+), 6 deletions(-) diff --git a/standard/namespaces.md b/standard/namespaces.md index d5145d5a7..1af780c1a 100644 --- a/standard/namespaces.md +++ b/standard/namespaces.md @@ -8,11 +8,11 @@ Using directives ([§14.5](namespaces.md#145-using-directives)) are provided to ## 14.2 Compilation units -A *compilation_unit* consists of zero or more *extern_alias_directive*s followed by zero or more *using_directive*s followed by zero or one *global_attributes* followed by zero or more *statement_list*s followed by zero or more *namespace_member_declaration*s. The *compilation_unit* defines the overall structure of the input. +A *compilation_unit* consists of zero or more *extern_alias_directive*s followed by zero or more *global_using_directive*s followed by zero or more *using_directive*s followed by zero or one *global_attributes* followed by zero or more *statement_list*s followed by zero or more *namespace_member_declaration*s. The *compilation_unit* defines the overall structure of the input. ```ANTLR compilation_unit - : extern_alias_directive* using_directive* global_attributes? + : extern_alias_directive* global_using_directive* using_directive* global_attributes? statement_list* namespace_member_declaration* ; ``` @@ -126,7 +126,7 @@ extern_alias_directive ; ``` -The scope of an *extern_alias_directive* extends over the *using_directive*s, *global_attributes* and *namespace_member_declaration*s of its immediately containing *compilation_unit* or *namespace_body*. +The scope of an *extern_alias_directive* extends over *global_using_directive*s, the *using_directive*s, *global_attributes* and *namespace_member_declaration*s of its immediately containing *compilation_unit* or *namespace_body*. Within a compilation unit or namespace body that contains an *extern_alias_directive*, the identifier introduced by the *extern_alias_directive* can be used to reference the aliased namespace. It is a compile-time error for the *identifier* to be the word `global`. @@ -155,6 +155,86 @@ An error occurs if a program declares an extern alias for which no external defi > The program declares the existence of the extern aliases `X` and `Y`, but the actual definitions of the aliases are external to the program. The identically named `N.B` classes can now be referenced as `X.N.B` and `Y.N.B`, or, using the namespace alias qualifier, `X::N.B` and `Y::N.B`. > *end example* +### §global-using-directives-general General + +A ***global using directive*** is a using directive ([§14.5](namespaces.md#145-using-directives)) at the top level of a compilation unit. + +```ANTLR +global_using_directive + : global_using_alias_directive + | global_using_namespace_directive + | global_using_static_directive + ; +``` + +> *Note*: The scope of a *global_using_directive* extends over the *namespace_member_declaration*s of all compilation units within the program. The scope of a *global_using_directive* specifically does not include other *global_using_directive*s. Thus, peer *global_using_directive*s or those from a different compilation unit do not affect each other, and the order in which they are written is insignificant. The scope of a *global_using_directive* specifically does not include *using_directive*s immediately contained in any compilation unit of the program. +> +> The effect of adding a *global_using_directive* to a program can be thought of as the effect of adding a similar *using_directive* that resolves to the same target namespace or type to every compilation unit of the program. However, the target of a *global_using_directive* is resolved in the context of the compilation unit that contains it. *end note* + +### §global-using-alias-directives Global using alias directives + +A *global_using_alias_directive* introduces an identifier that serves as an alias for a namespace or type within the program. + +```ANTLR +global_using_alias_directive + : 'global' using_alias_directive + ; +``` + +Within member declarations in any compilation unit of a program that contains a *global_using_alias_directive*, the *identifier* introduced by the *global_using_alias_directive* can be used to reference the given namespace or type. + +The *identifier* of a *global_using_alias_directive* shall be unique within the declaration space of any compilation unit of a program that contains the *global_using_alias_directive*. + +Just like regular members, names introduced by *global_using_alias_directive*s are hidden by similarly named members in nested scopes. + +The order in which *global_using_alias_directive*s are written has no significance, and resolution of the *namespace_or_type_name* referenced by a *global_using_alias_directive* is not affected by the *global_using_alias_directive* itself or by other *global_using_directive*s or *using_directive*s in the program. In other words, the *namespace_or_type_name* of a *global_using_alias_directive* is resolved as if the immediately containing compilation unit had no *using_directive*s and the entire containing program had no *global_using_directive*s. A *global_using_alias_directive* may however be affected by *extern_alias_directive*s in the immediately containing compilation unit. + +A *global_using_alias_directive* can create an alias for any namespace or type. + +Accessing a namespace or type through an alias yields exactly the same result as accessing that namespace or type through its declared name. + +Using aliases can name a closed constructed type, but cannot name an unbound generic type declaration without supplying type arguments. + +### §global-using-namespace-directives Global using namespace directives + +A *global_using_namespace_directive* imports the types contained in a namespace into the program, enabling the identifier of each type to be used without qualification. + +```ANTLR +global_using_namespace_directive + : 'global' using_namespace_directive + ; +``` + +Within member declarations in a program that contains a *global_using_namespace_directive*, the types contained in the given namespace can be referenced directly. + +A *global_using_namespace_directive* imports the types contained in the given namespace, but specifically does not import nested namespaces. + +Unlike a *global_using_alias_directive*, a *global_using_namespace_directive* may import types whose identifiers are already defined within a compilation unit of the program. In effect, in a given compilation unit, names imported by any *global_using_namespace_directive* in the program are hidden by similarly named members in the compilation unit. + +When more than one namespace or type imported by *global_using_namespace_directive*s or *global_using_static_directive*s in the same program contain types by the same name, references to that name as a *type_name* are considered ambiguous. + +Furthermore, when more than one namespace or type imported by *global_using_namespace_directive*s or *global_using_static_directive*s in the same program contain types or members by the same name, references to that name as a *simple_name* are considered ambiguous. + +The *namespace_name* referenced by a *global_using_namespace_directive* is resolved in the same way as the *namespace_or_type_name* referenced by a *global_using_alias_directive*. Thus, *global_using_namespace_directive*s in the same program do not affect each other and can be written in any order. + +### §global-using-static-directives Global using static directives + +A *global_using_static_directive* imports the nested types and static members contained directly in a type declaration into the containing program, enabling the identifier of each member and type to be used without qualification. + +```ANTLR +global_using_static_directive + : 'global' using_static_directive + ; +``` + +Within member declarations in a program that contains a *global_using_static_directive*, the accessible nested types and static members (except extension methods) contained directly in the declaration of the given type can be referenced directly. + +A *global_using_static_directive* specifically does not import extension methods directly as static methods, but makes them available for extension method invocation. + +A *global_using_static_directive* only imports members and types declared directly in the given type, not members and types declared in base classes. + +Ambiguities between multiple *global_using_namespace_directive*s and *global_using_static_directives* are discussed in §global-using-namespace-directives. + ## 14.5 Using directives ### 14.5.1 General @@ -355,7 +435,7 @@ Just like regular members, names introduced by *alias_directives* are hidden by > > *end example* -The order in which *extern_alias_directive*s are written has no significance. Likewise, the order in which *using_alias_directive*s are written has no significance, but all *using_alias_directives* shall come after all *extern_alias_directive*s in the same compilation unit or namespace body. Resolution of the *namespace_or_type_name* referenced by a *using_alias_directive* is not affected by the *using_alias_directive* itself or by other *using_directive*s in the immediately containing compilation unit or namespace body, but may be affected by *extern_alias_directive*s in the immediately containing compilation unit or namespace body. In other words, the *namespace_or_type_name* of a *using_alias_directive* is resolved as if the immediately containing compilation unit or namespace body had no *using_directive*s but has the correct set of *extern_alias_directive*s. +The order in which *extern_alias_directive*s are written has no significance. Likewise, the order in which *using_alias_directive*s are written has no significance, but all *using_alias_directives* shall come after all *extern_alias_directive*s in the same compilation unit or namespace body. Resolution of the *namespace_or_type_name* referenced by a *using_alias_directive* is not affected by the *using_alias_directive* itself or by other *using_directive*s in the immediately containing compilation unit or namespace body, but may be affected by *extern_alias_directive*s in the immediately containing compilation unit or namespace body. And, if the *using_alias_directive* is immediately contained in a compilation unit, is not affected by the *global_using_directive*s in the program. In other words, the *namespace_or_type_name* of a *using_alias_directive* is resolved as if the immediately containing compilation unit or namespace body had no *using_directive*s and, if the *using_alias_directive* is immediately contained in a compilation unit, the program had no *global_using_directive*s** but has the correct set of *extern_alias_directive*s. > *Example*: In the following code > @@ -809,8 +889,8 @@ Using this notation, the meaning of a *qualified_alias_member* is determined as - Otherwise, if the global namespace contains a type named `I` that has `e` type parameters, then the *qualified_alias_member* refers to that type constructed with the given type arguments. - Otherwise, the *qualified_alias_member* is undefined and a compile-time error occurs. - Otherwise, starting with the namespace declaration ([§14.3](namespaces.md#143-namespace-declarations)) immediately containing the *qualified_alias_member* (if any), continuing with each enclosing namespace declaration (if any), and ending with the compilation unit containing the *qualified_alias_member*, the following steps are evaluated until an entity is located: - - If the namespace declaration or compilation unit contains a *using_alias_directive* that associates N with a type, then the *qualified_alias_member* is undefined and a compile-time error occurs. - - Otherwise, if the namespace declaration or compilation unit contains an *extern_alias_directive* or *using_alias_directive* that associates `N` with a namespace, then: + - If the namespace declaration or compilation unit contains a *using_alias_directive* that associates N with a type, or when a compilation unit is reached, the program contains a *global_using_alias_directive* that associates `N` with a type, then the *qualified_alias_member* is undefined and a compile-time error occurs. + - Otherwise, if the namespace declaration or compilation unit contains an *extern_alias_directive* or *using_alias_directive* that associates `N` with a namespace, or when a compilation unit is reached, the program contains a *global_using_alias_directive* that associates `N` with a namespace, then: - If the namespace associated with `N` contains a namespace named `I` and `e` is zero, then the *qualified_alias_member* refers to that namespace. - Otherwise, if the namespace associated with `N` contains a non-generic type named `I` and `e` is zero, then the *qualified_alias_member* refers to that type. - Otherwise, if the namespace associated with `N` contains a type named `I` that has `e` type parameters, then the *qualified_alias_member* refers to that type constructed with the given type arguments. From 70e6387dcca131244d7a13b81fa5eaaa5d94622f Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Fri, 27 Mar 2026 13:51:56 -0400 Subject: [PATCH 4/5] Small formatting issues. --- standard/expressions.md | 3 +-- standard/namespaces.md | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/standard/expressions.md b/standard/expressions.md index 8c17c4415..98178a163 100644 --- a/standard/expressions.md +++ b/standard/expressions.md @@ -2120,8 +2120,7 @@ The search for `C` proceeds as follows: - Starting with the closest enclosing namespace declaration, continuing with each enclosing namespace declaration, and ending with the containing compilation unit, successive attempts are made to find a candidate set of extension methods: - If the given namespace or compilation unit directly contains non-generic type declarations `Cᵢ` with eligible extension methods `Mₑ`, then the set of those extension methods is the candidate set. - - If types `Ci` imported by *using_static_declarations* and directly declared in namespaces imported by *using_namespace_directive*s in the given namespace or compilation unit **and, if containing compilation unit is reached, imported by *global_using_static_declarations* and directly declared in namespaces imported by *global_using_namespace_directive*s in the program** directly contain eligible extension methods `Mₑ`, then the set of those extension methods is the candidate set. -- `Mₑ`, then the set of those extension methods is the candidate set. + - If types `Cᵢ` imported by *using_static_directive*s and directly declared in namespaces imported by *using_namespace_directive*s in the given namespace or compilation unit, and, if the containing compilation unit is reached, imported by *global_using_static_directive*s and directly declared in namespaces imported by *global_using_namespace_directive*s in the program, directly contain eligible extension methods `Mₑ`, then the set of those extension methods is the candidate set. - If no candidate set is found in any enclosing namespace declaration or compilation unit, a compile-time error occurs. - Otherwise, overload resolution is applied to the candidate set as described in [§12.6.4](expressions.md#1264-overload-resolution). If no single best method is found, a compile-time error occurs. - `C` is the type within which the best method is declared as an extension method. diff --git a/standard/namespaces.md b/standard/namespaces.md index 1af780c1a..9421ff876 100644 --- a/standard/namespaces.md +++ b/standard/namespaces.md @@ -435,7 +435,7 @@ Just like regular members, names introduced by *alias_directives* are hidden by > > *end example* -The order in which *extern_alias_directive*s are written has no significance. Likewise, the order in which *using_alias_directive*s are written has no significance, but all *using_alias_directives* shall come after all *extern_alias_directive*s in the same compilation unit or namespace body. Resolution of the *namespace_or_type_name* referenced by a *using_alias_directive* is not affected by the *using_alias_directive* itself or by other *using_directive*s in the immediately containing compilation unit or namespace body, but may be affected by *extern_alias_directive*s in the immediately containing compilation unit or namespace body. And, if the *using_alias_directive* is immediately contained in a compilation unit, is not affected by the *global_using_directive*s in the program. In other words, the *namespace_or_type_name* of a *using_alias_directive* is resolved as if the immediately containing compilation unit or namespace body had no *using_directive*s and, if the *using_alias_directive* is immediately contained in a compilation unit, the program had no *global_using_directive*s** but has the correct set of *extern_alias_directive*s. +The order in which *extern_alias_directive*s are written has no significance. Likewise, the order in which *using_alias_directive*s are written has no significance, but all *using_alias_directives* shall come after all *extern_alias_directive*s in the same compilation unit or namespace body. Resolution of the *namespace_or_type_name* referenced by a *using_alias_directive* is not affected by the *using_alias_directive* itself or by other *using_directive*s in the immediately containing compilation unit or namespace body, but may be affected by *extern_alias_directive*s in the immediately containing compilation unit or namespace body. And, if the *using_alias_directive* is immediately contained in a compilation unit, is not affected by the *global_using_directive*s in the program. In other words, the *namespace_or_type_name* of a *using_alias_directive* is resolved as if the immediately containing compilation unit or namespace body had no *using_directive*s and, if the *using_alias_directive* is immediately contained in a compilation unit, the program had no *global_using_directive*s but has the correct set of *extern_alias_directive*s. > *Example*: In the following code > From 29a956ff7fbdb29081da66aef0dd62a2b34573de Mon Sep 17 00:00:00 2001 From: Bill Wagner Date: Fri, 27 Mar 2026 15:10:24 -0400 Subject: [PATCH 5/5] Address a few omissions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add a `## §global-using-directives Global using directives` heading before `### §global-using-directives-general General`. - Add after the `using_directive` paragraph: "The *global_using_directive*s of a compilation unit affect the *global_attributes* and *namespace_member_declaration*s of all compilation units in the program." Update to: "The *extern_alias_directive*s of a compilation unit affect the *global_using_directive*s, *using_directive*s, *global_attributes* and *namespace_member_declaration*s of that compilation unit, but have no effect on other compilation units." - Update to: "Using directives (§14.5) and global using directives (§global-using-directives) are provided to facilitate the use of namespaces." --- standard/namespaces.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/standard/namespaces.md b/standard/namespaces.md index 9421ff876..67fdc5c96 100644 --- a/standard/namespaces.md +++ b/standard/namespaces.md @@ -4,7 +4,7 @@ C# programs are organized using namespaces. Namespaces are used both as an “internal” organization system for a program, and as an “external” organization system—a way of presenting program elements that are exposed to other programs. -Using directives ([§14.5](namespaces.md#145-using-directives)) are provided to facilitate the use of namespaces. +Using directives (§14.5) and global using directives (§global-using-directives) are provided to facilitate the use of namespaces. ## 14.2 Compilation units @@ -19,10 +19,12 @@ compilation_unit A C# program consists of one or more compilation units. When a C# program is compiled, all of the compilation units are processed together. Thus, compilation units can depend on each other, possibly in a circular fashion. -The *extern_alias_directive*s of a compilation unit affect the *using_directive*s, *global_attributes* and *namespace_member_declaration*s of that compilation unit, but have no effect on other compilation units. +The *extern_alias_directive*s of a compilation unit affect the *global_using_directive*s, *using_directive*s, *global_attributes* and *namespace_member_declaration*s of that compilation unit, but have no effect on other compilation units. The *using_directive*s of a compilation unit affect the *global_attributes* and *namespace_member_declaration*s of that compilation unit, but have no effect on other compilation units. +The *global_using_directive*s of a compilation unit affect the *global_attributes* and *namespace_member_declaration*s of all compilation units in the program. + The *global_attributes* ([§23.3](attributes.md#233-attribute-specification)) of a compilation unit permit the specification of attributes for the target assembly and module. Assemblies and modules act as physical containers for types. An assembly may consist of several physically separate modules. The *namespace_member_declaration*s of each compilation unit of a program contribute members to a single declaration space called the global namespace. @@ -155,6 +157,8 @@ An error occurs if a program declares an extern alias for which no external defi > The program declares the existence of the extern aliases `X` and `Y`, but the actual definitions of the aliases are external to the program. The identically named `N.B` classes can now be referenced as `X.N.B` and `Y.N.B`, or, using the namespace alias qualifier, `X::N.B` and `Y::N.B`. > *end example* +## §global-using-directives Global using directives + ### §global-using-directives-general General A ***global using directive*** is a using directive ([§14.5](namespaces.md#145-using-directives)) at the top level of a compilation unit.