# C# Language Design Meeting for March 23rd, 2022

## Agenda

1. [Open questions in required members](#open-questions-in-required-members)
    1. [Emitting `SetsRequiredMembers` for record copy constructors](#emitting-setsrequiredmembers-for-record-copy-constructors)
    2. [Should `SetsRequiredMembers` suppress errors?](#should-setsrequiredmembers-suppress-errors)
    3. [Unsettable members](#unsettable-members)
    4. [Ref returning properties](#ref-returning-properties)
    5. [Obsolete members](#obsolete-members)

## Quote of the Day

- "We can and do allow users to shoot their feet off. However, lets not give them something capable of doing nothing else"

## Discussion

### Open questions in required members

https://github.com/dotnet/csharplang/issues/3630  
https://github.com/dotnet/csharplang/issues/5945

#### Emitting `SetsRequiredMembers` for record copy constructors

We're not ok with option 1 here: these constructors can be accessed directly by consumers within the record type or any derived type of the record. We also think that option 2
changes too much metadata to be palatable: every existing record would change on recompile. While incorrect compilation order could result in a `SetsRequiredMembers` being missed
from a derived record, we think that this case is sufficiently in the corner that it's not necessary to try and address.

##### Conclusion

Option 3, `SetsRequiredMembers` will be added to record copy constructors when the record or any base type has required members.

#### Should `SetsRequiredMembers` suppress errors?

This is a corner case, as the scenario cannot arise from C# code, but it could potentially occur if another language were to extend a type with required members and either
override (without applying the correct attributes) or hide those members. This would cause the required member list to not be understood by the language, and there is danger in
allowing something we don't understand to proceed. However, in those cases, the external language user did decide to explicitly add the `SetsRequiredMembers` attribute: this is
a signal we can understand without context, so it seems fine to ignore errors around required members if the attribute is found.

##### Conclusion

`SetsRequiredMembers` will suppress the error.

#### Unsettable members

We've previously said constructors that require members must be at least as accessible as the members, to ensure that constructors don't become uncallable. This is just an extension
of that scenario.

##### Conclusion

We will require that required fields cannot be readonly, and that required properties are settable from every constructor (meaning that they have a setter/initer at least as
accessible as every constructor that requires them to be set).

#### Ref returning properties

There's an interesting debate here similar to the placement of `readonly` in comparison to the ref: does `required` here require setting of the ref itself (not possible with
ref properties, might be possible with ref field?), or does it require setting the _value_ pointed at by the ref? If the former, that would suggest `required ref` to be in line
with `readonly` members, and would necessitate a syntax for initializing a ref in an object initializer, which doesn't exist today. If the latter, it would suggest
`ref required`, to be in line with `ref readonly`, but it's unclear if this is a scenario to be concerned with.

##### Conclusion

Given lack of motivation, this is disallowed entirely (on both ref properties and, when added, ref fields). We can revisit in the future if we have motivating use cases.

#### Obsolete members

Finally, we considered `Obsolete` required members. We're not fans of libraries forcing their users into a warning, either by accident (adding `Obsolete` to a member while
forgetting to remove `required`) or intentionally. However, we don't feel this is worth an error: it's technically understandable, we just don't know why someone would intentionally
do it. This category of issue is best served by warnings, so we think that's the appropriate strategy.

##### Conclusion

Option 3, with a warning. Warnings will be suppressed for `Obsolete` constructors and for types that are obsolete.
