meetings/2024/LDM-2024-05-01.md
https://github.com/dotnet/csharplang/pull/8027
Last time, we looked at an adjustment to the rules of dynamic binding that would see the compiler
issue more errors for cases where dynamic operations could be resolved as never possible to work at compile-time. The new proposal suggests that, for assignments, we can statically bind during
compile and issue errors for scenarios where no valid assignment is possible. For example, we'd error for this scenario:
var c2 = new C2();
c2.M(0, 1);
public class C2
{
public void M(dynamic d, object o)
{
this[d] += o; // Would error, += cannot be applied to operands of type Base and object
}
Base this[int x]
{
get => new Base();
set {}
}
}
class Base { }
It was hoped that this narrow restriction, only affecting assignments and not affecting invocations, would be small enough to provide meaningful compile-time errors while avoiding runtime breaks. However, we were able to come up with several counterexamples for this scenario. One such example:
// Succeeds and prints 1
var c2 = new C2();
c2.M(0, 1);
public class C2
{
public void M(dynamic d, object o)
{
this[d] += o; // Succeeds today because `Derived.operator +` is found at runtime by dynamic
}
Base this[int x]
{
get => new Derived();
set {}
}
}
class Base { }
class Derived
{
public static Derived operator+(Derived x, object y)
{
System.Console.Write(1);
return x;
}
}
The proposed rules would break this scenario, because Base has no + operator; at runtime, though, the dynamic binder would see that the return of this[d] is a Derived, and find the operator
it defines. We're also concerned about interactions with IDynamicMetaObjectProvider, as those can also break in similar fashions with this scheme. Given these issues, we don't think that we're
comfortable with even this narrow set of errors. Ultimately, use of dynamic in these scenarios intentionally moves errors from compile-time to runtime, and we don't think that the potential for
breaking existing code is worth the additional validation here. We'll shelve this change for now, and revisit in the future if we have a better idea for how to avoid potential breaks.
Proposal is rejected.