-
Notifications
You must be signed in to change notification settings - Fork 4.5k
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
When is AOT + MakeGenericType safe? #71625
Comments
Tagging subscribers to this area: @dotnet/area-meta Issue Details
What are the rules around
|
The rule is basically "the native code for the generic instantiation has to be present". I don't know if there's a more succinct version of this documented somewhere - I had a twitter thread on how generic code is done in .NET that kind of explains what the problem is here: https://twitter.com/MStrehovsky/status/1244602445461950470. We generally suppress the warnings within CoreLib in places where the compiler is doing work to ensure the native code will be available at runtime. That's not very useful for things outside CoreLib. As an implementation detail (that has been true since .NET 2.0 and is unlikely to change), code for instantiations over reference types is fully shareable. So:
...the warning can be suppressed as well. Fully shareable code generation can be triggered in three ways, basically:
If you don't have the shared code available at runtime, there will be an exception at the time of MakeGeneric. For example: typeof(Foo<>).MakeGenericType(typeof(Bar));
class Foo<T> { }
struct Bar { } At runtime:
(The exception type and string is expected to change in .NET 7. Probably to PlatformNotSupportedException. The existing message dates back to .NET Native for UWP apps.) |
One more implementation detail that we don't intend to change: using System;
new Foo<Bar>();
typeof(Foo<>).MakeGenericType(typeof(Bar));
Console.WriteLine("It worked!");
typeof(Foo<>).MakeGenericType(typeof(Baz));
class Foo<T> { }
struct Bar { }
struct Baz { } This will print "It worked" and then crash with the unhandled exception. This is because we made native code for So if there's an upper bound on the list of |
Thanks, this is good info. All the cases I've been looking at include a constant for the generic definition (i.e. Kind of related follow up question: Do you know how optimized services.TryAddSingleton(typeof(ServerCallHandlerFactory<>));
services.TryAddSingleton(typeof(IGrpcServiceActivator<>), typeof(DefaultGrpcServiceActivator<>));
services.TryAddSingleton(typeof(IGrpcInterceptorActivator<>), typeof(DefaultGrpcInterceptorActivator<>)); The argument type is always a class in these examples. Is DI generating optimal code? |
Do you mean in the context of NativeAOT? CoreCLR-NativeAOT uses the same code generator as CoreCLR-JIT - RyuJIT. So the generated code will be the same. CoreCLR-JIT can do PGO-driven dynamic recompilation so it has a chance to produce better code in some cases, but I don't know how big of a difference it would make here. On the other hand, NativeAOT has a whole program view so it can devirtualize all interface calls to their actual targets if there's only one type implementing the interface within the app (we don't do that yet but there's a WIP pull request). |
MakeGenericType
generates warnings whenPublishAot
is enabled. I took at look at dotnet/runtime and there are some places where the IL3050 warning fromMakeGenericType
is suppressed.What are the rules around
MakeGenericType
? When is it safe to have it in a framework or library? And what happens if tries to create a type that it can't?The text was updated successfully, but these errors were encountered: