@@ -1156,17 +1156,36 @@ private BoundExpression BindConditionalLogicalOperator(BinaryExpressionSyntax no
1156
1156
CheckConstraintLanguageVersionAndRuntimeSupportForOperator ( node , kind == BinaryOperatorKind . LogicalAnd ? falseOperator : trueOperator ,
1157
1157
isUnsignedRightShift : false , signature . ConstrainedToTypeOpt , diagnostics ) ;
1158
1158
1159
+ var operandPlaceholder = new BoundValuePlaceholder ( resultLeft . Syntax , resultLeft . Type ) . MakeCompilerGenerated ( ) ;
1160
+ var trueFalseParameterType = ( resultKind . Operator ( ) == BinaryOperatorKind . And ? falseOperator : trueOperator ) . Parameters [ 0 ] . Type ;
1161
+ CompoundUseSiteInfo < AssemblySymbol > useSiteInfo = GetNewCompoundUseSiteInfo ( diagnostics ) ;
1162
+ var conversion = this . Conversions . ClassifyConversionFromType ( resultLeft . Type , trueFalseParameterType , isChecked : CheckOverflowAtRuntime , ref useSiteInfo ) ;
1163
+ Debug . Assert ( conversion . IsImplicit ) ;
1164
+
1165
+ BoundExpression operandConversion = CreateConversion (
1166
+ resultLeft . Syntax ,
1167
+ operandPlaceholder ,
1168
+ conversion ,
1169
+ isCast : false ,
1170
+ conversionGroupOpt : null ,
1171
+ trueFalseParameterType ,
1172
+ diagnostics ) ;
1173
+
1174
+ diagnostics . Add ( operandConversion . Syntax , useSiteInfo ) ;
1175
+
1159
1176
return new BoundUserDefinedConditionalLogicalOperator (
1160
1177
node ,
1161
1178
resultKind ,
1162
- resultLeft ,
1163
- resultRight ,
1164
1179
signature . Method ,
1165
1180
trueOperator ,
1166
1181
falseOperator ,
1182
+ operandPlaceholder ,
1183
+ operandConversion ,
1167
1184
signature . ConstrainedToTypeOpt ,
1168
1185
lookupResult ,
1169
1186
originalUserDefinedOperators ,
1187
+ resultLeft ,
1188
+ resultRight ,
1170
1189
signature . ReturnType ) ;
1171
1190
}
1172
1191
else
@@ -1234,8 +1253,35 @@ private bool IsValidDynamicCondition(BoundExpression left, bool isNegative, Bind
1234
1253
return false ;
1235
1254
}
1236
1255
1256
+ // Strictly speaking, we probably should be digging through nullable type here to look for an operator
1257
+ // declared by the underlying type. However, it doesn't look like dynamic binder is able to deal with
1258
+ // nullable types while evaluating logical binary operators. Exceptions that it throws look like:
1259
+ //
1260
+ // Microsoft.CSharp.RuntimeBinder.RuntimeBinderException : The type ('S1?') must contain declarations of operator true and operator false
1261
+ // Stack Trace:
1262
+ // at CallSite.Target(Closure, CallSite, Object, Object)
1263
+ // at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
1264
+ //
1265
+ // Microsoft.CSharp.RuntimeBinder.RuntimeBinderException : Operator '&&' cannot be applied to operands of type 'S1' and 'S1?'
1266
+ // Stack Trace:
1267
+ // at CallSite.Target(Closure, CallSite, Object, Nullable`1)
1268
+ // at System.Dynamic.UpdateDelegates.UpdateAndExecute2[T0,T1,TRet](CallSite site, T0 arg0, T1 arg1)
1237
1269
var namedType = type as NamedTypeSymbol ;
1238
1270
var result = HasApplicableBooleanOperator ( namedType , isNegative ? WellKnownMemberNames . FalseOperatorName : WellKnownMemberNames . TrueOperatorName , type , ref useSiteInfo , out userDefinedOperator ) ;
1271
+
1272
+ if ( result )
1273
+ {
1274
+ Debug . Assert ( userDefinedOperator is not null ) ;
1275
+
1276
+ var operandPlaceholder = new BoundValuePlaceholder ( left . Syntax , left . Type ) . MakeCompilerGenerated ( ) ;
1277
+ TypeSymbol parameterType = userDefinedOperator . Parameters [ 0 ] . Type ;
1278
+
1279
+ implicitConversion = this . Conversions . ClassifyConversionFromType ( operandPlaceholder . Type , parameterType , isChecked : CheckOverflowAtRuntime , ref useSiteInfo ) ;
1280
+ Debug . Assert ( implicitConversion . IsImplicit ) ;
1281
+
1282
+ CreateConversion ( left . Syntax , operandPlaceholder , implicitConversion , isCast : false , conversionGroupOpt : null , parameterType , diagnostics ) ;
1283
+ }
1284
+
1239
1285
diagnostics . Add ( left . Syntax , useSiteInfo ) ;
1240
1286
1241
1287
return result ;
0 commit comments