Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Invalid assignment to returned value #882

Closed
mmusu3 opened this Issue Sep 29, 2017 · 5 comments

Comments

Projects
None yet
3 participants
@mmusu3
Copy link

mmusu3 commented Sep 29, 2017

The output from decompiling this code cannot be recompiled due to referencing the unassigned local variable item.

class Item
{
    public Item Self;
}

static void Test()
{
    var item = GetItem(null);
    item.Self = item;
}

static Item GetItem(object obj) => null;

Produces:

private class Item
{
    public Item Self;
}

private static void Test()
{
    object obj = ((Item)obj).Self = GetItem(null);
}

private static Item GetItem(object obj)
{
    return null;
}

@siegfriedpammer siegfriedpammer added this to the 3.0 milestone Sep 29, 2017

@siegfriedpammer

This comment has been minimized.

Copy link
Member

siegfriedpammer commented Sep 29, 2017

Thanks for reporting this! I think we need more test cases in this area. If you could provide some, this would be very nice.

@mmusu3

This comment has been minimized.

Copy link
Author

mmusu3 commented Sep 29, 2017

I think this is the first I've seen but if I come across any more I'll be sure to report them.

@mmusu3

This comment has been minimized.

Copy link
Author

mmusu3 commented Jan 8, 2019

I have another test case for this issue. Tested at commit 17d19cd

Source:

struct Data
{
    public bool Condition { get; set; }
}

static Data GetData()
{
    throw new NotImplementedException();
}

static void Test()
{
    Data data = GetData();
    data.Condition = false;
}

Output:

struct Data
{
    public bool Condition
    {
        get;
        set;
    }
}

static Data GetData()
{
    throw new NotImplementedException();
}

static void Test()
{
    GetData().Condition = false;
}

@mmusu3 mmusu3 changed the title Invalid assignment code after decompiling Invalid assignment to returned value Jan 8, 2019

@dgrunwald

This comment has been minimized.

Copy link
Member

dgrunwald commented Jan 8, 2019

I don't see a problem there. The semantics of Data data = GetData(); data.Condition = false; and GetData().Condition = false; are identical if the data variable is not used elsewhere.
The C# compiler tends to optimize out such local variables in release builds, so we can't tell what the original code looked like.

@mmusu3

This comment has been minimized.

Copy link
Author

mmusu3 commented Jan 9, 2019

In this case the compiler does generate a local variable even in release. GetData().Condition = false; is invalid since it produces an error: Error CS1612 Cannot modify the return value of 'GetData()' because it is not a variable.

I though that this example might be a bit too simple to be representative. Here is another that is more like the original problem I encountered where the struct is a wrapper for unmanaged data (still simplified). I hope it gives a better idea of the issue.

Source:

unsafe struct Data
{
    byte* ptr;

    public bool Condition
    {
        get { return *(bool*)ptr; }
        set { *(bool*)ptr = value; }
    }
}

static Data GetData()
{
    throw new NotImplementedException();
}

static void Test()
{
    Data data = GetData();
    data.Condition = false;
}

Output:

private struct Data
{
    public unsafe bool Condition
    {
        get
        {
            return *ptr != 0;
        }
        set
        {
            *ptr = (value ? ((byte)1) : ((byte)0));
        }
    }

    private unsafe byte* ptr;
}

private static Data GetData()
{
    throw new NotImplementedException();
}

private static void Test()
{
    GetData().Condition = false;
}

@dgrunwald dgrunwald closed this in 4ad4f6a Mar 15, 2019

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.