-
Notifications
You must be signed in to change notification settings - Fork 128
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
Linker warns about generic type flown into lambda method #1416
Comments
I tried suppressing the warning, but I'm not sure how to do it. I've tried: static Func<T> Create<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] T>()
{
return () =>
{
return CreateTypedClient();
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL2006:UnrecognizedReflectionPattern",
Justification = "https://github.com/mono/linker/issues/1416")]
static T CreateTypedClient()
{
return Method<T>();
}
};
} But that still produces warnings.
|
Please dismiss this^, as that issue is not really related to this one (and to clarify, you can suppress warnings on local methods as long as you're not doing it through the Target property). I just verified that the method |
You would need to add a custom attribute to the lambda. That's probably refCount++ to dotnet/csharplang#3115. The workaround should be something along the lines of: static Func<T> Create<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)]T>()
{
return CreateTypedClient;
static T CreateTypedClient()
{
return Method<T>();
}
} You might not even need a suppression because the C# compiler seems to be propagating the custom attribute from Create's T to CreateTypedClient's T (they're different T's in IL no matter how it looks like in C#). |
@marek-safar - I don't believe this should be labeled as a @MichalStrehovsky - that workaround might work for the simplified case, but what about the original code that found this issue? How would I workaround the linker's bug here? internal static IHttpClientBuilder AddTypedClientCore<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TClient>(
this IHttpClientBuilder builder, bool validateSingleType)
where TClient : class
{
ReserveClient(builder, typeof(TClient), builder.Name, validateSingleType);
builder.Services.AddTransient<TClient>(s =>
{
IHttpClientFactory httpClientFactory = s.GetRequiredService<IHttpClientFactory>();
HttpClient httpClient = httpClientFactory.CreateClient(builder.Name);
ITypedHttpClientFactory<TClient> typedClientFactory = s.GetRequiredService<ITypedHttpClientFactory<TClient>>();
return typedClientFactory.CreateClient(httpClient);
});
return builder;
}
where
public interface ITypedHttpClientFactory<[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] TClient> {} Note that not using a lambda in this case is a performance trap - dotnet/roslyn#5835. |
This is not a linker bug. The linker design as specced requires annotating all fields and methods. Linker doesn't operate on C# source code. The output of the C# compiler are unannotated methods with unannotated instance state. Whole program analysis and automatic propagation of annotations was scoped out of the linker design because it's not possible to do in a single pass; linker operates in a single pass to be fast. It's possible to work around this multiple ways:
I don't believe whole program propagation of annotations in general is feasible. It would result in difficult to reason about warnings (the way methods call each other and store stuff into fields would result in situation where flow of data from A to B results in a warning in spot C that would be difficult to connect to A or B - e.g. you would get a several warnings in We could special case the specific shape of closures that C# compiler generates right now, but that's fragile and cannot be done without hardcoding detailed knowledge of how the closures are generated. It also requires a bunch of work on the warning side because we would need to unmangle the "Trim analysis warning IL2006: |
As of .NET 7 RC1 this is fixed - the repro from above doesn't produce any warnings. |
This is similar to #1403, but instead of generated fields, it is for generic types that are flown into lambda methods.
Produces warning:
This was exposed by the following code:
https://github.com/dotnet/runtime/blob/6072e4d3a7a2a1493f514cdf4be75a3d56580e84/src/libraries/Microsoft.Extensions.Http/src/DependencyInjection/HttpClientBuilderExtensions.cs#L330-L345
Where
ITypedHttpClientFactory<TClient>
is annotated withPublicConstructors
onTClient
.We should flow the generic type annotations into these methods.
cc @MichalStrehovsky @sbomer @marek-safar @vitek-karas
The text was updated successfully, but these errors were encountered: