Added LDM notes for January 27th, 2020
This commit is contained in:
parent
2328664170
commit
1741c519d2
117
meetings/2021/LDM-2021-01-27.md
Normal file
117
meetings/2021/LDM-2021-01-27.md
Normal file
|
@ -0,0 +1,117 @@
|
|||
# C# Language Design Meeting for Jan. 27th, 2021
|
||||
|
||||
## Agenda
|
||||
|
||||
1. [Init-only access on conversion on `this`](#init-only-access-on-conversion-on-this)
|
||||
2. [Record structs](#record-structs)
|
||||
1. [Copy constructors and Clone methods](#copy-constructors-and-clone)
|
||||
2. [`PrintMembers`](#printmembers)
|
||||
3. [Implemented equality algorithms](#implemented-equality-algorithms)
|
||||
4. [Field initializers](#field-initializers)
|
||||
5. [GetHashcode determinism](#gethashcode-determinism)
|
||||
|
||||
## Quote of the Day
|
||||
|
||||
- "You don't see the gazillion tabs I have in my other window... It's actually mostly stackoverflow posts on how to use System.IO.Pipelines."
|
||||
|
||||
## Discussion
|
||||
|
||||
### Init-only access on conversion on `this`
|
||||
|
||||
https://github.com/dotnet/roslyn/issues/50053
|
||||
|
||||
We have 3 options on this issue, centered around how whether we want to make a change and, if so, how far do we want to take it.
|
||||
|
||||
1. Change nothing. The scenario remains an error.
|
||||
2. Allow unconditional casts.
|
||||
3. Allow `as` casts as well.
|
||||
|
||||
We feel that this case is pretty pathological, and we have trouble coming up with real-world examples of APIs that would need to
|
||||
both hide a public member from a base type and initialize it in the constructor to some value. It would also be odd to allow it
|
||||
in the constructor while not having a form of initializing the property from an object initializer, which is the new thing that
|
||||
`init` enables over `set` methods. If we continue seeing a need to name hidden members, perhaps we can come up with a feature that
|
||||
generally allows that, as opposed to solving one particular case in constructors.
|
||||
|
||||
#### Conclusion
|
||||
|
||||
We'll go with 1. The proposal is rejected.
|
||||
|
||||
### Record structs
|
||||
|
||||
https://github.com/dotnet/csharplang/issues/4334
|
||||
|
||||
#### Copy constructors and Clone methods
|
||||
|
||||
We're revisiting the decision made the last time we talked about record structs. In that meeting, we decided to disallow record
|
||||
structs from defining customized `with` semantics, due to concerns over how such structs would behave in generic contexts when
|
||||
constrained to `where T : struct`. If we do disallow this customization, do we need to disallow methods named Clone as well?
|
||||
And should we also disallow copy constructors? In looking at the questions here, we spitballed some potential ways that we could
|
||||
allow customized copies and still allow record structs to be used in generics constrained to `where T : struct`, potentially by
|
||||
introducing a new interface in the BCL. A `with` on a struct type param would check for an implementation of that interface and
|
||||
call that, rather than blindly emitting a `dup` instruction as our original intention was. We think it's an interesting idea and
|
||||
want to pull it into a complete proposal, so we're holding off on making any decisions about allowed and disallowed members in
|
||||
record structs related to copying for now.
|
||||
|
||||
##### Conclusion
|
||||
|
||||
On hold.
|
||||
|
||||
#### `PrintMembers`
|
||||
|
||||
A question was raised during initial review of the specification for record structs on whether we need to keep `PrintMembers`.
|
||||
Struct types don't have inheritance, so we could theoretically simplify that to just `ToString()` for this case. However, we
|
||||
think that there is value in minimizing the differences between record structs and record classes, so conversion between them
|
||||
is as painless as possible. Since users can provide their own `PrintMembers` method with their own semantics, removing it
|
||||
potentially introduces friction in making such a change.
|
||||
|
||||
##### Conclusion
|
||||
|
||||
Keep `PrintMembers`. The behavior will be the same as in record classes.
|
||||
|
||||
#### Implemented equality algorithms
|
||||
|
||||
During review, a question was raised about our original decision here with respect to generating the actual equality implementation
|
||||
for record structs. Originally, we had decided to not generate a new `Equals(object)` method, and have making a struct a record
|
||||
be solely about adding new surface area for the same functionality. Instead, we'd work with the runtime to make the equality
|
||||
generation better for all struct types. While we still want to pursue this angle as well, after discussion we decided that this
|
||||
would be another friction point between record classes and record structs, and could potentially have negative consequences if
|
||||
we don't have time to ship better runtime equality for structs in .NET 6, as many scenarios would then just need to turn around
|
||||
and implement equality themselves. In the future, if we do get the better runtime-generated equality, that could be added as a
|
||||
feature flag to `System.Runtime.CompilerServices.RuntimeFeature`, and we can inform the generation of equality based on the
|
||||
presence of the flag.
|
||||
|
||||
##### Conclusion
|
||||
|
||||
We will generate equality methods in the same manner as proposed in the record struct specification proposal.
|
||||
|
||||
#### Field initializers
|
||||
|
||||
The question here is whether we can allow field initializers in structs that have a primary constructor with more than zero
|
||||
parameters. The immediate followup to that question, of course, is can we just finally allow parameterless constructors for
|
||||
structs in general, and then field initializers just work for all of them? We're still interested in doing this: the
|
||||
`Activator.CreateInstance` bug was in a version of the framework that is long out of support at this point, and we have universal
|
||||
agreement behind the idea. The last time we talked about the feature we took a look at non-defaultable value types in general,
|
||||
and while there are interesting ideas in there, we don't think we need to block parameterless constructors on it.
|
||||
|
||||
##### Conclusion
|
||||
|
||||
Let's dig up the proposal from when we did parameterless struct constructors last and get it done, then this question becomes
|
||||
moot.
|
||||
|
||||
#### GetHashcode Determinism in `Combine`
|
||||
|
||||
The record class specification, and the record struct specification, states:
|
||||
|
||||
> The synthesized override of `GetHashCode()` returns an `int` result of a deterministic function combining the values of
|
||||
> `System.Collections.Generic.EqualityComparer<TN>.Default.GetHashCode(fieldN)` for each instance field `fieldN` with `TN` being
|
||||
> the type of `fieldN`.
|
||||
|
||||
We're not precise on the semantics of "a deterministic function combining the values" here, and the question is whether we should
|
||||
be more precise about the semantics of that. After discussion, we believe we're fine with the wording. It does not promise
|
||||
determinism across boundaries such as different executions of the same program or running the same program on different versions
|
||||
of the runtime, which are not guarantees we want to make.
|
||||
|
||||
##### Conclusion
|
||||
|
||||
Fine as is.
|
||||
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
## Schedule when convenient
|
||||
|
||||
- IEnumerable and Length patterns - (Fred)
|
||||
|
||||
## Recurring topics
|
||||
|
||||
- *Triage championed features and milestones*
|
||||
|
@ -25,17 +27,22 @@
|
|||
|
||||
- Statics in interfaces
|
||||
|
||||
## Jan 27, 2021
|
||||
|
||||
- init-only access on conversion of `this` (Julien, issue https://github.com/dotnet/roslyn/issues/50053)
|
||||
- record structs (Julien - https://github.com/dotnet/csharplang/issues/4334)
|
||||
- IEnumerable and Length patterns - (Fred)
|
||||
|
||||
|
||||
# C# Language Design Notes for 2021
|
||||
|
||||
Overview of meetings and agendas for 2021
|
||||
|
||||
## Jan 27, 2021
|
||||
|
||||
[C# Language Design Notes for January 27th, 2021](https://github.com/dotnet/csharplang/blob/master/meetings/2021/LDM-2021-01-27.md)
|
||||
|
||||
1. Init-only access on conversion on `this`
|
||||
2. Record structs
|
||||
1. Copy constructors and Clone methods
|
||||
2. `PrintMembers`
|
||||
3. Implemented equality algorithms
|
||||
4. Field initializers
|
||||
5. GetHashcode determinism
|
||||
|
||||
## Jan 13, 2021
|
||||
|
||||
[C# Language Design Notes for January 13th, 2021](https://github.com/dotnet/csharplang/blob/master/meetings/2021/LDM-2021-01-13.md)
|
||||
|
|
Loading…
Reference in a new issue