Skip to content

Generated code for generic field references is incorrect #334

Open
0 of 1 issue completed
Open
@adrianoc

Description

@adrianoc
class Foo<T>
{
    public T item;

    public void SetItem(T v) => item = v;
}

generates the following snippet for the SetItem() method:

//Method : SetItem
var md_SetItem_3 = new MethodDefinition("SetItem", MethodAttributes.Public | MethodAttributes.HideBySig, assembly.MainModule.TypeSystem.Void);
cls_Foo_0.Methods.Add(md_SetItem_3);
md_SetItem_3.Body.InitLocals = true;
var il_SetItem_4 = md_SetItem_3.Body.GetILProcessor();

//Parameters of 'public void SetItem(T v) => item = v;'
var p_v_5 = new ParameterDefinition("v", ParameterAttributes.None, gp_T_1);
md_SetItem_3.Parameters.Add(p_v_5);

//item = v
il_SetItem_4.Emit(OpCodes.Ldarg_0);
il_SetItem_4.Emit(OpCodes.Ldarg_1);
il_SetItem_4.Emit(OpCodes.Stfld, fld_Item_2);
il_SetItem_4.Emit(OpCodes.Ret);

the line

il_SetItem_4.Emit(OpCodes.Stfld, fld_Item_2);

produces the following IL:

IL_0002: stfld !0 Foo`1::item

which is incorrect.

The IL generated by the C# compiler is:

IL_0002: stfld !0 Foo`1<!T>::item

This seems to happen because the parent of fld_Item_2 is a generic type definition when it should be a generic instance type.

if we replace the line that set the field with something like:

var newParent = new GenericInstanceType(cls_Foo_0);
newParent.GenericArguments.Add(gp_T_1);
var newFieldReference = new FieldReference("item", gp_T_1);
newFieldReference.DeclaringType = newParent;

il_SetItem_4.Emit(OpCodes.Stfld, newFieldReference);

then the generated IL matches the one generated by the C# compiler.

Note

Interestingly enough both ilverify and the runtime are happy with the "invalid" IL. Maybe with more complex types (or type hierarchies) it may result runtime errors?

We should also check other member types:

  • Properties
  • Events
  • Methods

Sub-issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    🐛 bugSomething isn't workingwipWork In Progress

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions