Repository navigation
fix: Private nested types in NetworkVariables in CoreCLR #4239
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
base: develop-3.x.x
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -208,6 +208,36 @@ public static bool HasInterface(this TypeReference typeReference, string interfa | |
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Collects every type that assembly scoped code cannot access when it uses <paramref name="type"/>. | ||
| /// This is each private or protected nested type in its nesting chain, or in the chain of its generic arguments. | ||
| /// </summary> | ||
| /// <param name="type">The type the generated code uses.</param> | ||
| /// <param name="hidden">Receives each inaccessible type, without duplicates.</param> | ||
| public static void CollectTypesHiddenFromAssembly(this TypeReference type, List<TypeDefinition> hidden) | ||
| { | ||
| if (type is GenericInstanceType genericInstance) | ||
| { | ||
| foreach (var argument in genericInstance.GenericArguments) | ||
| { | ||
| argument.CollectTypesHiddenFromAssembly(hidden); | ||
| } | ||
| } | ||
| else if (type is TypeSpecification specification) | ||
| { | ||
| specification.ElementType.CollectTypesHiddenFromAssembly(hidden); | ||
| return; | ||
| } | ||
|
|
||
| for (var definition = type.Resolve(); definition != null && definition.IsNested; definition = definition.DeclaringType) | ||
| { | ||
| if ((definition.IsNestedPrivate || definition.IsNestedFamily || definition.IsNestedFamilyAndAssembly) && !hidden.Contains(definition)) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
🤖 Helpful? 👍/👎 |
||
| { | ||
| hidden.Add(definition); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Checks a generic method instantiation against the generic constraints of the method it instantiates. | ||
| /// Mono does not enforce these on the calls codegen emits, but CoreCLR does, and it rejects the entire | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -437,6 +437,26 @@ private void CreateNetworkVariableTypeInitializers(AssemblyDefinition assembly, | |
| continue; | ||
| } | ||
|
|
||
| // CoreCLR enforces member access on the generic calls emitted below; Mono does not. | ||
| var hiddenTypes = new List<TypeDefinition>(); | ||
| type.CollectTypesHiddenFromAssembly(hiddenTypes); | ||
| if (hiddenTypes.Count > 0) | ||
| { | ||
| #if ENABLE_CORECLR | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The warning/error decision can use the wrong backend when the editor and player runtimes differ. This 🤖 Helpful? 👍/👎 |
||
| foreach (var hiddenType in hiddenTypes) | ||
| { | ||
| m_Diagnostics.AddError($"{type} cannot be used in a network variable - Cannot access the {hiddenType.Name} type to generate serialization as it is {(hiddenType.IsNestedPrivate ? "private" : "protected")}. To fix this, change the access modifier to internal or public."); | ||
| } | ||
| continue; | ||
| #else | ||
| // Log a warning in Mono so we can warn users who haven't yet switched their projects over. | ||
| foreach (var hiddenType in hiddenTypes) | ||
| { | ||
| m_Diagnostics.AddWarning($"NetworkVariable serialization for {type.Name} will fail in CoreCLR! With CoreCLR generated code cannot access the {hiddenType.Name} type to generate serialization as it is {(hiddenType.IsNestedPrivate ? "private" : "protected")}. To fix this, change the access modifier to internal or public."); | ||
| } | ||
| #endif | ||
| } | ||
|
|
||
| if (serializeMethod != null) | ||
| { | ||
| instructions.Add(processor.Create(OpCodes.Call, m_MainModule.ImportReference(serializeMethod))); | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to make it clear that this is related to the CoreCLR stuff above.