csharplang/meetings/2022/LDM-2022-10-12.md

3.0 KiB

C# Language Design Meeting for October 12th, 2022

Agenda

Quote of the Day

  • "You're muted" "Damn, I said it so well!"

Discussion

Keywordness of field

https://github.com/dotnet/csharplang/issues/140
https://github.com/dotnet/csharplang/issues/6530

Today, we considered compiler implementation issues for semi-auto properties. The compiler has run into a few circularity issues during implementation which are proving tricky to work out, and we wanted to revisit the decisions in LDM to see if there was an acceptable, easier option for implementation. After some initial discussion to understand the particular issue found here and brainstorm other approaches to the problem, we came up with the following list of solutions:

  1. Make field a keyword 1b. Use a different keyword. Maybe something with two components to reduce chance of conflicts.
  2. Ignore scopes for determining if there's a field. 2b. Could we do a cheap bind of scopes and see if there's a field reference without a visible declaration?
  3. Add an introducer modifier
  4. Do more work in the compiler to implement the existing rules.
  5. Make an assumption when we're about to go into a cycle, and error if the assumption is broken later

We think 1 and 3 are too big of reimaginings for the feature as of right now: previous LDM work came to the current keyword and feature shape after a lot of investigation, and we don't think that changing them up is warranted at this point, given that we don't think the engineering challenges are insurmountable. We also think option 5 will have unpredictable results: what assumptions the compiler makes may end up feeling like implementation details that leak into the specification. This leaves us with options 2 and 4.

Further delving into option 2, we realized that it has many of the same problems as just keeping the original specification as is. All of the following scenarios should work with option 2, but will still require the same engineering effort as 4:

class C
{
    int Prop
    {
        get
        {
            var x = (field: 1, 2); // Tuple element named field, not a use of the field keyword
            var y = new { field = 1 }; // Anonymous type property named field
            var x = new Foo() { field = 1 }; // Regular type member named field
            if (x is { field: 1 }) {} // Regular type member named field
            return 1; // No usage of the field keyword, so a backing field should not be generated
        }
    }
}

This realization showed us that what we really need to do is to do the work in the compiler to determine if a field keyword is in an expression context, in a purely syntactic fashion. This will require some effort, but unless the effort comes back as being extremely challenging (forcing us to look at options 1 or 3), we'll proceed with option 4.

Conclusion

We will continue pursuing the current work, and revisit if it proves to have a significant cost.