Skip to content

Commit 6ba7d59

Browse files
Fix #3891: don't reduce nesting when there is no else block
ReduceNesting walks an else-if chain to its innermost if and asks ShouldReduceNesting whether to extract the else block, which ExtractElseBlock does by casting the block to Block. A chain with no trailing else reaches this with a bare Nop, yet the heuristic still approved it (its stats count a Nop as one statement), so the cast threw InvalidCastException. Take a Block in ShouldReduceNesting and skip the reduction at the call site when the else is absent. Assisted-by: Claude:claude-opus-4-8:Claude Code
1 parent 9ff3ac9 commit 6ba7d59

1 file changed

Lines changed: 7 additions & 5 deletions

File tree

ICSharpCode.Decompiler/IL/Transforms/ReduceNestingTransform.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,9 @@ private bool ReduceNesting(Block block, IfInstruction ifInst, ILInstruction exit
254254
ifInst = elseIfInst;
255255
}
256256

257-
if (!ShouldReduceNesting(ifInst.FalseInst, maxStatements, maxDepth))
257+
// A chain with no trailing else has no block to reduce: ifInst.FalseInst is a bare Nop.
258+
// Guarding here keeps the else-block cast in ExtractElseBlock safe (#3891).
259+
if (ifInst.FalseInst is not Block falseBlock || !ShouldReduceNesting(falseBlock, maxStatements, maxDepth))
258260
return false;
259261

260262
// extract the else block and insert exit points all the way up the else-if tree
@@ -582,16 +584,16 @@ private void ComputeStats(ILInstruction inst, ref int numStatements, ref int max
582584

583585
/// <summary>
584586
/// Heuristic to determine whether it is worth duplicating exits into the preceeding sibling blocks (then/else-if/case)
585-
/// in order to reduce the nesting of inst by 1
587+
/// in order to reduce the nesting of block by 1
586588
/// </summary>
587-
/// <param name="inst">The instruction heading the nested candidate block</param>
589+
/// <param name="block">The nested candidate block (an else or default block)</param>
588590
/// <param name="maxStatements">The number of statements in the largest sibling block</param>
589591
/// <param name="maxDepth">The relative depth of the most nested statement in the sibling blocks</param>
590592
/// <returns></returns>
591-
private bool ShouldReduceNesting(ILInstruction inst, int maxStatements, int maxDepth)
593+
private bool ShouldReduceNesting(Block block, int maxStatements, int maxDepth)
592594
{
593595
int maxStatements2 = 0, maxDepth2 = 0;
594-
UpdateStats(inst, ref maxStatements2, ref maxDepth2);
596+
UpdateStats(block, ref maxStatements2, ref maxDepth2);
595597
// if the max depth is 2, always reduce nesting (total depth 3 or more)
596598
// if the max depth is 1, reduce nesting if this block is the largest
597599
// otherwise reduce nesting only if this block is twice as large as any other

0 commit comments

Comments
 (0)