meetings/2024/LDM-2024-06-03.md
Issue: https://github.com/dotnet/roslyn/issues/73643
The issue describes an existing scenario where we started issuing warnings although we didn't use to. The scenario seems mainline: It's in Razor, and it combines the use of dynamic and params, both of which are common in the context. This seems an easy situation to get into.
The warning is about one or more candidates not being able to be understood by the runtime binder, which will therefore ignore them. The warning means that new overloads, in this case params collection overloads, can "poison the pot", even for cases where the runtime binder could have still handled things just fine, only with a possibly different outcome than the compile-time binder.
We do have some existing warnings of the same type, but they were grandfathered in. The problem here is that the combination of a new language feature that the runtime binder can't handle plus new overloads that use that feature cause new warnings in existing code.
This seems like the first of potentially several situations like this going into the future. What should our general philosophy be going forward?
If we are certain that something is not going to work out at runtime, we can give compile-time errors. But is there ever a case where a warning is the right thing for dynamic? After all, use of the feature in and of itself signals a willingness to risk things going awry at runtime.
In the particular case in question, the warning does not serve a useful purpose and is not worth the break in behavior that it causes.
Furthermore, we feel in general that warnings are not useful with dynamic. They are a signal that something might not work, and with dynamic people are already bought in to that outcome. All else equal we should avoid adding such warnings in the future also.
We are fine with compile-time errors when we're certain things don't work out at runtime. We're even fine adding new compile-time errors for existing scenarios that break at runtime, since people are already broken, and getting the error earlier is helpful.
Proposal: https://github.com/dotnet/csharplang/blob/main/proposals/ref-unsafe-in-iterators-async.md
The proposal loosens the restrictions on having ref variables and unsafe blocks in iterators and async methods. The reason for earlier restrictions is that ref variables and unsafe code need their state on the stack, and don't mix well with yield and await which need to squirrel away state in the heap. However, there is no problem with ref and unsafe being used between yields and awaits, as long as the ref or unsafe state does not need to be persisted across them. This is what the proposal allows.
The feature is already implemented - this is a review of the speclet to verify that we remain in agreement with all the decisions.
Some specific points of discussion:
Currently, yield statements are allowed inside lock statements in iterators. This keeps a lock while the iterator is suspended, which is highly dubious, and the proposal calls for a new warning on this pattern of code.
Additionally, there is a new variant of the lock statement (https://github.com/dotnet/csharplang/blob/main/proposals/lock-object.md) specifically for the System.Threading.Lock type. Since this type is a ref struct, such a lock statement constitutes a use of a ref across a yield and is therefore an error.
Up until now, local functions inside unsafe async methods were erroneously allowed to have unsafe behavior, even though the top-level method body was safe due to other rules. The proposal calls for breaking this with an error going forward. Such an error is already issued for unsafe operations inside of lambda expressions - we just missed implementing it for local functions when we added those to the language.
We like this. Each design point seems well argued and balanced. We're provisionally ok with the breaking change on the local functions. We'll keep an eye on fallout and discuss if consequences turn out worse than we're able to anticipate.