-
Notifications
You must be signed in to change notification settings - Fork 2.7k
System.Reflection: Replicate custom modifiers of method parameters in MemberRef signatures #17881
Conversation
One quick note: this will propagate custom modifiers attached to the parameter type itself but not any types are used to construct the type. E.g. a parameter of type This is a long standing defect in how Reflection thinks about custom modifiers and it's not likely you could address this here without majorly impacting the cost of the fix. Just noting it here so we know the limitation exists, that this fix still solves the problem you wanted to solve with that limitation and that we're proceeding with knowledge of that. |
@atsushikan - I've suggested above that perhaps this PR shouldn't just focus on the
Is this the right time and place to do all of this (well, maybe not the last bullet point)? Or should I stick to the original, narrow scenario that led to this PR for now? (I'm fine with both.) Update: I'll just go ahead and prepare all changes (except for additions to the public API). Given that the C# compiler also produces modreqs on return types ( |
if (parameterTypes != null) | ||
{ | ||
int i = 0; |
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.
I would just turn this into a for (int i = …)
loop.
This method reproduces a method's signature for use in a MethodRef metadata entry, but currently ignores custom modifiers placed in the method's parameters. Add additional parameters for those.
This lets the change from the previous commit "bubble up" towards the public API by adding support for parameter cmods in more places.
ModuleBuilder.GetMemberRefToken
@atsushikan - I started working on return parameters, but found that this poses some additional problems and puzzles to solve. I think it'd be better to deal with return parameters in a separate, dedicated PR. In my opinion, the present PR is ready for review / merging. (Expand this to see an example of an additional problem unique to return parameters.)In this PR, often a coreclr/src/System.Private.CoreLib/src/System/Reflection/RuntimeConstructorInfo.cs Lines 231 to 232 in e353a22
Either a corresponding new method It's these kinds of decisions I'd like to shift to a separate PR to keep the present one focused. |
Type[][] requiredCustomModifiers = null; | ||
Type[][] optionalCustomModifiers = null; | ||
|
||
if (parameters?.Length > 0) |
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.
Every caller of this passes a non-null parameters
. The ?
isn't needed.
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.
Thanks for the review. I've replaced all three null-conditional member accesses ?.
with .
.
types[i] = parameters[i].ParameterType; | ||
|
||
Type[] rcms = parameters[i].GetRequiredCustomModifiers(); | ||
if (rcms?.Length > 0) |
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.
The ?
isn't needed. GetRequiredCustomModifiers
never returns a null array.
} | ||
|
||
Type[] ocms = parameters[i].GetOptionalCustomModifiers(); | ||
if (ocms?.Length > 0) |
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.
Same comment regarding ?
Other than noted, LGTM. |
In several places, `ParameterInfo[]` is converted to three matching arrays for parameter types and their modreqs and modpts, because that is what `SignatureHelper` requires. Extract this duplicated logic into a single method. Also, optimize it to reduce array allocations.
Thanks for the work @stakx. 👍 |
@TAGC - Thanks for the thumbs-up, I appreciate it! Not quite done yet, but we're getting there. |
This is in response to https://github.com/dotnet/corefx/issues/29254.
ModuleBuilder.GetMemberRefToken
reproduces a method's signature for use in a MethodRef metadata entry, but currently ignores custom modifiers placed on the method's parameters... which leads to non-matching signatures andMissingMethodException
s when using e.g. reflection.This commit adds a new method overload (in order to avoid a larger refactoring for now) that allows the inclusion of custom modifiers on parameters.
This is currently work in progress:Needs further testing.I ran successful end-to-end tests using tests from Castle DynamicProxy, which has tests targeting this. I'm going to submit another PR with tests for dotnet/corefx.
Are there any code paths intoModuleBuilder.GetMemberRefToken
that are negatively affected by the change made?It appears unlikely and did not find any (but it's pretty hard to keep track here, given all the branching and similarly named methods strewn across at least two classes).
Are there any other code paths into the method that could profit from the change made?Additional code paths have been included in the second commit of this PR.
Shouldn't the same be done for the methods' return type (not just its parameters)?Yes, but as it turns out, doing this for return parameters poses some unique problems that are perhaps better dealt with in a separate, dedicated PR.