Skip to content

Report an error for dynamic evaluation of &&/|| when left operand is statically typed as an interface#80962

Merged
AlekseyTs merged 14 commits intomainfrom
copilot/fix-dynamic-operator-evaluation
Nov 7, 2025
Merged

Report an error for dynamic evaluation of &&/|| when left operand is statically typed as an interface#80962
AlekseyTs merged 14 commits intomainfrom
copilot/fix-dynamic-operator-evaluation

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 and others added 3 commits October 30, 2025 15:32
Co-authored-by: AlekseyTs <10522107+AlekseyTs@users.noreply.github.com>
Co-authored-by: AlekseyTs <10522107+AlekseyTs@users.noreply.github.com>
Co-authored-by: AlekseyTs <10522107+AlekseyTs@users.noreply.github.com>
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
{
// 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.

Co-authored-by: AlekseyTs <10522107+AlekseyTs@users.noreply.github.com>
Co-authored-by: AlekseyTs <10522107+AlekseyTs@users.noreply.github.com>
@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

Co-authored-by: AlekseyTs <10522107+AlekseyTs@users.noreply.github.com>
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

Co-authored-by: AlekseyTs <10522107+AlekseyTs@users.noreply.github.com>
@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

1 similar comment
@AlekseyTs
Copy link
Contributor

@dotnet/roslyn-compiler Please review

@AlekseyTs
Copy link
Contributor

@dotnet/roslyn-compiler For a second review

Copy link
Member

@RikkiGibson RikkiGibson left a comment

Choose a reason for hiding this comment

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

LGTM, comment is not blocking.

Co-authored-by: Rikki Gibson <rigibson@microsoft.com>
@AlekseyTs AlekseyTs enabled auto-merge (squash) November 7, 2025 21:49
@AlekseyTs AlekseyTs merged commit 2bf680e into main Nov 7, 2025
24 of 25 checks passed
@dotnet-policy-service dotnet-policy-service bot added this to the Next milestone Nov 7, 2025
@CyrusNajmabadi CyrusNajmabadi deleted the copilot/fix-dynamic-operator-evaluation branch December 2, 2025 11:52
@davidwengier davidwengier modified the milestones: Next, 18.3 Jan 6, 2026
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.

5 participants