@@ -2351,47 +2351,82 @@ private void CheckAndPromoteOperand(Type signatures, string opName, ref Expressi
23512351 expr = args [ 0 ] ;
23522352 }
23532353
2354- private static string ? GetOverloadedOperationName ( TokenId tokenId )
2354+ private bool TryGetOverloadedEqualityOperator ( TokenId tokenId , ref Expression left , ref Expression right , ref Expression [ ] args )
23552355 {
2356- switch ( tokenId )
2356+ if ( tokenId is TokenId . DoubleEqual or TokenId . Equal )
23572357 {
2358- case TokenId . DoubleEqual :
2359- case TokenId . Equal :
2360- return "op_Equality" ;
2361-
2362- case TokenId . ExclamationEqual :
2363- return "op_Inequality" ;
2358+ const string method = "op_Equality" ;
2359+ return _methodFinder . ContainsMethod ( left . Type , method , true , null , ref args ) ||
2360+ _methodFinder . ContainsMethod ( right . Type , method , true , null , ref args ) ;
2361+ }
23642362
2365- default :
2366- return null ;
2363+ if ( tokenId is TokenId . ExclamationEqual or TokenId . LessGreater )
2364+ {
2365+ const string method = "op_Inequality" ;
2366+ return _methodFinder . ContainsMethod ( left . Type , method , true , null , ref args ) ||
2367+ _methodFinder . ContainsMethod ( right . Type , method , true , null , ref args ) ;
23672368 }
2369+
2370+ return false ;
23682371 }
23692372
2370- private void CheckAndPromoteOperands ( Type signatures , TokenId opId , string opName , ref Expression left , ref Expression right , int errorPos )
2373+ private bool TryGetOverloadedImplicitOperator ( TokenId tokenId , ref Expression left , ref Expression right )
23712374 {
2372- Expression [ ] args = { left , right } ;
2375+ const string methodName = "op_Implicit" ;
2376+ if ( tokenId is not ( TokenId . Ampersand or TokenId . DoubleAmpersand or TokenId . Bar or TokenId . DoubleBar ) )
2377+ {
2378+ return false ;
2379+ }
2380+
2381+ Expression ? expression = null ;
2382+ var overloadedImplicitOperatorFound = false ;
23732383
2374- // support operator overloading
2375- var nativeOperation = GetOverloadedOperationName ( opId ) ;
2376- bool found = false ;
2384+ // If the left is not a boolean, try to find the "op_Implicit" method on the left which takes the left as parameter and returns a boolean.
2385+ if ( left . Type != typeof ( bool ) )
2386+ {
2387+ var args = new [ ] { left } ;
2388+ if ( _methodFinder . FindMethod ( left . Type , methodName , true , ref expression , ref args , out var methodBase ) > 0 && methodBase is MethodInfo methodInfo && methodInfo . ReturnType == typeof ( bool ) )
2389+ {
2390+ left = Expression . Call ( methodInfo , left ) ;
2391+ overloadedImplicitOperatorFound = true ;
2392+ }
2393+ }
23772394
2378- if ( nativeOperation != null )
2395+ // If the right is not a boolean, try to find the "op_Implicit" method on the right which takes the right as parameter and returns a boolean.
2396+ if ( right . Type != typeof ( bool ) )
23792397 {
2380- // first try left operand's equality operators
2381- found = _methodFinder . ContainsMethod ( left . Type , nativeOperation , true , null , ref args ) ;
2382- if ( ! found )
2398+ var args = new [ ] { right } ;
2399+ if ( _methodFinder . FindMethod ( right . Type , methodName , true , ref expression , ref args , out var methodBase ) > 0 && methodBase is MethodInfo methodInfo && methodInfo . ReturnType == typeof ( bool ) )
23832400 {
2384- found = _methodFinder . ContainsMethod ( right . Type , nativeOperation , true , null , ref args ) ;
2401+ right = Expression . Call ( methodInfo , right ) ;
2402+ overloadedImplicitOperatorFound = true ;
23852403 }
23862404 }
23872405
2388- if ( ! found && ! _methodFinder . ContainsMethod ( signatures , "F" , false , null , ref args ) )
2406+ return overloadedImplicitOperatorFound ;
2407+ }
2408+
2409+ private void CheckAndPromoteOperands ( Type signatures , TokenId opId , string opName , ref Expression left , ref Expression right , int errorPos )
2410+ {
2411+ Expression [ ] args = { left , right } ;
2412+
2413+ // 1. Try to find the Equality/Inequality operator
2414+ // 2. Try to find the method with the given signature
2415+ if ( TryGetOverloadedEqualityOperator ( opId , ref left , ref right , ref args ) || _methodFinder . ContainsMethod ( signatures , "F" , false , null , ref args ) )
2416+ {
2417+ left = args [ 0 ] ;
2418+ right = args [ 1 ] ;
2419+
2420+ return ;
2421+ }
2422+
2423+ // 3. Try to find the Implicit operator
2424+ if ( TryGetOverloadedImplicitOperator ( opId , ref left , ref right ) )
23892425 {
2390- throw IncompatibleOperandsError ( opName , left , right , errorPos ) ;
2426+ return ;
23912427 }
23922428
2393- left = args [ 0 ] ;
2394- right = args [ 1 ] ;
2429+ throw IncompatibleOperandsError ( opName , left , right , errorPos ) ;
23952430 }
23962431
23972432 private static Exception IncompatibleOperandError ( string opName , Expression expr , int errorPos )
0 commit comments