diff --git a/src/ILInspector.Decompiler.Tests/IrImporterTests.cs b/src/ILInspector.Decompiler.Tests/IrImporterTests.cs index 22b8f7af..b3071d9d 100644 --- a/src/ILInspector.Decompiler.Tests/IrImporterTests.cs +++ b/src/ILInspector.Decompiler.Tests/IrImporterTests.cs @@ -1581,6 +1581,20 @@ public void BooleanFolding_TernarySource_PerConfigShape() #endif } + [Fact] + public void BooleanFolding_GuardReturn_BothConstantArms_CollapseToCondition() + { + // if (a > 0) { if (b > 0) return true; } return false; folds the nested + // guards to one condition, then the dual-constant return to the bare + // condition — not a dead `a > 0 && b > 0 && true` (the true arm is the + // result, not an extra && term). + using var source = MetadataSource.Open(typeof(CfgSampleClass).Assembly.Location); + string output = PrintWithPasses( + typeof(CfgSampleClass).FullName!, nameof(CfgSampleClass.BothPositive), source); + + Assert.Equal("return a > 0 && b > 0;", output); + } + [Fact] public void Structuring_NestedGuards_NestAndDropGotos() { diff --git a/src/ILInspector.Decompiler/Pipeline/Passes/BooleanFoldingPass.cs b/src/ILInspector.Decompiler/Pipeline/Passes/BooleanFoldingPass.cs index cb7deeb1..4375f4d4 100644 --- a/src/ILInspector.Decompiler/Pipeline/Passes/BooleanFoldingPass.cs +++ b/src/ILInspector.Decompiler/Pipeline/Passes/BooleanFoldingPass.cs @@ -228,7 +228,15 @@ static bool FoldGuardReturn(IfStatement guard) var condition = guard.Condition; condition.Detach(); IrExpression folded; - if (tailConstant is { } tailBool) + if (thenConstant is { } thenBool && tailConstant is { } tailBool2 && thenBool != tailBool2) + { + // Both arms are opposite bool constants, so the condition itself is + // the result: if (c) return true; return false; ≡ return c; and the + // dual ≡ return !c;. The generic fold below would append the literal + // arm as a dead `c && true` / `!c || false`. + folded = thenBool ? condition : Conditions.Negate(condition); + } + else if (tailConstant is { } tailBool) { thenValue.Detach(); // if (c) return A; return true; ≡ return !c || A;