# C# Language Design Meeting for Apr 25th, 2022

## Agenda

- [`ref readonly` method parameters](#ref-readonly-method-parameters)
- [Inconsistencies around accessibility checks for interface implementations](#inconsistencies-around-accessibility-checks-for-interface-implementations)

## Quote of the Day

- "The group you're talking about just raised their hand"

## Discussion

### `ref readonly` method parameters

https://github.com/dotnet/csharplang/issues/6010

In another lowlevel session, we looked at a feature designed to address pain points in the BCL with `in`. For the most part, `in` works quite
well. However, there are a few APIs that have been reluctant to adopt `in` because of two main reasons:

* Passing an rvalue, which `in` allows, is an anti-pattern and should be disallowed for a subset of APIs. This part could be addressed in an
analyzer.
* `in` requires that `in` be specified at the callsite for lvalues, not `ref`. For APIs that would want to move, such as `QueryInterface`, the
source-breaking change of moving to `in` is undesirable, and blocks adoption of the feature. This is not addressable by an analyzer.

We think that we've left ourselves room in the middle between `ref` and `in` for a `ref readonly` feature, where `in` can be thought of as
`ref readonly` plus an additional feature of allowing rvalue parameters.

As part of this, we re-examined the motivation behind `in` allowing rvalues, and behind not allowing `ref` to be used for `in` parameters.
Rvalues were allowed because the similar feature in Midori originally didn't allow rvalues, and that proved painful for devs in that environment.
That environment also had an advantage of being entirely new code: migrating from `ref` to `in` or another keyword as a source-break wasn't nearly
the pain point it is for the BCL and C#, which has 20-year-old code still in use today.

We therefore believe there is space for two changes to ease the migration path:

* Allow `in` and `ref` to both be used at the callsite for `in` parameters. `in` will still be preferred, and a warning will be issued when using
`ref` for such cases, but this will allow a migration path that doesn't completely break consumer code, and the warning can be disabled for
codebases that don't want to update.
* Have a language feature to prevent rvalues being passed where they don't belong. We looked at two possible syntaxes for this: `ref readonly`,
or using an attribute like `LvalueOnly`, effectively making it an analyzer. After some discussion, we prefer it being `ref readonly`: it's a
language feature, not an analyzer, so it should look like one. We will error when an rvalue is passed to a `ref readonly` parameter. Both `ref`
and `in` will be usable at the callsite, but use of `ref` will warn, like it will for `in` parameters.

#### Conclusion

Feature is accepted. The syntax will be `ref readonly`. `ref` will be usable for both `ref readonly` and `in` parameters at the callsite, but a
warning will be issues for such cases. Passing an rvalue to a `ref readonly` parameter is an error.

### Inconsistencies around accessibility checks for interface implementations

https://github.com/dotnet/roslyn/issues/60885

[Previously](../2021/LDM-2021-05-19.md#protected-interface-methods), we relaxed restrictions around non-public interface methods. Unfortunately,
this now leaves us with inconsistencies around internal interface methods: implementations of the interface in another assembly end up implementing
such internal methods implicitly, even when they lack visibility. This is particularly bad for virtual, non-abstract members, where an interface
could be perfectly legal to implement in another assembly, and then adding an internal virtual method could cause that other assembly type to end
up overriding an interface member it did not intend to.

In general, we dislike all of the proposed solutions here. Checking to make sure that methods aren't implicitly implementing interface methods
doesn't solve the issue when the dependent assembly doesn't recompile. Relaxing the restriction for explicit implementations seems to fly in the
face of accessibility in C#. Trying to emulate the exact behavior of class types has a number of holes in it. We think we need to brainstorm more
about what to do here.

#### Conclusion

No action today. We will go back to the drawing board and revisit.
