From a9ab5e9de023b52cc42e25d213da055ed2622b76 Mon Sep 17 00:00:00 2001
From: ds5678 <49847914+ds5678@users.noreply.github.com>
Date: Fri, 12 Jul 2024 00:35:45 -0700
Subject: [PATCH] Fix consistency issue with name unmangling for generic
 parameters

---
 .../Contexts/FieldRewriteContext.cs           |  2 +-
 .../Contexts/MethodRewriteContext.cs          |  4 +--
 .../Extensions/StringEx.cs                    | 25 +++++++++++++++----
 .../Passes/Pass70GenerateProperties.cs        |  2 +-
 4 files changed, 24 insertions(+), 9 deletions(-)

diff --git a/Il2CppInterop.Generator/Contexts/FieldRewriteContext.cs b/Il2CppInterop.Generator/Contexts/FieldRewriteContext.cs
index a6c41f39..0d890367 100644
--- a/Il2CppInterop.Generator/Contexts/FieldRewriteContext.cs
+++ b/Il2CppInterop.Generator/Contexts/FieldRewriteContext.cs
@@ -52,7 +52,7 @@ private string UnmangleFieldNameBase(FieldDefinition field, GeneratorOptions opt
         var accessModString = MethodAccessTypeLabels[(int)(field.Attributes & FieldAttributes.FieldAccessMask)];
         var staticString = field.IsStatic ? "_Static" : "";
         return "field_" + accessModString + staticString + "_" +
-               DeclaringType.AssemblyContext.RewriteTypeRef(field.Signature!.FieldType).GetUnmangledName();
+               DeclaringType.AssemblyContext.RewriteTypeRef(field.Signature!.FieldType).GetUnmangledName(field.DeclaringType);
     }
 
     private string UnmangleFieldName(FieldDefinition field, GeneratorOptions options,
diff --git a/Il2CppInterop.Generator/Contexts/MethodRewriteContext.cs b/Il2CppInterop.Generator/Contexts/MethodRewriteContext.cs
index 47538af1..ea6f8492 100644
--- a/Il2CppInterop.Generator/Contexts/MethodRewriteContext.cs
+++ b/Il2CppInterop.Generator/Contexts/MethodRewriteContext.cs
@@ -225,12 +225,12 @@ private string ProduceMethodSignatureBase()
                     builder.Append(str);
 
         builder.Append('_');
-        builder.Append(DeclaringType.AssemblyContext.RewriteTypeRef(method.Signature?.ReturnType).GetUnmangledName());
+        builder.Append(DeclaringType.AssemblyContext.RewriteTypeRef(method.Signature?.ReturnType).GetUnmangledName(method.DeclaringType, method));
 
         foreach (var param in method.Parameters)
         {
             builder.Append('_');
-            builder.Append(DeclaringType.AssemblyContext.RewriteTypeRef(param.ParameterType).GetUnmangledName());
+            builder.Append(DeclaringType.AssemblyContext.RewriteTypeRef(param.ParameterType).GetUnmangledName(method.DeclaringType, method));
         }
 
         var address = Rva;
diff --git a/Il2CppInterop.Generator/Extensions/StringEx.cs b/Il2CppInterop.Generator/Extensions/StringEx.cs
index 312ddf45..37c8c1d3 100644
--- a/Il2CppInterop.Generator/Extensions/StringEx.cs
+++ b/Il2CppInterop.Generator/Extensions/StringEx.cs
@@ -1,6 +1,7 @@
 using System.Diagnostics.CodeAnalysis;
 using System.Text;
 using AsmResolver;
+using AsmResolver.DotNet;
 using AsmResolver.DotNet.Signatures;
 
 namespace Il2CppInterop.Generator.Extensions;
@@ -116,27 +117,41 @@ public static bool StartsWith([NotNullWhen(true)] this Utf8String? str, string v
         return str is not null && str.Value.StartsWith(value, StringComparison.Ordinal);
     }
 
-    public static string GetUnmangledName(this TypeSignature typeRef)
+    /// <summary>
+    /// Construct an unmangled name for a type signature.
+    /// </summary>
+    /// <param name="typeRef"></param>
+    /// <param name="declaringType">The declaring type to use for resolving generic type parameter names.</param>
+    /// <param name="declaringMethod">The declaring method to use for resolving generic method parameter names.</param>
+    /// <returns></returns>
+    public static string GetUnmangledName(this TypeSignature typeRef, TypeDefinition? declaringType = null, MethodDefinition? declaringMethod = null)
     {
         var builder = new StringBuilder();
         if (typeRef is GenericInstanceTypeSignature genericInstance)
         {
-            builder.Append(genericInstance.GenericType.ToTypeSignature().GetUnmangledName());
+            builder.Append(genericInstance.GenericType.ToTypeSignature().GetUnmangledName(declaringType, declaringMethod));
             foreach (var genericArgument in genericInstance.TypeArguments)
             {
                 builder.Append("_");
-                builder.Append(genericArgument.GetUnmangledName());
+                builder.Append(genericArgument.GetUnmangledName(declaringType, declaringMethod));
             }
         }
         else if (typeRef is ByReferenceTypeSignature byRef)
         {
             builder.Append("byref_");
-            builder.Append(byRef.BaseType.GetUnmangledName());
+            builder.Append(byRef.BaseType.GetUnmangledName(declaringType, declaringMethod));
         }
         else if (typeRef is PointerTypeSignature pointer)
         {
             builder.Append("ptr_");
-            builder.Append(pointer.BaseType.GetUnmangledName());
+            builder.Append(pointer.BaseType.GetUnmangledName(declaringType, declaringMethod));
+        }
+        else if (typeRef is GenericParameterSignature genericParameter)
+        {
+            if (genericParameter.ParameterType == GenericParameterType.Type)
+                builder.Append(declaringType!.GenericParameters[genericParameter.Index].Name);
+            else
+                builder.Append(declaringMethod!.GenericParameters[genericParameter.Index].Name);
         }
         else
         {
diff --git a/Il2CppInterop.Generator/Passes/Pass70GenerateProperties.cs b/Il2CppInterop.Generator/Passes/Pass70GenerateProperties.cs
index 7dc84bae..8083f72e 100644
--- a/Il2CppInterop.Generator/Passes/Pass70GenerateProperties.cs
+++ b/Il2CppInterop.Generator/Passes/Pass70GenerateProperties.cs
@@ -68,7 +68,7 @@ private static string UnmanglePropertyName(AssemblyRewriteContext assemblyContex
         if (assemblyContext.GlobalContext.Options.PassthroughNames ||
             !prop.Name.IsObfuscated(assemblyContext.GlobalContext.Options)) return prop.Name!;
 
-        var baseName = "prop_" + assemblyContext.RewriteTypeRef(prop.Signature!.ReturnType).GetUnmangledName();
+        var baseName = "prop_" + assemblyContext.RewriteTypeRef(prop.Signature!.ReturnType).GetUnmangledName(prop.DeclaringType);
 
         countsByBaseName.TryGetValue(baseName, out var index);
         countsByBaseName[baseName] = index + 1;