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

Fix Enum field type bug found when underlying type is set from assembly loaded with MLC #106375

Merged
merged 2 commits into from
Aug 15, 2024

Conversation

buyaa-n
Copy link
Contributor

@buyaa-n buyaa-n commented Aug 14, 2024

EnumBuilder.UnderlyingSystemType, currently returns GetEnumUnderlyingType() which returns _underlyingField.FieldType underneath. Because Type.Equals checks UnderlyingSystemType for equality when the EnumBuilder underlying type is set from MLC Core assembly it is causing issue for enum fields defined, for example:

Type intType = mlc.CoreAssembly.GetType("System.Int32");
EnumBuilder enumBuilder = mb.DefineEnum("TestEnum", TypeAttributes.Public, intType);
FieldBuilder field = enumBuilder.DefineLiteral("Default", 0);

In this case the field type should be TestEnum, but it is evaluated to be equal to System.Int32 when writing the field signature on Save. I think we should not return underlying field type for EnumBuilder.UnderlyingSystemType, should probably return the Enum itself instead (runtime enums returns the enum type itself). Though the EnumBuilder.GetEnumUnderlyingType() method should keep returning the underlying field type.

Related to #105903

Copy link
Contributor

Tagging subscribers to this area: @dotnet/area-system-reflection-emit
See info in area-owners.md if you want to be subscribed.

@jkotas
Copy link
Member

jkotas commented Aug 14, 2024

Should this

if (IsEnum)
{
if (_enumUnderlyingType == null)
{
throw new InvalidOperationException(SR.InvalidOperation_NoUnderlyingTypeOnEnum);
}
return _enumUnderlyingType;
}
else
{
return this;
}
be changed to just return this as well?

@jkotas
Copy link
Member

jkotas commented Aug 14, 2024

How did you find this issue?

@steveharter
Copy link
Member

steveharter commented Aug 14, 2024

In this case the field type should be TestEnum, but it is evaluated to be equal to System.Int32 when writing the field signature on Save

Does .NET Framework have this issue?

Because Type.Equals checks UnderlyingSystemType for equality

Is an alternative to override Equals(Type) instead of changing UnderlyingSystemType? The "correct" way to check for the underlying type on an enum is GetEnumUnderlyingType() so I'm OK with returning "this" from EnumBuilder.UnderlyingSystemType.

@jkotas
Copy link
Member

jkotas commented Aug 14, 2024

Is an alternative to override Equals(Type)

I would stay away from that. The problem with overriding Type.Equals is that it only works in one direction, it does not handle the case where this is the foreign Type and the argument is your Type.

@buyaa-n
Copy link
Contributor Author

buyaa-n commented Aug 14, 2024

Should this

if (IsEnum)
{
if (_enumUnderlyingType == null)
{
throw new InvalidOperationException(SR.InvalidOperation_NoUnderlyingTypeOnEnum);
}
return _enumUnderlyingType;
}
else
{
return this;
}

be changed to just return this as well?

Good point, I think we also need to add GetEnumUnderlyingType() override that returns this _enumUnderlyingType

@buyaa-n
Copy link
Contributor Author

buyaa-n commented Aug 14, 2024

How did you find this issue?

Found with #105903

@buyaa-n
Copy link
Contributor Author

buyaa-n commented Aug 14, 2024

Does .NET Framework have this issue?

.NET Framework and existing runtime EnumBuilder doesn't have this issue as there is no Core assembly logic, the Type equality check happens when trying to determine the core type from core assembly.

Is an alternative to override Equals(Type)

I would stay away from that. The problem with overriding Type.Equals is that it only works in one direction, it does not handle the case where this is the foreign Type and the argument is your Type.

I tried that, and exactly as @jkotas said it was not solving the issue completely

@steveharter steveharter added this to the 9.0.0 milestone Aug 14, 2024
@buyaa-n buyaa-n merged commit 05053c4 into dotnet:main Aug 15, 2024
84 checks passed
@buyaa-n
Copy link
Contributor Author

buyaa-n commented Aug 15, 2024

/backport to release/9.0

Copy link
Contributor

Started backporting to release/9.0: https://github.com/dotnet/runtime/actions/runs/10411954784

@buyaa-n buyaa-n deleted the enumbuilder_underlyingtype branch August 15, 2024 23:25
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants