Skip to content
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

Aot Analyzer shouldn't warn when passing a const string to RequiresDynamicCode applied to Types #84433

Closed
eerhardt opened this issue Apr 6, 2023 · 10 comments · Fixed by #84622
Assignees
Labels
area-Tools-ILLink .NET linker development as well as trimming analyzers
Milestone

Comments

@eerhardt
Copy link
Member

eerhardt commented Apr 6, 2023

If I have a class like:

    [RequiresDynamicCode(RequiresDynamicCodeMessage)]
    public class XmlDsigXsltTransform : Transform
    {
        internal const string RequiresDynamicCodeMessage = "XmlDsigXsltTransform uses XslCompiledTransform which requires dynamic code.";

I am getting a warning by the analyzer:

XmlDsigXsltTransform.cs(12,26): error IL3050: Using member 'System.Security.Cryptography.Xml.XmlDsigXsltTransform.RequiresDynamicCodeMessage' which has RequiresDynamicCodeAttribute' can break functionality when AOT compiling. XmlDsigXsltTransform uses XslCompiledTransform which equires dynamic code. [C:\git\runtime2\src\libraries\System.Security.Cryptography.Xml\src\System.Security.Cryptography.Xml.csproj::TargetFramework=net8.0]

Similarly, if I reference the const string from another RequiresDynamicCode attribute applied to a class:

    [RequiresDynamicCode(XmlDsigXsltTransform.RequiresDynamicCodeMessage)]
    public class SignedInfo : ICollection
    {

produces:

SignedInfo.cs(10,26): error IL3050: Using member  'System.Security.Cryptography.Xml.XmlDsigXsltTransform.RequiresDynamicCodeMessage' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. XmlDsigXsltTransform uses XslCompiledTransform which requires dynamic code. [C:\git\runtime2\src\libraries\System.Security.Cryptography.Xml\src\System.Security.Cryptography.Xml.csproj::TargetFramework=net8.0]

But if I reference the const string from a RequiresDynamicCode attribute applied to a method, it doesn't warn:

        [RequiresDynamicCode(XmlDsigXsltTransform.RequiresDynamicCodeMessage)]
        internal void LoadXml(XmlElement value)
        {

I am declaring a RequiresDynamicCode attribute, the parameter I pass to the ctor of the attribute should also be considered as being in a "RequiresDynamicCode" scope - since by definition, I'm inside RequiresDynamicCode.

@vitek-karas @sbomer

@eerhardt eerhardt added the area-Tools-ILLink .NET linker development as well as trimming analyzers label Apr 6, 2023
@ghost ghost added the untriaged New issue has not been triaged by the area owner label Apr 6, 2023
@ghost
Copy link

ghost commented Apr 6, 2023

Tagging subscribers to this area: @agocke, @sbomer, @vitek-karas
See info in area-owners.md if you want to be subscribed.

Issue Details

If I have a class like:

    [RequiresDynamicCode(RequiresDynamicCodeMessage)]
    public class XmlDsigXsltTransform : Transform
    {
        internal const string RequiresDynamicCodeMessage = "XmlDsigXsltTransform uses XslCompiledTransform which requires dynamic code.";

I am getting a warning by the analyzer:

XmlDsigXsltTransform.cs(12,26): error IL3050: Using member 'System.Security.Cryptography.Xml.XmlDsigXsltTransform.RequiresDynamicCodeMessage' which has RequiresDynamicCodeAttribute' can break functionality when AOT compiling. XmlDsigXsltTransform uses XslCompiledTransform which equires dynamic code. [C:\git\runtime2\src\libraries\System.Security.Cryptography.Xml\src\System.Security.Cryptography.Xml.csproj::TargetFramework=net8.0]

Similarly, if I reference the const string from another RequiresDynamicCode attribute applied to a class:

    [RequiresDynamicCode(XmlDsigXsltTransform.RequiresDynamicCodeMessage)]
    public class SignedInfo : ICollection
    {

produces:

SignedInfo.cs(10,26): error IL3050: Using member  'System.Security.Cryptography.Xml.XmlDsigXsltTransform.RequiresDynamicCodeMessage' which has 'RequiresDynamicCodeAttribute' can break functionality when AOT compiling. XmlDsigXsltTransform uses XslCompiledTransform which requires dynamic code. [C:\git\runtime2\src\libraries\System.Security.Cryptography.Xml\src\System.Security.Cryptography.Xml.csproj::TargetFramework=net8.0]

But if I reference the const string from a RequiresDynamicCode attribute applied to a method, it doesn't warn:

        [RequiresDynamicCode(XmlDsigXsltTransform.RequiresDynamicCodeMessage)]
        internal void LoadXml(XmlElement value)
        {

I am declaring a RequiresDynamicCode attribute, the parameter I pass to the ctor of the attribute should also be considered as being in a "RequiresDynamicCode" scope - since by definition, I'm inside RequiresDynamicCode.

@vitek-karas @sbomer

Author: eerhardt
Assignees: -
Labels:

area-Tools-ILLink

Milestone: -

@agocke agocke added this to the 8.0.0 milestone Apr 6, 2023
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Apr 6, 2023
@agocke agocke self-assigned this Apr 6, 2023
@agocke
Copy link
Member

agocke commented Apr 6, 2023

A simple solution here might be that Requires on types does not apply to consts in the type as though they were statics.

@agocke
Copy link
Member

agocke commented Apr 6, 2023

This area is somewhat problematic as Requires on consts actually doesn't work in the trimmer/AOT because consts don't exist in IL -- they're always inlined.

But they do exist for the source generator, and I've previously mentioned that it could be useful to place RUC on a particular enum value to indicate that that setting is not trim compatible.

Curious on what you think @sbomer @vitek-karas

@vitek-karas
Copy link
Member

A simple solution here might be that Requires on types does not apply to consts in the type as though they were statics.

RUC on type applies to statics and .ctors - that's the rule. That's why the warning kicks in. The question here is if there's any situation where the .cctor would be triggered by an access to a const field.
If not - then we can safely ignore const fields in this case.

@agocke
Copy link
Member

agocke commented Apr 6, 2023

RUC on type applies to statics and .ctors - that's the rule. That's why the warning kicks in.

Right, and the warning behavior rests on the definition of consts, from my perspective. If we see const values as "functionally static" then the current behavior is consistent.

If we decide consts are a separate category, we can apply a different rule to them.

@vitek-karas
Copy link
Member

I've previously mentioned that it could be useful to place RUC on a particular enum value to indicate that that setting is not trim compatible.

There's been several discussions on this - the problem is that from IL this is really hard to tell because the values are inlined by the compiler and they look like integers (not even typed as the enum)

@agocke
Copy link
Member

agocke commented Apr 6, 2023

Sure -- leaving aside the IL analysis, is it useful to consider only having support in the analyzer?

@vitek-karas
Copy link
Member

Hmm - maybe in this case it would be beneficial.
I image also being able to "Obsolete" enum values would be nice as well.

vitek-karas added a commit to vitek-karas/runtime that referenced this issue Apr 6, 2023
The IL tools (illink, ilc) don't see const field references in code, since the compiler inlines the values. But analyzer does see them. If the const field is on a type with Requires attribute, that access is reported as a warning, which is only produced by the analyzer.

This adds tests for these cases, no product changes.

Tests for dotnet#84433
vitek-karas added a commit that referenced this issue Apr 7, 2023
#84452)

The IL tools (illink, ilc) don't see const field references in code, since the compiler inlines the values. But analyzer does see them. If the const field is on a type with Requires attribute, that access is reported as a warning, which is only produced by the analyzer.

This adds tests for these cases, no product changes.

Tests for #84433
@MichalStrehovsky
Copy link
Member

The only reason why we warn on access to static fields on RUC types is cctor - if there's a cctor, the field access would trigger it. But literal fields don't trigger the cctor because they don't actually get accessed. So the reason doesn't apply: there's nothing "unsafe" about data access. I don't think we should warn.

Is there any value in hypothetically being able to mark enum values as RUC? I don't see how that would work E2E:

Method(SomeEnum.Unsafe);

enum SomeEnum { Safe, [RUC] Unsafe }

static void Method(SomeEnum val) { ... }

So source analyzer would warn here because it sees SomeEnum.Unsafe being used. But IL analysis doesn't see it and won't warn.

So we need to do something so that IL analysis can see it. We have no option but to mark Method as RUC. But now the source analyzer warns twice, IL analyzer warns once.

If we wanted to go in the direction of carving out safe enum values, we'd probably put the annotations on code. So something like:

[RequiresUnreferencedCodeWhen(nameof(val), SomeEnum.Unsafe)]
static void Method(SomeEnum val) { ... }

vitek-karas added a commit to vitek-karas/runtime that referenced this issue Apr 11, 2023
Fields can only be annotated with `Requires*` attributes through their type (so RUC on type and so on). But that annotation is actually not guarding access to the field itself, but it's actually guarding access to static members, including static constructor.

Constant fields don't trigger static constructor. In fact at runtime constant fields are never accessed by code. The compiler is required to inline their values instead.

So IL based scanners will never produce the above warning, only analyzer would.

This change modifies the analyzer to stop producing warings for accessing constant fields.

Fixes dotnet#84433
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Apr 11, 2023
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Apr 11, 2023
vitek-karas added a commit that referenced this issue Apr 11, 2023
…4622)

Fields can only be annotated with `Requires*` attributes through their type (so RUC on type and so on). But that annotation is actually not guarding access to the field itself, but it's actually guarding access to static members, including static constructor.

Constant fields don't trigger static constructor. In fact at runtime constant fields are never accessed by code. The compiler is required to inline their values instead.

So IL based scanners will never produce the above warning, only analyzer would.

This change modifies the analyzer to stop producing warings for accessing constant fields.

Fixes #84433
@ghost ghost locked as resolved and limited conversation to collaborators May 11, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-Tools-ILLink .NET linker development as well as trimming analyzers
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants