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: Adding FastBuffer* extension methods for multiple instantiations of a generic type causes runtime errors [MTT-3063] #2142

Merged

Conversation

ShadauxCat
Copy link
Collaborator

@ShadauxCat ShadauxCat commented Aug 23, 2022

The code that was finding extension methods was not differentiating between different instantiations of generic types - for example, an extension method for List<int> would match when searching for List<string>, and invalid bytecode would be created as a result.

Unfortunately, GenericInstanceType doesn't seem to be something that can be compared with == so I had to make it compare the names instead, which kind of feels bad but I couldn't find another way to do it.

fixes #1582

Changelog

  • Fixed: Fixed RPC codegen failing to choose the correct extension methods for FastBufferReader and FastBufferWriter when the parameters were a generic type (i.e., List<int>) and extensions for multiple instantiations of that type have been defined (i.e., List<int> and List<string>)

Testing and Documentation

  • Includes integration tests.
  • No documentation changes or additions were necessary.

@ShadauxCat ShadauxCat requested a review from a team as a code owner August 23, 2022 21:18
@ShadauxCat ShadauxCat requested a review from 0xFA11 August 23, 2022 21:21
Comment on lines +672 to 673
if (((ByReferenceType)parameters[1].ParameterType).ElementType.FullName == paramType.FullName &&
((ByReferenceType)parameters[1].ParameterType).ElementType.IsArray == paramType.IsArray)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (((ByReferenceType)parameters[1].ParameterType).ElementType.FullName == paramType.FullName &&
((ByReferenceType)parameters[1].ParameterType).ElementType.IsArray == paramType.IsArray)
if (((ByReferenceType)parameters[1].ParameterType).ElementType.FullName == paramType.FullName)

Presumably you don't need the array check anymore since fullname should include []

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I THINK you're right on that, but I'm not confident enough in that thought to remove it. My thought was that leaving it wouldn't hurt anything, but I can't completely guarantee removing it won't... I think we have tests that should cover it if that breaks but again, not 100% sure that they exist or are thorough enough. I personally just kind of feel risk-averse in this part of the codebase.

Comment on lines +682 to 683
if (parameters[1].ParameterType.FullName == paramType.FullName &&
parameters[1].ParameterType.IsArray == paramType.IsArray)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (parameters[1].ParameterType.FullName == paramType.FullName &&
parameters[1].ParameterType.IsArray == paramType.IsArray)
if (parameters[1].ParameterType.FullName == paramType.FullName)

Comment on lines +815 to 816
((ByReferenceType)parameters[1].ParameterType).ElementType.FullName == paramType.FullName &&
((ByReferenceType)parameters[1].ParameterType).ElementType.IsArray == paramType.IsArray)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
((ByReferenceType)parameters[1].ParameterType).ElementType.FullName == paramType.FullName &&
((ByReferenceType)parameters[1].ParameterType).ElementType.IsArray == paramType.IsArray)
((ByReferenceType)parameters[1].ParameterType).ElementType.FullName == paramType.FullName)

@@ -225,62 +225,98 @@ public IEnumerator ExtensionMethodRpcTest()
var obj = new MyObject(256);
var obj2 = new MySharedObjectReferencedById(256);
var obj3 = new MyObjectPassedWithThisRef(256);
var intList = new List<int> { 5, 10, 15, 5, 1 };
var strList = new List<string> { "foo", "bar", "baz", "qux" };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: Maybe a test for nested generics (List<List<string>>) or multiple type generics (KeyValuePair<K, V>)? Shouldn't matter with the new code change so not terribly important - but not sure how comprehensive you're looking for the tests to be.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In an ideal world I would like to make the tests much more comprehensive here. I'd also like to support fully generic extension methods. In the current world - keeping in mind that I've been out for a month and don't know how priorities might have shifted during that time - I didn't think the engineering effort to make them super comprehensive would be worth it.

@JesseOlmer JesseOlmer merged commit e28eb2a into develop Aug 23, 2022
@JesseOlmer JesseOlmer deleted the fix/fastbuffer_extension_methods_for_generic_types branch August 23, 2022 23:20
jakobbbb pushed a commit to GooseGirlGames/com.unity.netcode.gameobjects that referenced this pull request Feb 22, 2023
…of a generic type causes runtime errors [MTT-3063] (Unity-Technologies#2142)

Fixed RPC codegen failing to choose the correct extension methods for FastBufferReader and FastBufferWriter when the parameters were a generic type (i.e., List<int>) and extensions for multiple instantiations of that type have been defined (i.e., List<int> and List<string>)
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

Successfully merging this pull request may close these issues.

When Overloading FastBuffer methods, The wrong reflection is called for List<T>
2 participants