Avoid producing Requires* warnings when accessing constant fields (#84622)
authorVitek Karas <10670590+vitek-karas@users.noreply.github.com>
Tue, 11 Apr 2023 18:58:40 +0000 (11:58 -0700)
committerGitHub <noreply@github.com>
Tue, 11 Apr 2023 18:58:40 +0000 (11:58 -0700)
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 https://github.com/dotnet/runtime/issues/84433

src/tools/illink/src/ILLink.RoslynAnalyzer/RequiresAnalyzerBase.cs
src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs

index 49c85c7..cd3dca2 100644 (file)
@@ -197,6 +197,13 @@ namespace ILLink.RoslynAnalyzer
                                        if (operationContext.Operation.Parent is IOperation operation && operation.Kind == OperationKind.NameOf)
                                                return;
 
+                                       // Do not emit any diagnostics for constant fields - they can only have Requires attributes applied to them
+                                       // via the type, and in that case the attribute is guarding the access to the static ctor.
+                                       // But constant fields are never accessed at runtime, and thus they don't cause static ctor to run.
+                                       // Constant fields are always inlined by the compiler (required by the ECMA spec).
+                                       if (member is IFieldSymbol field && field.HasConstantValue)
+                                               return;
+
                                        ISymbol containingSymbol = FindContainingSymbol (operationContext, AnalyzerDiagnosticTargets);
 
                                        // Do not emit any diagnostic if caller is annotated with the attribute too.
index 97c6292..93445e8 100644 (file)
@@ -1243,11 +1243,6 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
                                public static void Method () { }
                        }
 
-                       // https://github.com/dotnet/runtime/issues/84433
-                       [ExpectedWarning ("IL2026", "--ConstClassWithRequires--", nameof (ConstClassWithRequires.Message), ProducedBy = Tool.Analyzer)]
-                       [ExpectedWarning ("IL3050", "--ConstClassWithRequires--", nameof (ConstClassWithRequires.Message), ProducedBy = Tool.Analyzer)]
-                       [ExpectedWarning ("IL2026", "--ConstClassWithRequires--", nameof (ConstClassWithRequires.Number), ProducedBy = Tool.Analyzer)]
-                       [ExpectedWarning ("IL3050", "--ConstClassWithRequires--", nameof (ConstClassWithRequires.Number), ProducedBy = Tool.Analyzer)]
                        [ExpectedWarning ("IL2026", "--ConstClassWithRequires--", nameof (ConstClassWithRequires.Method))]
                        [ExpectedWarning ("IL3050", "--ConstClassWithRequires--", nameof (ConstClassWithRequires.Method), ProducedBy = Tool.Analyzer | Tool.NativeAot)]
                        static void TestClassWithRequires ()
@@ -1258,12 +1253,7 @@ namespace Mono.Linker.Tests.Cases.RequiresCapability
                                ConstClassWithRequires.Method ();
                        }
 
-                       // https://github.com/dotnet/runtime/issues/84433
-                       [ExpectedWarning ("IL2026", "--ConstClassWithRequiresUsingField--", nameof (ConstClassWithRequiresUsingField.Message), ProducedBy = Tool.Analyzer)]
-                       [ExpectedWarning ("IL3050", "--ConstClassWithRequiresUsingField--", nameof (ConstClassWithRequiresUsingField.Message), ProducedBy = Tool.Analyzer)]
                        [RequiresUnreferencedCode (ConstClassWithRequiresUsingField.Message)]
-                       [ExpectedWarning ("IL2026", "--ConstClassWithRequiresUsingField--", nameof (ConstClassWithRequiresUsingField.Message), ProducedBy = Tool.Analyzer)]
-                       [ExpectedWarning ("IL3050", "--ConstClassWithRequiresUsingField--", nameof (ConstClassWithRequiresUsingField.Message), ProducedBy = Tool.Analyzer)]
                        [RequiresDynamicCode (ConstClassWithRequiresUsingField.Message)]
                        class ConstClassWithRequiresUsingField
                        {