This project is read-only.
2

Resolved

Extra semicolon should not have effect on overload resolution

description

Compile and run:
using System;

class C
{
    static void Main()
    {
        Foo(() => { return () => 0; ; });
        Foo(() => { return () => 0; });
    }

    static void Foo(Func<Func<short>> x) { Console.WriteLine(1); }
    static void Foo(Func<Func<int>> x) { Console.WriteLine(2); }
}
ACTUAL: 1 2
EXPECTED: 1 1

comments

dpen2000 wrote Apr 4, 2014 at 6:02 PM

I've looked into this. The reason for the difference is in the second invocation exactly matches the second overload of the Foo function which is defined as having only one statement and that this one statement returns the same type (see http://source.roslyn.codeplex.com/#Microsoft.CodeAnalysis.CSharp/Binder/Semantics/OverloadResolution/OverloadResolution.cs#1639 ).
In the first invocation, the second semi-colon is interpreted as it's own statement so it doesn't get caught by this exact match logic. It would be easy to make this exact case work the same as the second invocation by removing the requirement for there to be only one statement and only go off the first statement being a return but this:
  1. Would result in the above test returning 2, 2, not 1, 1
  2. Would still result in other trivial cases such as Foo(() => { Console.WriteLine("side effect"); return () => 0; }) returning 2 here
I wonder instead if a better solution would be to remove this exact match logic entirely if indeed we want both of these invocations to return in 1 being printed and other trivial cases also doing this?

That said, I'm not convinced that either of these invocations should return 1. Would not the method taking Func<Func<int>> be the best match in both cases because the literal 0 is evaluated as an int, not short? If I have a method overloads that take short or int as a parameter, the int one is chosen.

VSadov wrote Apr 8, 2014 at 7:31 PM

Fixed in changeset e5105b69903b959935573f70d1b771cdc2be29b1