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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Match generic type parameters by position, not by name #465

Closed

Conversation

stakx
Copy link
Member

@stakx stakx commented Aug 4, 2019

Fixes #106.

I didn't (and still don't quite) trust this bug fix, mainly because it seems far too easy for DP standards (+-1 LoC!? 馃槤). However, it makes good sense to match generic type parameters by position instead of by name; in IL, for instance, generic type parameters are referred to by position (e.g. ``1). The execution environment doesn't really care about the names.

To give us some added safety, I ran a few additional checks:

  • I ran the Moq unit test suite (approx. 1,500 additional tests) against the updated version of DP to see whether this might cause regressions further downstream. (Doesn't look like it.)
  • I verified that the original Moq issue which led to #106 is fixed by this. (It is.)

@stakx stakx force-pushed the generic-type-parameter-name-mismatch branch from 8ca481e to f8366d6 Compare August 4, 2019 21:46
@@ -303,7 +303,7 @@ public Type[] GetGenericArgumentsFor(MethodInfo genericMethod)
var types = new List<Type>();
foreach (var genType in genericMethod.GetGenericArguments())
{
types.Add(name2GenericType[genType.Name].AsType());
types.Add(genericTypeParams[genType.GenericParameterPosition].AsType());
Copy link
Member

Choose a reason for hiding this comment

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

This makes sense. I wonder if it would be a good idea to check if genericTypeParams isn't null and the array contains the element before accessing it since it is provided externally by SetGenericTypeParameters, then provide a useful exception, so we don't get something useless like the previous KeyNotFoundException one.

Have you looked at the previous GetGenericArgumentsFor overload to see if that should also be changed?

Copy link
Member Author

Choose a reason for hiding this comment

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

I wonder if it would be a good idea to check if genericTypeParams isn't null and the array contains the element before accessing it since it is provided externally by SetGenericTypeParameters

Having an assertion to that effect might be good, but it shouldn't be any more necessary than checking whether name2GenericType contains the key genType.Name. Note how the only place where SetGenericTypeParameters is called from initializes both genericTypeParams and populates name2GenericType:

SetGenericTypeParameters(GenericUtil.CopyGenericArguments(methodToCopyGenericsFrom, typebuilder, name2GenericType));

I'll give it some more thought.

This comment was marked as resolved.

Copy link
Member Author

@stakx stakx Aug 13, 2019

Choose a reason for hiding this comment

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

Have you looked at the previous GetGenericArgumentsFor overload to see if that should also be changed?

@jonorossi, it turns out that other overload is most probably unreachable code. See the new commit for details. Without any test cases, it's hard to know whether or not it is faulty. But given that it's public and there may in theory be external consumers, I think the safest option is to leave it as is, but mark it [Obsolete].

We have yet another method, Type GetGenericArgument(string genericArgumentName), which precedes the two that we've discussed so far. The code paths surrounding generic type arguments are rather convoluted, and I don't understand them well enough (yet) to know whether or not there needs to be a change here, too.

@stakx stakx force-pushed the generic-type-parameter-name-mismatch branch from f8366d6 to dc09dd7 Compare August 13, 2019 20:18
It turns out that beside the name-to-parameter map `name2GenericType`,
we also have a position-to-parameter map available that we can use in-
stead of a costly LINQ query: `genericTypeParams`.
... but let's not turn into a debug-only assertion, because if it *is*
reachable against our assumptions we need to find out about it so that
we can add a test case.
@stakx stakx force-pushed the generic-type-parameter-name-mismatch branch from dc09dd7 to 3acb4d5 Compare August 13, 2019 20:48
@stakx
Copy link
Member Author

stakx commented Aug 13, 2019

I think I'll need to take some time to study the (rather convoluted) code paths that are involved here in much more depth. I'd like to feel more confident in the change I'm proposing here... if possible.

@jonorossi
Copy link
Member

I think I'll need to take some time to study the (rather convoluted) code paths that are involved here in much more depth. I'd like to feel more confident in the change I'm proposing here... if possible.

No problem.

@jonorossi
Copy link
Member

I think I'll need to take some time to study the (rather convoluted) code paths that are involved here in much more depth. I'd like to feel more confident in the change I'm proposing here... if possible.

@stakx any change in your position? Should we merge or close this pull request?

@jonorossi jonorossi marked this pull request as draft April 28, 2020 12:42
@stakx
Copy link
Member Author

stakx commented Apr 28, 2020

I haven't got around to really study this through as the code surrounding this is rather convoluted.

Let's close this for now. When I eventually get this fully done, I'll reopen.

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.

Generic method with differently named generic arguments to parent throws KeyNotFoundException
2 participants