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

TypeLoadException when patching a method in a class, which inherits a class that has a generic argument of type enum #73

Open
btastic opened this issue Apr 13, 2023 · 4 comments

Comments

@btastic
Copy link

btastic commented Apr 13, 2023

Describe the bug
I want to patch a method which is residing in a class, that inherits from a class which has a generic argument of 'T' where 'T' is enum.

To Reproduce
I compiled a little package with a simple repro.

You can download the zip file here: https://we.tl/t-yfbtmiVmA5

The packaged game is prepatched with MelonLoader 0.6.1

Steps to reproduce the behavior:

  1. The original method and its signature and class
using System;
using UnityEngine;

public enum GameScreen
{
    Title = 0,
    Game = 1,
}

public class MyGameScreen : GameScreen<GameScreen>
{
    private int _something = 0;

    public void SetSomething(int i)
    {
        _something = i;
    }

    void Start()
    {
    }

    void Update()
    {
    }
}

public class GameScreen<T> : MonoBehaviour where T : Enum
{

}
  1. The patch code
[HarmonyPatch(typeof(MyGameScreen), "SetSomething", new Type[] { typeof(int) })]
public static class Patch
{
    private static void Prefix()
    {
        // The code inside this method will run before 'PrivateMethod' is executed
    }

    private static void Postfix()
    {
        // The code inside this method will run after 'PrivateMethod' has executed
    }
}

public class Mod : MelonMod
{

}

Errors:

[14:48:45.178] [PWS_Tool_Mod] System.TypeLoadException: GenericArguments[0], 'Il2Cpp.GameScreen', on 'Il2Cpp.GameScreen`1[T]' violates the constraint of type parameter 'T'.
   at System.Reflection.CustomAttribute._CreateCaObject(RuntimeModule pModule, RuntimeType type, IRuntimeMethodInfo pCtor, Byte** ppBlob, Byte* pEndBlob, Int32* pcNamedArgs)
   at System.Reflection.CustomAttribute.CreateCaObject(RuntimeModule module, RuntimeType type, IRuntimeMethodInfo ctor, IntPtr& blob, IntPtr blobEnd, Int32& namedArgs)
   at System.Reflection.CustomAttribute.AddCustomAttributes(ListBuilder`1& attributes, RuntimeModule decoratedModule, Int32 decoratedMetadataToken, RuntimeType attributeFilterType, Boolean mustBeInheritable, ListBuilder`1 derivedAttributes)
   at System.Reflection.CustomAttribute.GetCustomAttributes(RuntimeType type, RuntimeType caType, Boolean inherit)
   at System.RuntimeType.GetCustomAttributes(Boolean inherit)
   at HarmonyLib.HarmonyMethodExtensions.GetFromType(Type type)
   at HarmonyLib.PatchClassProcessor..ctor(Harmony instance, Type type, Boolean allowUnannotatedType)
   at HarmonyLib.PatchClassProcessor..ctor(Harmony instance, Type type)
   at HarmonyLib.Harmony.CreateClassProcessor(Type type)
   at HarmonyLib.Harmony.<PatchAll>b__11_0(Type type)
   at HarmonyLib.CollectionExtensions.Do[T](IEnumerable`1 sequence, Action`1 action)
   at HarmonyLib.Harmony.PatchAll(Assembly assembly)
   at MelonLoader.MelonMod.HarmonyInit() in D:\a\MelonLoader\MelonLoader\MelonLoader\Melons\MelonMod.cs:line 40
   at MelonLoader.MelonEvent.<>c.<Invoke>b__1_0(LemonAction x) in D:\a\MelonLoader\MelonLoader\MelonLoader\Melons\Events\MelonEvent.cs:line 174
   at MelonLoader.MelonEventBase`1.Invoke(Action`1 delegateInvoker) in D:\a\MelonLoader\MelonLoader\MelonLoader\Melons\Events\MelonEvent.cs:line 143

Expected behavior
It should not error..?

Screenshots / Code
Not much to say here. I originally intend to patch a game which uses the same unity version, the same code structure etc.

Runtime environment (please complete the following information):

  • OS: Windows 11
  • .NET version: .NET Standard
  • Harmony version: 2.10.1.0
  • Name of game or host application: doesn't matter, I included a custom made sample which reproduces the same error as in the game

Additional context
Add any other context about the problem here.

@btastic
Copy link
Author

btastic commented Apr 13, 2023

It seems that the issue lies within how Il2CPP code is generated, maybe it can't be done in HarmonyX?

I added a reproducible branch here: https://github.com/btastic/HarmonyX/tree/generics_il2cpp (it includes some IL2CPP dll files)

I added a new test class GenericsFromIl2Cpp which will fail with the error message I wrote earlier

@plokmijnuhby
Copy link

Il2CPP code could in theory be changed to allow this, so that all instances of Il2CPPSystem.Enum are replaced with System.Enum. This would, however, be a breaking change, and it would mean that methods of the Enum class itself could no longer be patched.

@plokmijnuhby
Copy link

plokmijnuhby commented Dec 13, 2023

I wonder if the best plan is to introduce some sort of equivalent to each type of enum that inherits from Il2CPPSystem.Enum, that can be used as a parameter? Maybe GenericType<AnEnum> is replaced with GenericType<Il2CPPReferenceEnum<AnEnum>>, or something like that?

@Azim
Copy link

Azim commented May 26, 2024

Was there any progress on that? Im facing a similar issue

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants