Bool-to-int conditional is inlined into every use instead of kept in its local
Author: siegfriedpammerCreated Sep 13, 2026Updated Sep 14, 2026
LabelsDecompilerC#
Input code
public static byte ShiftTwice(byte frequency, bool scale)
{
int n = (scale ? 1 : 0);
return (byte)(frequency + n >> n);
}Compiled with Roslyn, -o+, net8.0.
Erroneous output
Current master (dbf23c6e4) keeps the local:
public static byte ShiftTwice(byte frequency, bool scale)
{
int num = (scale ? 1 : 0);
return (byte)(frequency + num >> num);
}With #4091 (6fcb387ff) the local is dropped and the conditional is printed once per use, plus an
(int) cast on the other operand:
public static byte ShiftTwice(byte frequency, bool scale)
{
return (byte)((int)frequency + (scale ? 1 : 0) >> (scale ? 1 : 0));
}The output is still correct, it just repeats a subexpression the original code had factored out. A loop bound shows the same effect:
// input
int lo = (skipFirst ? 1 : 0);
int i = rules.Length - 1;
while (i >= lo && rules[i] == null)
i--;
// with #4091
int num = rules.Length - 1;
while (num >= (skipFirst ? 1 : 0) && rules[num] == null)
num--;Real-world instances found by diffing #4091 against its merge base over the top-200 nuget.org
packages: SharpCompress.Compressors.PPMd.I1.Model.Refresh (prints (scale ? 1 : 0) three times
in one method) and Humanizer.Vocabulary.
Details
- Product in use: ICSharpCode.Decompiler, built from source
- Version in use: not reproducible on master (dbf23c6e4); introduced somewhere in #4091, measured at 6fcb387ff against merge base 712ad1aed
Filed by an AI agent (Claude) on Siegfried's behalf.
Source: icsharpcode/ILSpy