Skip to content

[BUG]: Usage of a conditional return label results in an unexpected null value #123

@victorr99

Description

@victorr99

Current Behavior

Running an expression which uses the BlockAsync and Await methods, in combination with an IfThen and Return(...) lets the expression return an unexpected null value.

Expected Behavior

The actual value which should be returned in the IfThen expression is being returned.

Steps To Reproduce

The example below shows the usage of a conditional return. At no place we return a null value, although a null value is returned when the IfThen branch is being taken.

var expected = new object();
var variable = Variable(typeof(object));
var label = Label(typeof(object), "return");

var lambda =
    Lambda<Func<Task<object>>>(
        BlockAsync(
            [variable],
            Assign(
                variable,
                Await(
                    Constant(Task.FromResult(expected)))),
            IfThen(
                NotEqual(
                    variable,
                    Constant(null, typeof(object))),
                Return(
                    label,
                    variable,
                    typeof(object))),
            Return(
                label,
                Constant(
                    new object(),
                    typeof(object)),
                typeof(object)),
            Label(
                label,
                Constant(
                    new object(),
                    typeof(object)))
        ));

var method = lambda.Compile();
var result = await method();

Assert.Same(expected, result); // == false, but true was expected here.

Anything else?

When I modify the expression tree to a non-async variant, I do get the result I'm expecting.
You may verify this with the example below:

var expected = new object();
var variable = Variable(typeof(object));
var label = Label(typeof(object), "return");

var lambda =
    Lambda<Func<object>>(
        Block(
            [variable],
            Assign(
                variable,
                Constant(expected)),
            IfThen(
                NotEqual(
                    variable,
                    Constant(null, typeof(object))),
                Return(
                    label,
                    variable,
                    typeof(object))),
            Return(
                label,
                Constant(
                    new object(),
                    typeof(object)),
                typeof(object)),
            Label(
                label,
                Constant(
                    new object(),
                    typeof(object)))
        ));

var method = lambda.Compile();
var result = method();

Assert.Same(expected, result); // == true in this case

It seems that SetResult on the AsyncStateMachine isn't being called (or not properly).

I'm aware that I can use an IfThenElse to prevent the need of return labels. Our use case however requires a lot of early bail outs which will grow exponentially. Nesting the IfThenElse would result in deep nested IfThenElse expressions (a depth of 30+ isn't uncommon in our case).

Thanks in advance!

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions