Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test plan for static local functions #32069

Closed
47 of 70 tasks
jaredpar opened this issue Dec 31, 2018 · 2 comments
Closed
47 of 70 tasks

Test plan for static local functions #32069

jaredpar opened this issue Dec 31, 2018 · 2 comments
Assignees
Labels
Area-Compilers Test Test failures in roslyn-CI Test-Gap Describes a specific feature or scenario that does not have test coverage
Milestone

Comments

@jaredpar
Copy link
Member

jaredpar commented Dec 31, 2018

Feature

Static Local Functions

This feature allows for the following changes to local functions:

  1. Allow static modifier to be applied to local function declarations. Such a function will not be allowed to capture
    any state from the enclosing functions: locals, parameters or this. Additionally the function is guaranteed to be
    emitted as static in the binary.
  2. Allow locals and parameters in a local function, static or not, to shadow identifiers in the enclosing scope.

Code Examples

Static enforcement

int field;
void M() {
    int x = 42;

    M(x);
    static int M(int p) {
        Console.WriteLine(x);       // Error: Can't capture local
        Console.WriteLine(field);   // Error: Can't capture this
        return p;
    }
}

Shadowing

void G(DiagnosticBag diagnostics) {

    void M(DiagnosticsBag diagnostics) {
        DiagnosticsBag diagnostics;     // Error: can't shadow in same scope
    }
}

Compiler Scenarios

  • Ensure all features tied to the C# 8.0 feature flag
    • Can't shadow
    • Can't annotate a local function with static
  • static local function
    • Can't capture this, local or parameter (function or lambda)
    • Can't call instance methods
    • Can't use instance fields
    • Can access private data from enclosing scope as long as it's static
    • Parsing
      • Fails for static static
      • Fails for <return type> static
    • Definition is emitted as static in the binary static Local Functions are not being emitted as static #38143
    • Can't declare an extension method
    • Semantic API correctly implements the is static check for local functions
  • Shadowing
    • Can't shadow within a scope
    • Can shadow in non-static local functions
    • Test semantic model (LookupSymbols, GetSymbolInfo, GetOperation in particular)
    • Can shadow local, parameter, lambda parameter, local function parameter
    • Can shadow in nested scenarios
    • Can shadow with different type
    • Can shadow in
      • LINQ query from
      • LINQ query group by
      • Pattern expression
      • out variable declaration
      • Type parameter
    • Can't shadow in lambda expressions (not part of this implementation)
    • nameof on identifiers that shadow (variables and type parameter)
      • On shadowed variables
      • On variables in enclosing scope
    • Ensure self referencing initializers that shadow use final identifier
      void M() { 
          int x = 13;
          void G() { 
              int x = (x = 0) + 42;
              Console.WriteLine(x);   // Prints 42
          }
          G();
          Console.WriteLine(x);       // Prints 13
      }
    • IOperation can produce nodes for identifiers that shadow
    • CFG can represent control flow of shadowed identifiers properly
  • Confirm shadowing expectations for static and non-static local functions with LDM
  • Design principal: removing static from a local function in a valid program should not change the meaning of the program
  • Emit as static method with same signature. If the containing method is generic, the method emitted for the local function should be generic, even if the local function does not reference the type parameters. EmittedAsStatic_03
  • Can reference type parameters from enclosing scope. StaticWithTypeParameterReferences
  • Allow shadowing type parameter in containing method with local, parameter, type parameter, range variable in local function. Shadowing a type parameter with a type parameter should be a warning. ShadowNames_TypeParameter
  • Allow shadowing local, parameter, type parameter, range variable in containing method with type parameter in local function.
  • Allow using local function name for local, parameter, type parameter, range variable in same local function: void Local(object Local) { }. ShadowNames_ThisLocalFunction
  • No new diagnostics for existing scenarios
  • Non-static local function inside static local function can capture variables from static local function but not variables outside the static local function StaticWithLocalFunctionVariableReference_01, _02
  • nameof(identifier) should bind to shadowing symbol
  • typeof(T) should bind to type parameter T even if T is shadowed by a variable
  • sizeof(T) should bind to type parameter T even if T is shadowed by a variable
  • _ should bind to _ symbol in outer scope even in static local function. UnderscoreInOuterScope
  • var should bind to var symbol in outer scope even in static local function. VarInOuterScope
  • await should be contextual keyword in the same way regardless of whether local function is static. AwaitWithinAsyncOuterScope_02
  • Test overloading with mix of static and non-static
  • Test IOperation and CFG to ensure IDE does not crash
  • EE: should be easier to allow invoking static local functions than non-static local functions
  • Intellisense should only include one identifier for shadowed symbol
  • Intellisense should only include shadowing local function, not shadowed
  • Invoking a static local function in an expression tree should be an error. ExpressionTreeLocalFunctionUsage_02
  • Emit call rather than callvirt for local functions regardless of whether local function is static. EmitCallInstruction
  • ISymbol.IsStatic should return false for non-static local function (not blocking)

IDE Scenarios

@jaredpar jaredpar added Area-Compilers Test Test failures in roslyn-CI labels Dec 31, 2018
@jaredpar jaredpar added this to the 16.0 milestone Dec 31, 2018
@jaredpar jaredpar self-assigned this Dec 31, 2018
@jcouv
Copy link
Member

jcouv commented Dec 31, 2018

It looks like we're separating out "attributes on local functions". That seems fine.
I don't know if there were other upgrades to local functions that were under consideration (unsafe maybe?)

@jaredpar
Copy link
Member Author

@jcouv

Items we are separating out from the full proposal:

  • attributes on local functions
  • shadowing in lambdas

Note: the unsafe modifier is already allowed.

@jcouv jcouv modified the milestones: 16.0, 16.0.P3 Jan 12, 2019
@jcouv jcouv modified the milestones: 16.0.P3, 16.1, 16.2 Apr 18, 2019
@jcouv jcouv modified the milestones: 16.2, 16.3 Jun 25, 2019
@gafter gafter modified the milestones: 16.3, 16.4 Aug 4, 2019
@jaredpar jaredpar modified the milestones: 16.4, Compiler.Next Sep 9, 2019
@gafter gafter added the Test-Gap Describes a specific feature or scenario that does not have test coverage label Jan 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Compilers Test Test failures in roslyn-CI Test-Gap Describes a specific feature or scenario that does not have test coverage
Projects
None yet
Development

No branches or pull requests

4 participants