# C# Language Design Meeting for May 1st, 2024

## Agenda

- [Adjust binding rules in the presence of a single candidate](#adjust-binding-rules-in-the-presence-of-a-single-candidate)

## Quote of the Day

- "I'm going to release you all early. I know your parents aren't here to pick you up yet." "So we should all go to the playground and stay there?" ... "Or if we're older we go to the library."

## Discussion

### Adjust binding rules in the presence of a single candidate

https://github.com/dotnet/csharplang/pull/8027

[Last time](LDM-2024-04-24.md#adjust-dynamic-binding-rules-for-a-situation-of-a-single-applicable-candidate), 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:

```cs
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:

```cs
// 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.

#### Conclusion

Proposal is rejected.
