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

Match generic parameters by position, not by name #580

Merged
merged 9 commits into from Mar 25, 2021

Conversation

stakx
Copy link
Member

@stakx stakx commented Feb 22, 2021

Fixes #106. See commit messages for further explanations.

This is a redo of #465, which we closed because I needed more time to study how DynamicProxy deals with generics. I think I've now got an understanding of the bigger picture, and am feeling more confident that the proposed change is sound.


One might think that some of the infrastructure being removed here could have come in handy once we decide to support open generic proxy type generation (#448). However, I don't think this is the case:

  • As one commit message remarks, some of the parameter mapping code appears to be incomplete. Worse than that, it might even be buggy. It is hard to tell which because we don't have any test cases nor real-world scenarios that cover it (which also makes it so much harder to even understand what the code was supposed to achieve).

  • More importantly, matching arguments by name fundamentally seems like the wrong approach, because that is not how the underlying platform works: the CLI generally identifies generic parameters by their position.

I think we're better off basing future developments on new (position-based) code instead of the name2GenericType infrastructure being removed here.

@stakx stakx force-pushed the generic-parameter-name-mismatch branch from bba86ea to 3e7ce38 Compare February 22, 2021 20:19
@stakx stakx requested a review from jonorossi February 22, 2021 20:28
@teneko
Copy link

teneko commented Mar 14, 2021

Seems to fix #585.

teneko added a commit to teneko/Teronis.DotNet that referenced this pull request Mar 14, 2021
Copy link
Member

@jonorossi jonorossi left a comment

Choose a reason for hiding this comment

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

@stakx this looks great!

@jonorossi jonorossi added this to the v5.0.0 milestone Mar 24, 2021
To understand why this change is permissible, it is helpful to know the
types generated by DynamicProxy:

 * Proxy types. Those are (at present) never generic.

 * Delegate types and invocation classes. Those may be generic, and when
   they are, their generic parameters correspond exactly with those of
   some target method.

It is this correspondence which makes any mapping by name unnecessary.
The constructor being changed is only called by event/property emitters,
via the `MetaType` model, and by contributors, all of which are used for
proxy type generation only (and those are never generic).

The only generic types generated by DynamicProxy are delegate types and
invocation classes, but their generators never call this `MethodEmitter`
ctor.
Because `name2GenericType` is in practice always an empty dictionary,
the helper methods `ExtractCorrectType` and `ExtractParametersTypes` in
`GenericUtil` don't really do anything. They can be removed since noone
else is using them.

(Side note: it looks like `ExtractCorrectType` might have malfunctioned,
had it ever actually done anything: it maps parameters `T` -> `Tmapped`
and arrays `T[]` -> `Tmapped[]`, but forgets about instantiatd generic
types involving `T` as an argument, such as `IEnumerable<T>`.)
@stakx stakx force-pushed the generic-parameter-name-mismatch branch from 3e7ce38 to c3780f1 Compare March 25, 2021 21:13
@stakx stakx merged commit d88e944 into castleproject:master Mar 25, 2021
@stakx stakx deleted the generic-parameter-name-mismatch branch March 25, 2021 21:21
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
3 participants