-
Notifications
You must be signed in to change notification settings - Fork 4.6k
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
Remove redundant and incorrect checking. #46094
Conversation
I couldn't figure out the best area label to add to this PR. If you have write-permissions please help me learn by adding exactly one area label. |
@@ -568,8 +568,6 @@ public override MethodInfo MakeGenericMethod(params Type[] typeArguments) | |||
throw new InvalidOperationException("Method is not a generic method definition"); | |||
if (typeArguments == null) | |||
throw new ArgumentNullException(nameof(typeArguments)); | |||
if (generic_params!.Length != typeArguments.Length) |
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'm not sure I understood why this is wrong? It sounds like they should be the same; what do they really represent?
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 checked the implementation on CoreCLR side, this check doesn't exist there. Here are the CoreCLR implementations:
- On one side,
MethodBuilder::MakeGenericMethod
runtime/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/MethodBuilder.cs
Lines 543 to 546 in 0fd78a8
public override MethodInfo MakeGenericMethod(params Type[] typeArguments) { return MethodBuilderInstantiation.MakeGenericMethod(this, typeArguments); } - On the other side, the constructor of
MethodOnTypeBuilderInstantiation
assign type to a variable ofTypeBuilderInstantiation
type. AndMakeGenericMethod
ofTypeBuilderInstantiation
could be found hereruntime/src/coreclr/System.Private.CoreLib/src/System/Reflection/Emit/TypeBuilderInstantiation.cs
Lines 20 to 37 in 1cdafd2
internal static Type MakeGenericType(Type type, Type[] typeArguments) { Debug.Assert(type != null, "this is only called from RuntimeType.MakeGenericType and TypeBuilder.MakeGenericType so 'type' cannot be null"); if (!type.IsGenericTypeDefinition) throw new InvalidOperationException(); if (typeArguments == null) throw new ArgumentNullException(nameof(typeArguments)); foreach (Type t in typeArguments) { if (t == null) throw new ArgumentNullException(nameof(typeArguments)); } return new TypeBuilderInstantiation(type, typeArguments); }
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.
@naricc Evidently CoreCLR actually ends up generating some invalid IL (ie IL that applies the generic method to an incorrect number of arguments) and then only throws an error at runtime https://gist.github.com/lambdageek/e8173ed7b0e3f416ae1ff656d5141f98
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.
@lambdageek, if this is a potential bug in coreclr implementation, should mono introduce the same bug or report it instead to find resolution?
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.
@am11 I don't think it's a bug - or at least I could conceive of a rationalization for why CoreCLR behaves as it does. Just because IL today does not allow - for example - defaulted generic parameters, doesn't mean that it won't support it in the future. So while the IL is bad today, you could imagine using that at some point in the future it might actually be sensible in some circumstances. So it makes sense to allow the IL to be constructed and to leave the check is at the place where it actually matters - in the runtime when it needs to decide how to execute the IL.
(By defaulted generic parameters I mean something like void Method<T1, T2> (T1 arg1, T2 arg2) where T2 : default(T2)=int
and then uses could be Method<string>("abcd", 42) // actually Method<string,int>(...)
)
Tagging subscribers to this area: @CoffeeFlux Issue DetailsMono class
|
please verify the previously failing tests are included in the validation runs with this PR. |
For |
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.
LGTM. In the long term we should try to unify MethodBuilderInstantiation
(CoreCLR) with MethodOnTypeBuilderInst
(Mono) - with the caveat that actually MethodOnTypeBuilderInst
is doing double-duty as MethodBuilderInstantiation
and also MethodOnTypeBuilderInstantiation
(CoreCLR). And the second caveat that the native side in mono in sre.c
will need to be updated to look for the new class names. Slightly non-trivial.
But it's good to first get the tests working and then to undertake a more thorough refactoring.
Created #46149 to track future refactoring work. |
Mono class
MethodOnTypeBuilderInst
was designed to does the same job as two of CoreCLR classesMethodBuilderInstantiation
andMethodOnTypeBuilderInstantiation
. By tracking down the definition of the constructors and function MakeGenericMethod, I came to a conclusion that the argument length checking is redundant and incorrect.Contributes to #2389