dotnet / roslyn

The Roslyn .NET compiler provides C# and Visual Basic languages with rich code analysis APIs.
https://docs.microsoft.com/dotnet/csharp/roslyn-sdk/
MIT License
18.97k stars 4.03k forks source link

LangVersion affects binding of lambdas #53761

Open 333fred opened 3 years ago

333fred commented 3 years ago

Roslyn's general philosophy on LangVersion checks is that they shouldn't affect how binding is performed. However, there exists a place that they can affect binding today: when we test to see whether or not a lambda can be converted to a delegate type. Consider this example:

using System;

namespace test
{
    public class Class1
    {
        void M(Action<(int, int)> param) { }
        void M(Action<int> param) { }

        void M1()
        {
            M(param => _ = param == param);
        }
    }
}

With today's compiler, if you compile that sample with LangVersion set to 7.2 or earlier, it succeeds. Compile it with 7.3 or later, and compilation fails because the call to M is considered ambiguous. This happens because using the == operator to compare tuples wasn't added until C# 7.3, so when compiling with 7.2 we create a diagnostic about the language version for M(Action<(int, int)> param). Later, when considering whether the lambda bound to the delegate type successfully, we look through the errors reported to see whether any of them should prevent conversion: this allow list is maintained here. LangVersion is not in the list, so the conversion is considered unsuccessful and M(Action<(int, int)> param) is removed from the candidate list, leaving only one overload.

There's a few paths forward here:

333fred commented 3 years ago

/cc @jaredpar @AlekseyTs @cston

333fred commented 3 years ago

Comment from Aleksey on a short-term suggestion to the allow-list code: