diff --git a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs index d6a768dce..a379899b2 100644 --- a/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs +++ b/ICSharpCode.Decompiler.Tests/TestCases/Pretty/ExpressionTrees.cs @@ -416,6 +416,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty ToCode(X(), () => "abc"[1] == 'b'); } + public void ConditionalWithNarrowConstant(string s) + { + ToCode(X(), () => (s.Length < 1) ? '\0' : s[0]); + ToCode(X(), () => (s.Length < 1) ? ((byte)0) : ((byte)s[0])); + ToCode(X(), () => (s.Length < 1) ? ((short)0) : ((short)s[0])); + } + public void StringsImplicitCast() { int i = 1; diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs index 8d593935d..96dbe32de 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs @@ -1156,9 +1156,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms return null; if (value.MatchBox(out var arg, out var boxType)) { - if (boxType.Kind == TypeKind.Enum || boxType.IsKnownType(KnownTypeCode.Boolean)) - return () => new ExpressionTreeCast(boxType, ConvertValue(arg, invocation), false); - return () => ConvertValue(arg, invocation); + return () => { + // A constant narrower than its stack type - a bool, a char, an enum, one of + // the small integers - builds as a plain ldc.i4 that infers as int, and + // consumers compare inferred types. The cast keeps the type the tree + // declared for it. + var constantValue = ConvertValue(arg, invocation); + if (!NormalizeTypeVisitor.TypeErasure.EquivalentTypes(constantValue.InferType(context.TypeSystem), boxType)) + return new ExpressionTreeCast(boxType, constantValue, false); + return constantValue; + }; } return () => ConvertValue(value, invocation);