Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Natural delegate type depends on order of candidates #71333

Closed
AlekseyTs opened this issue Dec 19, 2023 · 5 comments · Fixed by #71380
Closed

Natural delegate type depends on order of candidates #71333

AlekseyTs opened this issue Dec 19, 2023 · 5 comments · Fixed by #71380

Comments

@AlekseyTs
Copy link
Contributor

AlekseyTs commented Dec 19, 2023

class Program
{
    static void Main()
    {
        var x1 = new Program().Test1;
        var x2 = new Program().Test2;

        x1(); // error CS7036: There is no argument given that corresponds to the required parameter 'obj' of 'Action<long[]>'
        x2();
    }
}

static class Params
{
    static public void Test1(this Program p, long[] a) { System.Console.WriteLine(a.Length); }
    static public void Test1(this object p, params long[] a) { System.Console.WriteLine(a.Length); }

    static public void Test2(this object p, params long[] a) { System.Console.WriteLine(a.Length); }
    static public void Test2(this Program p, long[] a) { System.Console.WriteLine(a.Length); }
}

Observed:
Type inferred for x1 is Action<long[]>, type inferred for x2 is void <anonymous delegate>(params long[] a)

Expected:
The same type is inferred, they differ only by order of candidates.

@dotnet-issue-labeler dotnet-issue-labeler bot added Area-Compilers untriaged Issues and PRs which have not yet been triaged by a lead labels Dec 19, 2023
@AlekseyTs
Copy link
Contributor Author

CC @cston

@AlekseyTs
Copy link
Contributor Author

CC @jjonescz

@AlekseyTs
Copy link
Contributor Author

AlekseyTs commented Dec 19, 2023

It looks like the behavior was introduced in #64861. There could be a similar issue around optional parameters as well. Basically any aspect that is not considered as a difference by MemberSignatureComparer.MethodGroupSignatureComparer is a suspect.

@jjonescz
Copy link
Member

I think the expected behavior here are errors:

var x1 = new Program().Test1; // error CS8917: The delegate type could not be inferred.
var x2 = new Program().Test2; // error CS8917: The delegate type could not be inferred.

This is what also happens with ref instead of params, for example. And it matches the speclets:

  1. lambda improvements:

    A method group has a natural type if all candidate methods in the method group have a common signature. (If the method group may include extension methods, the candidates include the containing type and all extension method scopes.)

  2. params/defaults for lambdas:

    The natural type of an anonymous function expression or method group is a function_type. A function_type represents a method signature: the parameter types, default values, ref kinds, params modifiers, and return type and ref kind. Anonymous function expressions or method groups with the same signature have the same function_type.

I.e., the candidate methods differ in signature, hence the method group has no natural type and CS8917 should be reported.

@AlekseyTs
Copy link
Contributor Author

@jjonescz
I think params modifier and default values are not part of the signature from the language point of view. One cannot overload on them. In my opinion, the fact that function_type mentions them doesn't automatically make them part of the signature for the purpose of the "if all candidate methods in the method group have a common signature" part. I think what you are proposing to do is a viable option, but, judging by the quotes above, that would require a spec change for the feature.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants