Skip to content

Commit acb5d06

Browse files
authored
Merge pull request #504 from dadhi/copilot/check-csharp-output-improvements
Fix C# output: add `_ = ` discard for non-void calls in if/else block bodies
2 parents 0e2bcc3 + 4a54b45 commit acb5d06

2 files changed

Lines changed: 18 additions & 4 deletions

File tree

src/FastExpressionCompiler/FastExpressionCompiler.cs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8235,6 +8235,17 @@ internal static bool IsBlockLikeOrConditional(this ExpressionType nodeType) =>
82358235
nodeType == ExpressionType.Conditional | nodeType == ExpressionType.Coalesce ||
82368236
IsBracedBlockLike(nodeType);
82378237

8238+
// Returns true when a non-void expression used as a statement needs a `_ = ` discard prefix
8239+
// to suppress CS0201 / produce valid, unambiguous C# output.
8240+
[MethodImpl((MethodImplOptions)256)]
8241+
internal static bool NeedsDiscardWhenUsedAsStatement(this Expression expr)
8242+
{
8243+
var nodeType = expr.NodeType;
8244+
return expr.Type != typeof(void)
8245+
&& (nodeType == ExpressionType.Call | nodeType == ExpressionType.Invoke
8246+
| nodeType == ExpressionType.Conditional | nodeType == ExpressionType.Coalesce);
8247+
}
8248+
82388249
[MethodImpl((MethodImplOptions)256)]
82398250
internal static bool IsReturnable(this Expression expr)
82408251
{
@@ -10927,6 +10938,8 @@ private static StringBuilder ToCSharpBlock(this Expression expr, StringBuilder s
1092710938
else
1092810939
{
1092910940
sb.NewLineIndent(lineIndent + indentSpaces);
10941+
if (expr != null && expr.NeedsDiscardWhenUsedAsStatement())
10942+
sb.Append("_ = ");
1093010943
sb = expr?.ToCSharpString(sb, EnclosedIn.ParensByDefault, ref ctx,
1093110944
lineIndent + indentSpaces, stripNamespace, printType, indentSpaces, notRecognizedToCode) ?? sb.Append("null");
1093210945
sb.AppendSemicolonOnce(expr);
@@ -11149,9 +11162,8 @@ private static StringBuilder BlockToCSharpString(this BlockExpression b, StringB
1114911162
{
1115011163
sb.NewLineIndent(lineIndent);
1115111164
var nodeType = expr.NodeType;
11152-
var returningCondOrCoalesce = expr.Type != typeof(void)
11153-
&& nodeType == ExpressionType.Conditional | nodeType == ExpressionType.Coalesce;
11154-
if (returningCondOrCoalesce) // it requires some assignment target to avoid error or warning
11165+
var returningCondOrCoalesceOrCall = expr.NeedsDiscardWhenUsedAsStatement();
11166+
if (returningCondOrCoalesceOrCall)
1115511167
sb.Append("_ = ");
1115611168

1115711169
expr.ToCSharpString(sb, EnclosedIn.Block, ref ctx,
@@ -11160,7 +11172,7 @@ private static StringBuilder BlockToCSharpString(this BlockExpression b, StringB
1116011172
// Preventing the `};` kind of situation and separating the conditional block with empty line
1116111173
if (nodeType.IsBlockLikeOrConditional())
1116211174
{
11163-
sb = returningCondOrCoalesce ? sb.AppendSemicolonOnce() : sb;
11175+
sb = returningCondOrCoalesceOrCall ? sb.AppendSemicolonOnce() : sb;
1116411176
sb.NewLineIndent(lineIndent);
1116511177
}
1116611178
else if (nodeType != ExpressionType.Label & nodeType != ExpressionType.Default)

test/FastExpressionCompiler.IssueTests/Issue252_Bad_code_gen_for_comparison_of_nullable_type_to_null.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,8 @@ public void Equal_in_void_Handler_should_work()
5353
var expr = Lambda<Handler>(callIfNotNull, parameterExpr);
5454

5555
expr.PrintCSharp();
56+
Asserts.Contains("_ = ((int?)null).ToString();", expr.ToCSharpString());
57+
5658
var fs = expr.CompileSys();
5759
fs.PrintIL();
5860

0 commit comments

Comments
 (0)