-
Notifications
You must be signed in to change notification settings - Fork 754
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
Invalid trimming suppression in AIJsonUtilities #5629
Comments
It's something we debated when the polyfill got introduced. Ultimately, the desire to avoid viral annotations prevailed. cc @stephentoub |
But not suppressing harms the experience for everyone else, by forcing APIs to be surfaced in particularly non-ergonomic ways. It's a balancing act. In this case, you get an exception the moment you hit this in your app that tells you exactly what the problem is and how to fix it. |
The runtime exceptions have actually been eliminated with some clever use of reflection Eric proposed. The issue now only manifests as missing custom attributes (nullability annotations, description attributes). The workaround to disable |
Then even more so I'm happier suppressing here, since the impact is minimal but the cost of not suppressing like this is high, IIRC. Though maybe I'm merging cases in my head. Remind me what the impact would be in this case of marking this RUC? Regardless, it sounds like the justification is now wrong and should be fixed. |
The same APIs can be surfaced in the same way. You would just need to flow the
This is part of why the suppressions are bad. The static analysis is disabled, so it can't help you anymore.
@agocke @MichalStrehovsky - I don't see any documentation on that switch on learn.microsoft.com. |
Yes, and then to allow the functionality to be used, you need to expose other APIs that complicate the surface area. At which point you need to re-evaluate everything about how it's exposed. When it's a big issue, this makes sense. When it's minor, it's a gray area, in my opinion.
How would [RequiresUnreferencedCode] help with that? If the underlying reason it's been annotated becomes safer, are you alerted to the annotation no longer being necessary? |
How does suppressing the warning change this? Why don't we need these other APIs now?
It turns this case from a possible false-negative into a possible false-postive, which is more desirable. It is more desirable to get a warning, when in fact it is fine, than it is to not get a warning for something that is going to break. |
If we propagate the [RUC] all the way up to public surface area, then for example this needs to show up on AIFunctionFactory.Create, which optionally accepts an AIFunctionFactoryCreateOptions, which optionally contains a JsonSerializerOptions. If that Create is [RUC], then to make the whole factory usable with trimming / NativeAOT, we can't expose it like that, and instead need some other API that forces you to provide a JSO when creating an AIFunctionFactoryCreateOptions and forces you to supply an AIFunctionFactoryCreateOptions to Create.
Right, you're still disabling static analysis, and if something changes, you may never know. For significant issues, yes, knowing about the possibility of an issue is more desirable. For a minor issue, I don't believe that's law. There are similar gray areas everywhere: you accept a JsonSerializerOptions, but the JSO doesn't contain the type information necessary, everything compiles fine, no analyzer warnings, no publish errors, and you may or may not blow up at run-time depending on how the application is written to look for and consume the type information from the JSO. |
Instead use RequiresUnreferencedCode to show that these APIs may not work in trimmed apps. Fix dotnet#5629
Here's all the public API that would need to be annotated 2b17dff |
Note it is only [RUC] on pre-.NET 9 builds, where you aren't using System.Text.Json v9. |
The problem with these annotations is that they're not actionable. There is no alternative API users can call that gets rid of it. They have to either propagate the annotation on their code or suppress it. |
AFAICT - these are the 2 places that are problematic: extensions/src/Shared/JsonSchemaExporter/JsonSchemaExporter.cs Lines 261 to 276 in 6487428
Doing a visual inspection, I don't see any runtime error that will happen if either the constructors (1st case) or the property/field metadata (2nd case) are trimmed. So what will happen is that when you try using these APIs in a trimmed .NET 8 app, you can get a different JSON schema depending on what reflection info was available. If no one else is reflecting on the constructor or properties, the metadata won't be there, and the JSON schema will be missing that information. The property attributes appear to be used for nullability and description info, as @eiriktsarpalis points out above. The constructor is used to know which ctor parameter maps to which property. This is the bad scenario - your app "kinda works" like it did before trimming. But it works in a different way now, because the JSON schema is different. There is no way for you to know that your app is going to behave differently other than by exercising every line after trimming.
The action would be to target |
Related to eiriktsarpalis/stj-schema-mapper#7 |
Your analysis is correct. In practice, this translates to three specific issues:
|
We guarantee to users that either there will be trimming warnings, or the app will behave the same before/after trimming. If you suppress a warning and this doesn't hold, the suppression is simply a bug. It would be better to do nothing (no suppression, just turn off the trimming analyzer on the AIJsonUtilities project). We don't ask users to re-test the entire app after trimming. By suppressing a warning you put them into a position where they would need to re-test entire app every time they publish. Minor changes in completely unrelated parts of the codebase could make it so that this throws or doesn't throw. Whether something is visible from reflection or isn't can be affected by butterfly effects in unrelated parts of the app.
That's because it's an undocumented, and unsupported switch. We only have it due to testing in the dotnet/runtime repo and trying to phase it out (dotnet/runtime#91774). There's no intention to ship it. It doesn't "solve" trimming. |
We have the following trimming suppression:
extensions/src/Libraries/Microsoft.Extensions.AI.Abstractions/Utilities/AIJsonUtilities.Schema.cs
Lines 193 to 198 in 6487428
This is an incorrect way to address trimming warnings. The intention of the warnings is so developers now upfront what does and what doesn't work when the build and publish a trimmed or native AOT'd app. Suppressing warnings like this minimizes the principle of "if you don't get warnings during publish, your app is guaranteed to work the same as before you published".
We should remove this suppression and either make the underlying code trim-compatible, or we should annotate this method as
RequiresUnreferencedCode
.cc @eiriktsarpalis
The text was updated successfully, but these errors were encountered: