Differences in expression body for lambdas and enums #4085

Closed
daveaglick opened this Issue Jul 23, 2015 · 1 comment

Projects

None yet

4 participants

@daveaglick
Contributor

I'm noticing some differences in expression bodies when using enums. Specifically, the Roslyn compiler appears to add a Convert expression whereas the previous compiler did not. Take the following code:

using System;
using System.Linq.Expressions;

public class Program
{
    public enum TestEnum
    {
        Foo,
        Bar
    }

    public static void Main()
    {
        Expression<Func<TestEnum, bool>> expected = x => TestEnum.Bar == x;
        Console.WriteLine(expected.Body.ToString());
    }
}

The old compiler outputs (1 == Convert(x)). Roslyn outputs (Convert(Bar) == Convert(x)).

I would understand if this is fixing a bug or a premature optimization or something with the old compiler, but the odd thing is that Roslyn itself doesn't seem to have the same hangups about optimizing the enum value when used directly (I.e., not via an Expression). If you put the following into TryRoslyn:

using System;
using System.Linq.Expressions;

public class C {
    public enum TestEnum
    {
        Foo,
        Bar
    }

    public void M() 
    {
        Func<TestEnum, bool> compiled = x => TestEnum.Bar == x;
    }
}

you can see that the relevant part decompiles to return C.TestEnum.Bar == x or the following IL which does not contain any type of conversion for TestEnum.Bar:

IL_0000: ldc.i4.1
IL_0001: ldarg.1
IL_0002: ceq
IL_0004: ret

This might be related to #3292, but it's different enough I figured I'd open a new issue so that it doesn't get lost in the noise. Feel free to close and reference from the other one if it's the same thing.

@VSadov VSadov was assigned by gafter Aug 13, 2015
@gafter gafter added this to the 1.1 milestone Aug 13, 2015
@gafter
Member
gafter commented Aug 13, 2015

@VSadov I think you were looking at this issue?

@VSadov VSadov added a commit to VSadov/roslyn that referenced this issue Aug 15, 2015
@VSadov VSadov Make expression trees involving enum literals to look like produced b…
…y native compiler

Native compiler exposes results of constant folding in the expression trees.
In particular, conversion from an enum literal to an underlying type is fairly consistently folded by the native compiler as it can be observed in the expression trees.

Roslyn, on the other hand, was not very consistent here.
Some cases like explicitly converted literals were folded - Ex:  IntTakingMethod((int)E1.a)
Other cases like implicit conversions to underlying type introduced in the processs of type promotion in binary expressions were not.

This fixes known differences in this behavior.

Fixes #4085
Fixes #3292
5a2d963
@VSadov VSadov added a commit to VSadov/roslyn that referenced this issue Aug 15, 2015
@VSadov VSadov Make expression trees involving enum literals to look like produced b…
…y native compiler

Native compiler exposes results of constant folding in the expression trees.
In particular, conversion from an enum literal to an underlying type is fairly consistently folded by the native compiler as it can be observed in the expression trees.

Roslyn, on the other hand, was not very consistent here.
Some cases like explicitly converted literals were folded - Ex:  IntTakingMethod((int)E1.a)
Other cases like implicit conversions to underlying type introduced in the processs of type promotion in binary expressions were not.

This fixes known differences in this behavior.

Fixes #4085
Fixes #3292
75befe7
@VSadov VSadov closed this in #4574 Aug 15, 2015
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment