Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Nov 16, 2025

Plan: Improve error message for overloaded generic delegate-accepting methods ✅

When overload resolution fails and there's a lambda/anonymous method argument, the compiler now prefers reporting errors about overloads that accept delegates in that position, and also prefers reporting errors about non-lambda arguments when both lambda and non-lambda errors exist.

Implementation Plan:

  • Understand the current behavior
  • Modify error reporting to prefer delegate-accepting overloads
  • Create focused tests for the scenario
  • Build and test changes - all OverloadResolutionTests pass (231 tests)
  • Run broader test suite - LambdaTests (319 tests) pass
  • Added edge case tests
  • Extended fix to also handle issue Wrong error message for Task.Run with invalid argument #10672
  • Updated test expectations in DelegateTypeTests and SemanticErrorTests
  • All tests passing (819 DelegateTypeTests + 784 SemanticErrorTests)

Changes Made:

OverloadResolutionResult.cs:

  1. Modified HadBadArguments to detect when a lambda is converting to a non-delegate type
  2. Check for type inference failures on delegate-accepting overloads and report those instead
  3. Updated GetFirstMemberKind to prefer delegate-accepting candidates when lambda arguments are present
  4. Modified HadLambdaConversionError to check if there are bad arguments in non-lambda positions
  5. If lambda errors exist but there are also bad non-lambda arguments and a delegate-accepting overload, report the non-lambda argument errors instead
  6. Added HasDelegateParameterForLambdaArgument helper method
  7. Added HasLambdaArgumentConvertingToNonDelegate helper method
  8. Added HasBadArgumentsInNonLambdaPositions helper method

Test Updates:

  • Updated DelegateTypeTests.OverloadResolution_33, OverloadResolution_35, OverloadResolution_36, OverloadResolution_38
  • Updated SemanticErrorTests.CS1061ERR_NoSuchMemberOrExtension05
  • These updates reflect the improved error messages that now correctly point to delegate-accepting overloads

Issues Fixed:

Issue #21950:

M(x => { });
static void M(string s) { }
static void M<T>(Action<T> a) { }

// ❌ Before: CS1660: Cannot convert lambda expression to type 'string'
// ✅ After: CS0411: The type arguments for method 'Program.M<T>(Action<T>)' cannot be inferred

Issue #10672:

Task.Run(() => { }, TaskCreationOptions.LongRunning);

// ❌ Before: CS1643: Not all code paths return a value in lambda expression of type 'Func<Task>'
// ✅ After: CS1503: Argument 2: cannot convert from 'TaskCreationOptions' to 'CancellationToken'

Additional improvements (reflected in updated tests):

  • When multiple generic overloads exist, now reports errors about ones that accept delegates
  • For LINQ methods like Select, now prefers Enumerable.Select (takes Func) over Queryable.Select (takes Expression<Func>)

All test failures were appropriate - they reflected the improved error reporting behavior.

Original prompt

This section details on the original issue you should resolve

<issue_title>Confusing error message for overloaded generic delegate-accepting method</issue_title>
<issue_description>I have the following code:

using System;

class Program
{
    static void Main()
    {
        M(x => { });
    }

    static void M(string s)
    {
    }

    static void M<T>(Action<T> a)
    {
    }
}

It produces the following error:

CS1660 Cannot convert lambda expression to type 'string' because it is not a delegate type

I think that a human can clearly see that the code is attempting to call the delegate-accepting overload, but is missing a type argument (M<int>(x => { });) or explicit parameter type (M((int x) => { });).

But the compiler shows error message that's related to the first (string-accepting) overload, which I think is confusing.
</issue_description>

<agent_instructions>@copilot see if this is easy to make better. specifically, in an overload resolution error case, when determining the best overload to report, if there is a lambda/anonymous-method, prefer one of the overloads that takes a delegate in that position/named-arg-location.</agent_instructions>

Comments on the Issue (you are @copilot in this section)


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

@CyrusNajmabadi
Copy link
Member

@copilot ensure that this makes the case in #10672 better as well.

Copilot AI changed the title [WIP] Improve error message for overloaded generic delegate-accepting method Prefer delegate-accepting overload in error messages when lambda argument is present Nov 16, 2025
Copilot AI requested a review from CyrusNajmabadi November 16, 2025 15:10
Copilot finished work on behalf of CyrusNajmabadi November 16, 2025 15:10
…errors over lambda conversion errors

Co-authored-by: CyrusNajmabadi <[email protected]>
Copy link
Contributor Author

Copilot AI commented Nov 16, 2025

@copilot ensure that this makes the case in #10672 better as well.

Done! The fix now also improves issue #10672.

For the scenario Task.Run(() => { }, TaskCreationOptions.LongRunning), the error changed from:

  • Before: CS1643: Not all code paths return a value in lambda expression of type 'Func'
  • After: CS1503: Argument 2: cannot convert from 'TaskCreationOptions' to 'CancellationToken'

The fix detects when lambda conversion errors exist alongside bad arguments in non-lambda positions, and when a delegate-accepting overload is available, it reports the non-lambda argument errors instead.

Added test case Issue10672_TaskRunWithInvalidArgument to validate this behavior. Commit: d1952a0

@CyrusNajmabadi
Copy link
Member

@copilot tests fail in "DelegateTypeTests" and "SemanticErrorTests". See if these failures are appropriate and the tests should be updated. Or if this has revealed a problem with this approach.

…ests and SemanticErrorTests

Co-authored-by: CyrusNajmabadi <[email protected]>
Copy link
Contributor Author

Copilot AI commented Nov 16, 2025

@copilot tests fail in "DelegateTypeTests" and "SemanticErrorTests". See if these failures are appropriate and the tests should be updated. Or if this has revealed a problem with this approach.

The test failures were appropriate - they reflect the improved error reporting behavior. Updated the test expectations in both test suites:

DelegateTypeTests (4 tests):

  • OverloadResolution_33, OverloadResolution_35, OverloadResolution_36, OverloadResolution_38
  • Now correctly report type inference errors (CS0411) for generic overloads that accept delegates, instead of "cannot convert lambda to Delegate" errors (CS1660)

SemanticErrorTests (1 test):

  • CS1061ERR_NoSuchMemberOrExtension05
  • Now prefers Enumerable.Select (takes Func<T>) over Queryable.Select (takes Expression<Func<T>>), since Func is a direct delegate type

All 819 DelegateTypeTests and 784 SemanticErrorTests now pass. These changes align with the fix's intent: prefer delegate-accepting overloads when reporting errors for lambda arguments.

Commit: 35b5f35c

Copilot finished work on behalf of CyrusNajmabadi November 16, 2025 19:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Confusing error message for overloaded generic delegate-accepting method

2 participants