Skip to content

Commit 87fab80

Browse files
Fix duplicate types in generated assemblies on Unity 6.4+
- Use unified type name conversion (MakeValidInSource) for all unstripped types - Look up types by FullName consistently instead of simple name - Skip nested types when parent type is not in the output assembly - Add null guard for Resolve() in HasNonBlittableFields recursion
1 parent 61f44a5 commit 87fab80

1 file changed

Lines changed: 27 additions & 10 deletions

File tree

Il2CppInterop.Generator/Passes/Pass79UnstripTypes.cs

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,20 @@ private static void ProcessType(AssemblyRewriteContext processedAssembly, TypeDe
4747
if (unityType.BaseType != null && unityType.BaseType.FullName == "System.MulticastDelegate")
4848
return;
4949
var newModule = processedAssembly.NewAssembly.ManifestModule!;
50-
var processedType = enclosingNewType == null
51-
? processedAssembly.TryGetTypeByName(unityType.FullName)?.NewType
52-
: enclosingNewType.NestedTypes.SingleOrDefault(it => it.Name == unityType.Name);
50+
var processedType = processedAssembly.TryGetTypeByName(unityType.FullName)?.NewType;
51+
var convertedTypeName = GetConvertedUnityTypeName(processedAssembly.GlobalContext, unityType);
52+
53+
// If the parent type does not exist in the rewritten assembly, this nested type cannot be emitted safely.
54+
// Promoting it to a top-level type creates orphan compiler-generated types such as __O/__c.
55+
if (unityType.DeclaringType != null && enclosingNewType == null && processedType == null)
56+
return;
57+
5358
if (unityType.IsEnum)
5459
{
5560
if (processedType != null) return;
5661

5762
typesUnstripped++;
58-
var clonedType = CloneEnum(unityType, imports);
63+
var clonedType = CloneEnum(unityType, convertedTypeName, imports);
5964
if (enclosingNewType == null)
6065
{
6166
newModule.TopLevelTypes.Add(clonedType);
@@ -74,7 +79,8 @@ private static void ProcessType(AssemblyRewriteContext processedAssembly, TypeDe
7479
!unityType.HasGenericParameters()) // restore all types even if it would be not entirely correct
7580
{
7681
typesUnstripped++;
77-
var clonedType = new TypeDefinition(unityType.Namespace, unityType.Name, ForcePublic(unityType.Attributes), unityType.BaseType == null ? null : newModule.DefaultImporter.ImportType(unityType.BaseType));
82+
var clonedType = new TypeDefinition(unityType.Namespace, convertedTypeName, ForcePublic(unityType.Attributes),
83+
unityType.BaseType == null ? null : newModule.DefaultImporter.ImportType(unityType.BaseType));
7884
if (enclosingNewType == null)
7985
{
8086
newModule.TopLevelTypes.Add(clonedType);
@@ -100,9 +106,9 @@ private static void ProcessType(AssemblyRewriteContext processedAssembly, TypeDe
100106
ProcessType(processedAssembly, nestedUnityType, processedType, imports, ref typesUnstripped);
101107
}
102108

103-
private static TypeDefinition CloneEnum(TypeDefinition sourceEnum, RuntimeAssemblyReferences imports)
109+
private static TypeDefinition CloneEnum(TypeDefinition sourceEnum, string convertedTypeName, RuntimeAssemblyReferences imports)
104110
{
105-
var newType = new TypeDefinition(sourceEnum.Namespace, sourceEnum.Name, ForcePublic(sourceEnum.Attributes),
111+
var newType = new TypeDefinition(sourceEnum.Namespace, convertedTypeName, ForcePublic(sourceEnum.Attributes),
106112
imports.Module.Enum().ToTypeDefOrRef());
107113
foreach (var sourceEnumField in sourceEnum.Fields)
108114
{
@@ -130,14 +136,25 @@ private static bool HasNonBlittableFields(TypeDefinition type)
130136
if (!fieldDefinition.Signature!.FieldType.IsValueType())
131137
return true;
132138

133-
if (fieldDefinition.Signature.FieldType.Namespace?.StartsWith("System") ?? false &&
134-
HasNonBlittableFields(fieldDefinition.Signature.FieldType.Resolve()))
135-
return true;
139+
if (fieldDefinition.Signature.FieldType.Namespace?.StartsWith("System") ?? false)
140+
{
141+
var resolved = fieldDefinition.Signature.FieldType.Resolve();
142+
if (resolved != null && HasNonBlittableFields(resolved))
143+
return true;
144+
}
136145
}
137146

138147
return false;
139148
}
140149

150+
private static string GetConvertedUnityTypeName(RewriteGlobalContext context, TypeDefinition unityType)
151+
{
152+
if (context.Options.PassthroughNames)
153+
return unityType.Name;
154+
155+
return unityType.Name.MakeValidInSource();
156+
}
157+
141158
private static TypeAttributes ForcePublic(TypeAttributes typeAttributes)
142159
{
143160
var visibility = typeAttributes & TypeAttributes.VisibilityMask;

0 commit comments

Comments
 (0)