Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Oct 30, 2025

Plan for fixing interface operator with dynamic bug

  • Explore repository structure and build system
  • Understand the issue: compiler doesn't error when interface with true/false operators is used with && or || and dynamic right operand
  • Locate relevant code in Binder_Operators.cs (IsValidDynamicCondition method)
  • Understand the root cause: runtime dynamic binder cannot use operators defined on interfaces
  • Create focused test cases for the bug (2 interface tests, 1 class regression test)
  • Implement fix to detect interface operators and report ERR_InvalidDynamicCondition
  • Run tests to ensure fix works correctly (3 new tests pass)
  • Run existing tests to ensure no regressions (all 263 DynamicTests pass, all 605 operator tests pass)
  • Run semantic test suite to ensure no broader regressions (all 19,421 tests pass)
  • Address code review feedback - move interface check to line 1580
  • Update error message to clarify interface constraint
  • Update all test comments to reflect new error message wording (8 additional test files)
  • Document breaking change in Compiler Breaking Changes - DotNet 11.md
  • Final testing confirms all tests still pass
Original prompt

This section details on the original issue you should resolve

<issue_title>Compiler doesn't report an error for dynamic evaluation of &&/|| when left operand is statically typed as an interface with true/false operator.</issue_title>
<issue_description>```
using System;

public class Program
{
static void Main()
{
I1 x = new C1();
dynamic y = new C1();

    _ = x && y;
}

}

interface I1
{
static bool operator true(I1 x)
{
Console.WriteLine(20);
return false;
}
static bool operator false(I1 x)
{
Console.WriteLine(30);
return false;
}
}

class C1 : I1
{
public static C1 operator &(C1 x, C1 y)
{
Console.WriteLine(1);
return x;
}
public static bool operator true(C1 x)
{
Console.WriteLine(2);
return false;
}

public static bool operator false(C1 x)    
{
    Console.WriteLine(3);
    return false;
}

}


Output:

Exit code: -532462766
Stdout:
30

Stderr:
Unhandled exception. Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: BadBinaryOps
at System.Object.CallSite.Target(Closure , CallSite , I1 , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute2[I1,Object,Object](CallSite site, I1 arg0, Object arg1)
at Program.Main()
at System.Reflection.MethodBaseInvoker.InterpretedInvoke_Method(Object obj, IntPtr* args)
at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr)


Expected an error like in the following scenario:

using System;

public class Program
{
static void Main()
{
C0 x = new C1();
dynamic y = new C1();

    _ = x && y; // error CS7083: Expression must be implicitly convertible to Boolean or its type 'C0' must define operator 'false'.
}

}

class C0;
class C1 : C0
{
public static C1 operator &(C1 x, C1 y)
{
return x;
}
public static bool operator true(C1 x)
{
return false;
}

public static bool operator false(C1 x)    
{
    return false;
}

}


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

<comments>
</comments>


💬 We'd love your input! Share your thoughts on Copilot coding agent in our 2 minute survey.

Copilot AI changed the title [WIP] Fix compiler error for dynamic evaluation of && and || operators Fix: Report error for interface operators with dynamic operands in logical expressions Oct 30, 2025
Copilot AI requested a review from AlekseyTs October 30, 2025 15:53
Copilot finished work on behalf of AlekseyTs October 30, 2025 15:53
{
// Operators defined on interfaces cannot be used with dynamic binding at runtime,
// so we don't consider them as applicable.
if (op.ContainingType.IsInterface)
Copy link
Contributor

@AlekseyTs AlekseyTs Nov 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if (op.ContainingType.IsInterface)

@copilot Please combine interface check with condition in if (type.Kind != SymbolKind.NamedType) on line 1580 instead. #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit 3cf6ed6. The interface check is now combined with the SymbolKind.NamedType check at line 1580, and the redundant check inside hasApplicableBooleanOperator has been removed.

}
}";
CreateCompilation(source, targetFramework: TargetFramework.Net70).VerifyDiagnostics(
// (21,13): error CS7083: Expression must be implicitly convertible to Boolean or its type 'I1' must define operator 'false'.
Copy link
Contributor

@AlekseyTs AlekseyTs Nov 4, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Expression must be implicitly convertible to Boolean or its type 'I1' must define operator 'false'.

@copilot Please adjust corresponding resource string so that wording for this error message would be: "Expression must be implicitly convertible to Boolean or its type 'I1' must not be an interface and must define operator 'false'." #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit ee63d62. The error message now reads: "Expression must be implicitly convertible to Boolean or its type '{0}' must not be an interface and must define operator '{1}'." All test comments have been updated accordingly.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit ee63d62. The error message now reads: "Expression must be implicitly convertible to Boolean or its type '{0}' must not be an interface and must define operator '{1}'." All test comments have been updated accordingly.

@copilot Please adjust the following test comments in a similar way:

src\Compilers\CSharp\Test\Emit3\Semantics\ExtensionOperatorsTests.cs(15848):// (26,13): error CS7083: Expression must be implicitly convertible to Boolean or its type 'object' must define operator 'false'.
src\Compilers\CSharp\Test\IOperation\IOperation\IOperationTests_IBinaryOperatorExpression.cs(6353):// file.cs(6,18): error CS7083: Expression must be implicitly convertible to Boolean or its type 'C' must define operator 'false'.
src\Compilers\CSharp\Test\IOperation\IOperation\IOperationTests_IBinaryOperatorExpression.cs(6865):// file.cs(6,18): error CS7083: Expression must be implicitly convertible to Boolean or its type 'C?' must define operator 'false'.
src\Compilers\CSharp\Test\IOperation\IOperation\IOperationTests_IBinaryOperatorExpression.cs(7586):// file.cs(6,18): error CS7083: Expression must be implicitly convertible to Boolean or its type 'C?' must define operator 'false'.
src\Compilers\CSharp\Test\IOperation\IOperation\IOperationTests_IBinaryOperatorExpression.cs(7695):// file.cs(6,18): error CS7083: Expression must be implicitly convertible to Boolean or its type 'C?' must define operator 'false'.
src\Compilers\CSharp\Test\IOperation\IOperation\IOperationTests_IBinaryOperatorExpression.cs(8017):// file.cs(6,18): error CS7083: Expression must be implicitly convertible to Boolean or its type 'bool?' must define operator 'false'.
src\Compilers\CSharp\Test\Semantic\Semantics\OperatorTests.cs(9274):// (27,37): error CS7083: Expression must be implicitly convertible to Boolean or its type 'S1?' must define operator 'false'.
src\Compilers\CSharp\Test\Semantic\Semantics\OperatorTests.cs(9319):// (27,37): error CS7083: Expression must be implicitly convertible to Boolean or its type 'S1?' must define operator 'false'.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit 92e9427. Updated all 8 test comment occurrences across 3 files (ExtensionOperatorsTests.cs, IOperationTests_IBinaryOperatorExpression.cs, and OperatorTests.cs) to include "must not be an interface and" in the error message.

Copilot AI requested a review from AlekseyTs November 4, 2025 18:16
Copilot finished work on behalf of AlekseyTs November 4, 2025 18:16
Copilot finished work on behalf of AlekseyTs November 4, 2025 18:26
@AlekseyTs
Copy link
Contributor

@copilot Please document the breaking change at the end of "roslyn\docs\compilers\CSharp\Compiler Breaking Changes - DotNet 11.md" file

Copy link
Contributor Author

Copilot AI commented Nov 4, 2025

@copilot Please document the breaking change at the end of "roslyn\docs\compilers\CSharp\Compiler Breaking Changes - DotNet 11.md" file

Done in commit fb27b79. The breaking change has been documented at the end of "Compiler Breaking Changes - DotNet 11.md" with a description of the issue, example code showing the error, a workaround, and a link to the GitHub issue. #Closed

Copilot finished work on behalf of AlekseyTs November 4, 2025 19:09
Copilot finished work on behalf of AlekseyTs November 4, 2025 20:34
@AlekseyTs AlekseyTs changed the title Fix: Report error for interface operators with dynamic operands in logical expressions Report an error for dynamic evaluation of &&/|| when left operand is statically typed as an interface Nov 4, 2025
@AlekseyTs AlekseyTs marked this pull request as ready for review November 5, 2025 00:53
@AlekseyTs AlekseyTs requested a review from a team as a code owner November 5, 2025 00:53
@AlekseyTs
Copy link
Contributor

@dotnet/roslyn-compiler Please review.

@AlekseyTs
Copy link
Contributor

@dotnet/roslyn-compiler Please review

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compiler doesn't report an error for dynamic evaluation of &&/|| when left operand is statically typed as an interface with true/false operator.

2 participants