From 9fe7f497529063a8c6f44ab2ba31538aeba5c09a Mon Sep 17 00:00:00 2001 From: Rex Jaeschke Date: Sat, 22 Jul 2023 18:21:23 -0400 Subject: [PATCH 01/17] Add static local functions --- standard/statements.md | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/standard/statements.md b/standard/statements.md index a8fc58a60..8fbcc0f62 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -505,7 +505,8 @@ local_function_modifier ; ref_local_function_modifier - : unsafe_modifier // unsafe code support + : 'static' + | unsafe_modifier // unsafe code support ; local_function_body @@ -561,9 +562,9 @@ Unless specified otherwise below, the semantics of all grammar elements is the s The *identifier* of a *local_function_declaration* must be unique in its declared block scope, including any enclosing local variable declaration spaces. One consequence of this is that overloaded *local_function_declaration*s are not allowed. -A *local_function_declaration* may include one `async` ([§15.15](classes.md#1515-async-functions)) modifier and one `unsafe` ([§23.1](unsafe-code.md#231-general)) modifier. If the declaration includes the `async` modifier then the return type shall be `void` or a `«TaskType»` type ([§15.15.1](classes.md#15151-general)). The `unsafe` modifier uses the containing lexical scope. The `async` modifier does not use the containing lexical scope. It is a compile-time error for *type_parameter_list* or *formal_parameter_list* to contain *attributes*. +A *local_function_declaration* may include one `async` ([§15.15](classes.md#1515-async-functions)) modifier and one `unsafe` ([§23.1](unsafe-code.md#231-general)) modifier. If the declaration includes the `async` modifier then the return type shall be `void` or a `«TaskType»` type ([§15.15.1](classes.md#15151-general)). The `unsafe` modifier uses the containing lexical scope. The `unsafe` modifier uses the containing lexical scope. The `async` modifier does not use the containing lexical scope. If the declaration includes the `static` modifier, the function is a ***static local function***; otherwise, it is a ***non-static local function***. It is a compile-time error for *type_parameter_list* or *formal_parameter_list* to contain *attributes*. -A local function is declared at block scope, and that function may capture variables from the enclosing scopes. It is a compile-time error if a captured variable is read by the body of the local function but is not definitely assigned before each call to the function. The compiler shall determine which variables are definitely assigned on return ([§9.4.4.33](variables.md#94433-rules-for-variables-in-local-functions)). +A local function is declared at block scope, and that function may capture variables from the enclosing scopes. A non-static local function may capture variables from the enclosing scope while a static local function may not (so it has no access to enclosing locals, parameters, or `this`). It is a compile-time error if a captured variable is read by the body of the non-static local function but is not definitely assigned before each call to the function. The compiler shall determine which variables are definitely assigned on return ([§9.4.4.33](variables.md#94433-rules-for-variables-in-local-functions)). When the type of `this` is a struct type, it is a compile-time error for the body of a local function to access `this`. This is true whether the access is explicit (as in `this.x`) or implicit (as in `x` where `x` is an instance member of the struct). This rule only prohibits such access and does not affect whether member lookup results in a member of the struct. @@ -604,6 +605,19 @@ Local function bodies are always reachable. The endpoint of a local function dec If the type of the argument to a local function is `dynamic`, the function to be called must be resolved at compile time, not runtime. +A static local function + +- May not reference instance members from an implicit or explicit `this` or `base` reference. +- May reference `static` members from the enclosing scope. +- May reference `constant` definitions from the enclosing scope. +- May use `nameof()` to reference locals, parameters, or `this` or `base` from the enclosing scope. +- May capture state from an enclosing static local function, but may not capture state outside the enclosing static local function. The same rules apply to a lambda. +- May not be invoked in an expression tree. + +Overload resolution of a call within a local function is not affected by whether the local function is static. + +Removing the `static` modifier from a local function in a valid program does not change the meaning of the program. + ## 13.7 Expression statements An *expression_statement* evaluates a given expression. The value computed by the expression, if any, is discarded. From 9b5c5356dc358b804f4237feea537afbfe360666 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 20:22:49 +0000 Subject: [PATCH 02/17] Update standard/statements.md Co-authored-by: Bill Wagner --- standard/statements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/statements.md b/standard/statements.md index 8fbcc0f62..8417bb0a1 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -562,7 +562,7 @@ Unless specified otherwise below, the semantics of all grammar elements is the s The *identifier* of a *local_function_declaration* must be unique in its declared block scope, including any enclosing local variable declaration spaces. One consequence of this is that overloaded *local_function_declaration*s are not allowed. -A *local_function_declaration* may include one `async` ([§15.15](classes.md#1515-async-functions)) modifier and one `unsafe` ([§23.1](unsafe-code.md#231-general)) modifier. If the declaration includes the `async` modifier then the return type shall be `void` or a `«TaskType»` type ([§15.15.1](classes.md#15151-general)). The `unsafe` modifier uses the containing lexical scope. The `unsafe` modifier uses the containing lexical scope. The `async` modifier does not use the containing lexical scope. If the declaration includes the `static` modifier, the function is a ***static local function***; otherwise, it is a ***non-static local function***. It is a compile-time error for *type_parameter_list* or *formal_parameter_list* to contain *attributes*. +A *local_function_declaration* may include one `async` ([§15.15](classes.md#1515-async-functions)) modifier and one `unsafe` ([§23.1](unsafe-code.md#231-general)) modifier. If the declaration includes the `async` modifier then the return type shall be `void` or a `«TaskType»` type ([§15.15.1](classes.md#15151-general)). If the declaration includes the `static` modifier, the function is a ***static local function***; otherwise, it is a ***non-static local function***. It is a compile-time error for *type_parameter_list* or *formal_parameter_list* to contain *attributes*. If the local function is declared in an unsafe context (§23.2), the local function may include unsafe code, even if the local function declaration doesn't include the `unsafe` modifier. A local function is declared at block scope, and that function may capture variables from the enclosing scopes. A non-static local function may capture variables from the enclosing scope while a static local function may not (so it has no access to enclosing locals, parameters, or `this`). It is a compile-time error if a captured variable is read by the body of the non-static local function but is not definitely assigned before each call to the function. The compiler shall determine which variables are definitely assigned on return ([§9.4.4.33](variables.md#94433-rules-for-variables-in-local-functions)). From 701a5a250e56cd6c2c8beeb2385b3da2b807c729 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 20:23:11 +0000 Subject: [PATCH 03/17] Update standard/statements.md Co-authored-by: Bill Wagner --- standard/statements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/statements.md b/standard/statements.md index 8417bb0a1..93c07f6b1 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -564,7 +564,7 @@ The *identifier* of a *local_function_declaration* must be unique in its declare A *local_function_declaration* may include one `async` ([§15.15](classes.md#1515-async-functions)) modifier and one `unsafe` ([§23.1](unsafe-code.md#231-general)) modifier. If the declaration includes the `async` modifier then the return type shall be `void` or a `«TaskType»` type ([§15.15.1](classes.md#15151-general)). If the declaration includes the `static` modifier, the function is a ***static local function***; otherwise, it is a ***non-static local function***. It is a compile-time error for *type_parameter_list* or *formal_parameter_list* to contain *attributes*. If the local function is declared in an unsafe context (§23.2), the local function may include unsafe code, even if the local function declaration doesn't include the `unsafe` modifier. -A local function is declared at block scope, and that function may capture variables from the enclosing scopes. A non-static local function may capture variables from the enclosing scope while a static local function may not (so it has no access to enclosing locals, parameters, or `this`). It is a compile-time error if a captured variable is read by the body of the non-static local function but is not definitely assigned before each call to the function. The compiler shall determine which variables are definitely assigned on return ([§9.4.4.33](variables.md#94433-rules-for-variables-in-local-functions)). +A local function is declared at block scope. A non-static local function may capture variables from the enclosing scope while a static local function may not (so it has no access to enclosing locals, parameters, or `this`). It is a compile-time error if a captured variable is read by the body of the non-static local function but is not definitely assigned before each call to the function. The compiler shall determine which variables are definitely assigned on return ([§9.4.4.33](variables.md#94433-rules-for-variables-in-local-functions)). When the type of `this` is a struct type, it is a compile-time error for the body of a local function to access `this`. This is true whether the access is explicit (as in `this.x`) or implicit (as in `x` where `x` is an instance member of the struct). This rule only prohibits such access and does not affect whether member lookup results in a member of the struct. From 2294ea0a91f2c1354ba9c3cd797b757267667fea Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 20:23:33 +0000 Subject: [PATCH 04/17] Update standard/statements.md --- standard/statements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/statements.md b/standard/statements.md index 93c07f6b1..5d3945c0e 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -607,7 +607,7 @@ If the type of the argument to a local function is `dynamic`, the function to be A static local function -- May not reference instance members from an implicit or explicit `this` or `base` reference. +- Shall not reference instance members from an implicit or explicit `this` or `base` reference. - May reference `static` members from the enclosing scope. - May reference `constant` definitions from the enclosing scope. - May use `nameof()` to reference locals, parameters, or `this` or `base` from the enclosing scope. From 8b4e09627c4a549ab2bfa8d355f63e38d7a8571f Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 20:23:49 +0000 Subject: [PATCH 05/17] Update standard/statements.md --- standard/statements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/statements.md b/standard/statements.md index 5d3945c0e..4397679b5 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -609,7 +609,7 @@ A static local function - Shall not reference instance members from an implicit or explicit `this` or `base` reference. - May reference `static` members from the enclosing scope. -- May reference `constant` definitions from the enclosing scope. +- May reference constant definitions from the enclosing scope. - May use `nameof()` to reference locals, parameters, or `this` or `base` from the enclosing scope. - May capture state from an enclosing static local function, but may not capture state outside the enclosing static local function. The same rules apply to a lambda. - May not be invoked in an expression tree. From fbd73c8345a7d15e5029d9407f6ef3fabfcf7bef Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 20:24:57 +0000 Subject: [PATCH 06/17] Update standard/statements.md Co-authored-by: Bill Wagner --- standard/statements.md | 1 - 1 file changed, 1 deletion(-) diff --git a/standard/statements.md b/standard/statements.md index 4397679b5..7cd5ba9a5 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -611,7 +611,6 @@ A static local function - May reference `static` members from the enclosing scope. - May reference constant definitions from the enclosing scope. - May use `nameof()` to reference locals, parameters, or `this` or `base` from the enclosing scope. -- May capture state from an enclosing static local function, but may not capture state outside the enclosing static local function. The same rules apply to a lambda. - May not be invoked in an expression tree. Overload resolution of a call within a local function is not affected by whether the local function is static. From 27270f299c1c43f2a3764d5203db9a3c5f1f1259 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 20:30:55 +0000 Subject: [PATCH 07/17] Update standard/statements.md Co-authored-by: Bill Wagner --- standard/statements.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/standard/statements.md b/standard/statements.md index 7cd5ba9a5..870d72f5b 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -605,6 +605,8 @@ Local function bodies are always reachable. The endpoint of a local function dec If the type of the argument to a local function is `dynamic`, the function to be called must be resolved at compile time, not runtime. +A local function shall not be invoked in an expression tree. + A static local function - Shall not reference instance members from an implicit or explicit `this` or `base` reference. From bd94e94a1b377a36c691a218c22879aaf4174c1d Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 20:31:03 +0000 Subject: [PATCH 08/17] Update standard/statements.md --- standard/statements.md | 1 - 1 file changed, 1 deletion(-) diff --git a/standard/statements.md b/standard/statements.md index 870d72f5b..685f84306 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -613,7 +613,6 @@ A static local function - May reference `static` members from the enclosing scope. - May reference constant definitions from the enclosing scope. - May use `nameof()` to reference locals, parameters, or `this` or `base` from the enclosing scope. -- May not be invoked in an expression tree. Overload resolution of a call within a local function is not affected by whether the local function is static. From 5784a5c232ce69e95bbec663641834d6ca14d4d6 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 20:32:55 +0000 Subject: [PATCH 09/17] Update standard/statements.md --- standard/statements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/statements.md b/standard/statements.md index 685f84306..6694a4e85 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -605,7 +605,7 @@ Local function bodies are always reachable. The endpoint of a local function dec If the type of the argument to a local function is `dynamic`, the function to be called must be resolved at compile time, not runtime. -A local function shall not be invoked in an expression tree. +A local function shall not be used in an expression tree. A static local function From 531b4e18962376d6aab26b0fb2e79665ad9fc493 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 20:45:34 +0000 Subject: [PATCH 10/17] Update standard/statements.md --- standard/statements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/statements.md b/standard/statements.md index 6694a4e85..e5a8552b3 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -564,7 +564,7 @@ The *identifier* of a *local_function_declaration* must be unique in its declare A *local_function_declaration* may include one `async` ([§15.15](classes.md#1515-async-functions)) modifier and one `unsafe` ([§23.1](unsafe-code.md#231-general)) modifier. If the declaration includes the `async` modifier then the return type shall be `void` or a `«TaskType»` type ([§15.15.1](classes.md#15151-general)). If the declaration includes the `static` modifier, the function is a ***static local function***; otherwise, it is a ***non-static local function***. It is a compile-time error for *type_parameter_list* or *formal_parameter_list* to contain *attributes*. If the local function is declared in an unsafe context (§23.2), the local function may include unsafe code, even if the local function declaration doesn't include the `unsafe` modifier. -A local function is declared at block scope. A non-static local function may capture variables from the enclosing scope while a static local function may not (so it has no access to enclosing locals, parameters, or `this`). It is a compile-time error if a captured variable is read by the body of the non-static local function but is not definitely assigned before each call to the function. The compiler shall determine which variables are definitely assigned on return ([§9.4.4.33](variables.md#94433-rules-for-variables-in-local-functions)). +A local function is declared at block scope. A non-static local function may capture variables from the enclosing scope while a static local function shall not (so it has no access to enclosing locals, parameters, non-static local functions, or `this`). It is a compile-time error if a captured variable is read by the body of a non-static local function but is not definitely assigned before each call to the function. The compiler shall determine which variables are definitely assigned on return ([§9.4.4.33](variables.md#94433-rules-for-variables-in-local-functions)). When the type of `this` is a struct type, it is a compile-time error for the body of a local function to access `this`. This is true whether the access is explicit (as in `this.x`) or implicit (as in `x` where `x` is an instance member of the struct). This rule only prohibits such access and does not affect whether member lookup results in a member of the struct. From 6348dc27c96f1df692e5116d16b55135972ccfd9 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 20:45:39 +0000 Subject: [PATCH 11/17] Update standard/statements.md --- standard/statements.md | 1 - 1 file changed, 1 deletion(-) diff --git a/standard/statements.md b/standard/statements.md index e5a8552b3..123196d64 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -611,7 +611,6 @@ A static local function - Shall not reference instance members from an implicit or explicit `this` or `base` reference. - May reference `static` members from the enclosing scope. -- May reference constant definitions from the enclosing scope. - May use `nameof()` to reference locals, parameters, or `this` or `base` from the enclosing scope. Overload resolution of a call within a local function is not affected by whether the local function is static. From 1032cf4e4972806c40a7a5951512831c4f148a5a Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 20:45:43 +0000 Subject: [PATCH 12/17] Update standard/statements.md --- standard/statements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/statements.md b/standard/statements.md index 123196d64..52f9c5a4d 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -611,7 +611,7 @@ A static local function - Shall not reference instance members from an implicit or explicit `this` or `base` reference. - May reference `static` members from the enclosing scope. -- May use `nameof()` to reference locals, parameters, or `this` or `base` from the enclosing scope. +- May use `nameof()` to reference locals, parameters, non-static local functions, `this` or `base` from the enclosing scope. Overload resolution of a call within a local function is not affected by whether the local function is static. From 968f60eb68e9f96d65a9c5617d919953cfa307e6 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 20:45:48 +0000 Subject: [PATCH 13/17] Update standard/statements.md --- standard/statements.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/standard/statements.md b/standard/statements.md index 52f9c5a4d..bdedec52f 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -610,7 +610,7 @@ A local function shall not be used in an expression tree. A static local function - Shall not reference instance members from an implicit or explicit `this` or `base` reference. -- May reference `static` members from the enclosing scope. +- May reference static members, type parameters, constant definitions and static local functions from the enclosing scope. - May use `nameof()` to reference locals, parameters, non-static local functions, `this` or `base` from the enclosing scope. Overload resolution of a call within a local function is not affected by whether the local function is static. From a2d6862cb5d41a5f22e9f11705a765728b0d6106 Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 20:45:52 +0000 Subject: [PATCH 14/17] Update standard/statements.md --- standard/statements.md | 1 + 1 file changed, 1 insertion(+) diff --git a/standard/statements.md b/standard/statements.md index bdedec52f..4a1555e99 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -610,6 +610,7 @@ A local function shall not be used in an expression tree. A static local function - Shall not reference instance members from an implicit or explicit `this` or `base` reference. +- Shall not reference local variables, parameters, or non-static local functions from the enclosing scope. - May reference static members, type parameters, constant definitions and static local functions from the enclosing scope. - May use `nameof()` to reference locals, parameters, non-static local functions, `this` or `base` from the enclosing scope. From 0020b471b8e64067d9d3efb31d19939feadc001b Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 21:00:40 +0000 Subject: [PATCH 15/17] Update standard/statements.md Co-authored-by: Neal Gafter --- standard/statements.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/standard/statements.md b/standard/statements.md index 4a1555e99..d8b0253c3 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -609,10 +609,8 @@ A local function shall not be used in an expression tree. A static local function -- Shall not reference instance members from an implicit or explicit `this` or `base` reference. -- Shall not reference local variables, parameters, or non-static local functions from the enclosing scope. - May reference static members, type parameters, constant definitions and static local functions from the enclosing scope. -- May use `nameof()` to reference locals, parameters, non-static local functions, `this` or `base` from the enclosing scope. +- Shall not reference `this` or `base` nor instance members from an implicit `this` reference, nor local variables, parameters, or non-static local functions from the enclosing scope. However, all these are permitted in a `nameof()` expression. Overload resolution of a call within a local function is not affected by whether the local function is static. From 7d70fd6c9cbc2c445acd569a9205b46275fb9d2b Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 21:10:20 +0000 Subject: [PATCH 16/17] Update standard/statements.md --- standard/statements.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/standard/statements.md b/standard/statements.md index d8b0253c3..832d9a59c 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -614,8 +614,6 @@ A static local function Overload resolution of a call within a local function is not affected by whether the local function is static. -Removing the `static` modifier from a local function in a valid program does not change the meaning of the program. - ## 13.7 Expression statements An *expression_statement* evaluates a given expression. The value computed by the expression, if any, is discarded. From 634b325118b3e9f074ea9b1a1786129c82ed3dce Mon Sep 17 00:00:00 2001 From: Jon Skeet Date: Wed, 27 Mar 2024 21:26:21 +0000 Subject: [PATCH 17/17] Update standard/statements.md --- standard/statements.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/standard/statements.md b/standard/statements.md index 832d9a59c..e9a7b0703 100644 --- a/standard/statements.md +++ b/standard/statements.md @@ -612,8 +612,6 @@ A static local function - May reference static members, type parameters, constant definitions and static local functions from the enclosing scope. - Shall not reference `this` or `base` nor instance members from an implicit `this` reference, nor local variables, parameters, or non-static local functions from the enclosing scope. However, all these are permitted in a `nameof()` expression. -Overload resolution of a call within a local function is not affected by whether the local function is static. - ## 13.7 Expression statements An *expression_statement* evaluates a given expression. The value computed by the expression, if any, is discarded.