Add notes for October 26th, 2020
This commit is contained in:
parent
9807f9b2e2
commit
211d49a34f
109
meetings/2020/LDM-2020-10-26.md
Normal file
109
meetings/2020/LDM-2020-10-26.md
Normal file
|
@ -0,0 +1,109 @@
|
|||
# C# Language Design Meeting for October 26st, 2020
|
||||
|
||||
## Agenda
|
||||
|
||||
1. [Pointer types in records](#pointer-types-in-records)
|
||||
2. [Triage](#triage)
|
||||
1. [readonly classes and records](#readonly-classes-and-records)
|
||||
2. [Target typed anonymous type initializers](#target-typed-anonymous-type-initializers)
|
||||
3. [Static local functions in base calls](#static-local-functions-in-base-calls)
|
||||
|
||||
## Quote of the Day
|
||||
|
||||
- "And I specialize in taking facetious questions and answering them literally"
|
||||
|
||||
## Discussion
|
||||
|
||||
### Pointer types in records
|
||||
|
||||
Today, you cannot use pointer types in records, because our lowering will use `EqualityComparer<T>.Default`, and pointer
|
||||
types are not allowed as generic type arguments in general. We could specially recognize pointer types here, and use a
|
||||
different equality when comparing fields of that type. We have a similar issue with anonymous types, where pointers are
|
||||
not permitted for the same reason (and indeed, Roslyn's code for generating the equality implementation is shared between
|
||||
these constructs). We would also need consider every place record types can be used if we enabled this: for example, what
|
||||
would the experience be when attempting to pattern deconstruct on a record type, as pointer types are not allowed in patterns
|
||||
today? It also might not be a good idea to introduce value equality based on pointer types to class types, as this is not
|
||||
well-defined for all pointer types (function pointers, for example). Finally, the runtime has talked several times about
|
||||
enabling pointer types as generic type parameters, and if they were to do so then the rules for this might fall out at that
|
||||
time.
|
||||
|
||||
#### Conclusion
|
||||
|
||||
Triaged to the Backlog. We're not convinced this needs to be something that we enable right now, and may end up being resolved
|
||||
by fallout from other changes.
|
||||
|
||||
### Triage
|
||||
|
||||
#### readonly classes and records
|
||||
|
||||
https://github.com/dotnet/csharplang/issues/3885
|
||||
|
||||
This proposal would allow marking a class type `readonly`, ensuring that all fields and properties on the type must be `readonly`
|
||||
as well. Several familiar questions were immediately raised, namely around the benefit. `readonly` has a very specific benefit
|
||||
for struct types, around allowing the compiler to avoid defensive copies where they would otherwise be necessary. For
|
||||
`readonly` classes, there is no clear similar advantage. We might not even emit such information to metadata, and the main
|
||||
benefit would be for type authors, not for type consumers. There is also some concern about whether this would be confusing to
|
||||
users, particularly if this does not apply to an entire hierarchy. If you depend on a non-Object base type that has mutable,
|
||||
then the benefits of using `readonly` are not as clear, even for a type author. Similarly, if a non-`readonly` type can inherit
|
||||
from a `readonly` type, that means that any guarantees on the current type aren't very strong, as mutation can occur under the
|
||||
hood anyway. `readonly` in C# today always means shallow immutability, so there is an argument to be made that this level of
|
||||
hierarchy-mutability is not too different.
|
||||
We also looked at the question of whether this feature should just be analyzer. There is certainly argument for that: particularly
|
||||
if there is no hierarchy impact, it seems a perfect use case for an analyzer. However, this is a case where we allow the keyword
|
||||
on one set of types, while not allowing it on a different set of types. Further, unlike many such proposals, we already have a
|
||||
C# keyword that is perfect for the scenario.
|
||||
|
||||
##### Conclusion
|
||||
|
||||
Triaged into the Working Set. We'll look at this with low priority, and particularly try to see what the scenarios around
|
||||
hierarchical enforcement look like, as those were more generally palatable to LDT members.
|
||||
|
||||
#### Target typed anonymous type initializers
|
||||
|
||||
https://github.com/dotnet/csharplang/issues/3957
|
||||
|
||||
This is a proposal to address some cognitive dissonance we have with object creation in C#: you can leave off the parens if you
|
||||
have an object initializer, but only if you specify the type. While it does save 2 characters, that is not a primary motivation
|
||||
of this proposal. There are grow-up stories for other areas we could explore in this space as well: we could allow F#-style
|
||||
object expressions, for example, or borrow from Java and allow anonymous types to actually inherit from existing types/interfaces.
|
||||
However, we have a number of concerns about the compat aspects of doing this, where adding a new `object` overload can silently
|
||||
change consumer code to call a different overload and create an anonymous type. In these types of scenarios, it might even be
|
||||
impossible to determine if the user made an error: if they typed a wrong letter in the property name, for example, we might be
|
||||
forced to create an anonymous type silently, instead of erroring on the invalid object initializer.
|
||||
|
||||
We also briefly considered more radical changes to the syntax: for example, could we allow TS/JS-style object creation, with
|
||||
just the brackets? However, this idea was not very well received by the LDM.
|
||||
|
||||
##### Conclusion
|
||||
|
||||
Triaged into the Backlog. While we're open to new proposals in this space that significantly shift the bar (such as around new
|
||||
ways of creating anonymous types that inherit from existing types), we think that this proposal could end up conflicting with
|
||||
any such future proposals and should be considered then.
|
||||
|
||||
#### Static local functions in base calls
|
||||
|
||||
https://github.com/dotnet/csharplang/issues/3980
|
||||
|
||||
This is a proposal that, depending on the exact specification, would either be a breaking change or have complicated lookup rules
|
||||
designed to avoid the breaking change. It also requires some deep thought into how the exact scoping rules would work. Today,
|
||||
locals introduced in the `base` call are visible throughout the constructor, so we would have to retconn the scoping rules to
|
||||
work something like this:
|
||||
|
||||
1. Outermost scope, contains static local functions
|
||||
2. Middle scope, contains the base clause and any variables declared there
|
||||
3. Inner scope, contains the method body locals and regular local functions.
|
||||
|
||||
This also raises the question of whether we should stop here. For example, it might be nice if `const` locals could be used as
|
||||
parameter default values, or if attributes could use names from inside a method body. We've had a few proposals for creating
|
||||
various parts of a "method header" scope (such as https://github.com/dotnet/csharplang/issues/373), we could consider extending
|
||||
that generally to allow this type of thing. Another question would be: why stop at `static` local functions? We could allow
|
||||
regular local functions in the base clause, and leverage definite assignment to continue doing the same things it does today to
|
||||
make sure that things aren't used before assignment. This might work well with a general "method header" scope, instead of the
|
||||
scheme proposed above. Finally, we considered simply allowing the `base` call to be done in the body of the constructor instead,
|
||||
a la Visual Basic. This has some support, and would allow us to avoid the question of a method header scope by simply allowing
|
||||
users to move the base call to where the local function is visible.
|
||||
|
||||
##### Conclusion
|
||||
|
||||
Triaged into the Working Set. We like the idea, and have a few avenues to explore around method header scopes or allowing the
|
||||
base call to be moved.
|
|
@ -40,15 +40,17 @@
|
|||
|
||||
- *Design review*
|
||||
|
||||
## Oct 26, 2020
|
||||
|
||||
- Triage [untriaged championed issues](https://github.com/dotnet/csharplang/issues?q=is%3Aissue+is%3Aopen+label%3A%22Proposal+champion%22+no%3Amilestone)
|
||||
- Triage [Backlog](https://github.com/dotnet/csharplang/issues?q=is%3Aopen+is%3Aissue+milestone%3ABacklog) for issues to promote to the [Working Set](https://github.com/dotnet/csharplang/issues?q=is%3Aopen+is%3Aissue+milestone%3A%22Working+Set%22)
|
||||
|
||||
# C# Language Design Notes for 2020
|
||||
|
||||
Overview of meetings and agendas for 2020
|
||||
|
||||
## Oct 26, 2020
|
||||
|
||||
[C# Language Design Notes for October 26st, 2020](https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-26.md)
|
||||
|
||||
- Pointer types in records
|
||||
- Triage
|
||||
|
||||
## Oct 21, 2020
|
||||
|
||||
[C# Language Design Notes for October 21st, 2020](https://github.com/dotnet/csharplang/blob/master/meetings/2020/LDM-2020-10-21.md)
|
||||
|
|
Loading…
Reference in a new issue