Skip to content

Suppress interface generic dataflow warnings under RUC - #131911

Open
sbomer wants to merge 9 commits into
dotnet:mainfrom
sbomer:runtime-base-ctor
Open

Suppress interface generic dataflow warnings under RUC#131911
sbomer wants to merge 9 commits into
dotnet:mainfrom
sbomer:runtime-base-ctor

Conversation

@sbomer

@sbomer sbomer commented Aug 5, 2026

Copy link
Copy Markdown
Member

Summary

  • suppress generic interface-list IL2026 and IL2091 warnings when the implementing type is directly annotated with RequiresUnreferencedCode
  • keep linker and NativeAOT dataflow running so constructors and members required by the interface instantiation remain preserved
  • keep NativeAOT's independent IL3002 and IL3050 warnings active when only the trimming warning axis is suppressed
  • add cross-tool diagnostic coverage and a kept-member regression for the interface path

This follows the existing base-type behavior while keeping the suppression local to interface-list analysis. Warnings from attributes and DynamicallyAccessedMembers type-hierarchy analysis remain unaffected because those can be reached through reflection outside the type's RequiresUnreferencedCode scope.

Fixes #108507
Fixes #108523

Testing

  • ILLink.RoslynAnalyzer.Tests
  • ILCompiler.Trimming.Tests
  • Mono.Linker.Tests

Note

This content was created with assistance from AI.

sbomer and others added 3 commits July 27, 2026 14:06
Warnings for generic instantiations in the interface list originate from
the type declaration itself, so they are not suppressed by
RequiresUnreferencedCode on the type. The base type case was fixed in
dotnet#119419 by moving the check to the (implicit) constructor,
but the interface list is still analyzed at the type level in the
analyzer, ILLink and ILCompiler.

Cover the interface analogues of the existing base type test cases:
- new() constraint with a RUC generic argument, with and without RUC on
  the implementing type (dotnet#108507)
- DynamicallyAccessedMembers mismatch with RUC on the implementing type
  (dotnet#108523)

The unsuppressed warnings are marked with UnexpectedWarning so the tests
document the current behavior and will need updating once fixed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 89d21a2e-26e9-4e1c-b670-5ec5336c5e28
Assisted-by: GitHub Copilot CLI:claude-opus-5
The generic instantiations in a type's interface list are only reachable
through the members of that type. When the type is annotated with
RequiresUnreferencedCode, all of those members are in the Requires scope,
so the attribute should silence the warnings, the same way it already does
for the base type instantiation (dotnet#119419).

This warns at the type declaration rather than at the point where the type
becomes castable to the interface, so it is scoped narrowly to the three
interface-list call sites instead of being added to the shared Requires
suppression helpers. Attributes on the type and DynamicallyAccessedMembers
type hierarchy warnings are deliberately not affected, since those are
reachable from reflection outside of any Requires scope.

The data flow still runs in ILLink and ILCompiler so that the members
required by the instantiation (for example the parameterless constructor
implied by a new() constraint) keep being marked; only the diagnostics are
suppressed.

Fixes dotnet#108507 for interfaces.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 89d21a2e-26e9-4e1c-b670-5ec5336c5e28
Assisted-by: GitHub Copilot CLI:claude-opus-5
Type-level RequiresUnreferencedCode should suppress the trimming warnings
produced while analyzing a generic interface instantiation, but it does not
suppress RequiresAssemblyFiles or RequiresDynamicCode warnings.

Narrow NativeAOT's warning gate to the trimming axis so IL3002 and IL3050
remain reported. Add regression coverage for those capability warnings and
for the requirement that suppressed interface dataflow still preserves the
members requested by DynamicallyAccessedMembers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 89d21a2e-26e9-4e1c-b670-5ec5336c5e28
Assisted-by: GitHub Copilot CLI:gpt-5.6-sol
Copilot AI lite review requested due to automatic review settings August 5, 2026 23:00
@github-actions github-actions Bot added the area-Tools-ILLink .NET linker development as well as trimming analyzers label Aug 5, 2026
@dotnet-policy-service dotnet-policy-service Bot added the linkable-framework Issues associated with delivering a linker friendly framework label Aug 5, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adjusts trimming/dataflow diagnostics so that generic instantiations in a type’s interface list no longer produce IL2026/IL2091 warnings when the implementing type is directly annotated with RequiresUnreferencedCode, while still running dataflow to preserve members required by the instantiation and maintaining cross-tool consistency (linker, analyzer, NativeAOT).

Changes:

  • Suppress interface-list generic-argument dataflow warnings under type-level RUC while keeping marking/dataflow active (ILLink + NativeAOT).
  • Align Roslyn analyzer behavior to skip interface-list generic instantiation warnings for RUC-annotated types while leaving DAM hierarchy/attribute analysis intact.
  • Extend test coverage to validate warning suppression behavior and that required members are still kept/marked.
Show a summary per file
File Description
src/tools/illink/src/linker/Linker.Steps/MarkStep.cs Adds localized suppression state around interface implementation generic-argument dataflow to silence warnings while still marking required members.
src/tools/illink/src/linker/Linker.Dataflow/GenericArgumentDataFlow.cs Adds a suppression parameter to control whether generic-argument diagnostics are emitted during processing.
src/tools/illink/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs Skips interface-list generic instantiation analysis for types with RequiresUnreferencedCode, while still applying DAM type-hierarchy analysis.
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/DataflowAnalyzedTypeDefinitionNode.cs Suppresses interface-list trimming diagnostics under type-level RUC while still executing dataflow to mark required members.
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs Introduces an option to suppress trim-analysis warnings while keeping other capability warnings (e.g., AOT/single-file) reportable.
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/GenericArgumentDataFlow.cs Threads suppression through generic argument dataflow to match the updated interface-list behavior.
src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs Adds test cases covering interface-list generic warnings under RUC and ensures other capability warnings remain for NativeAOT where appropriate.
src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlowMarking.cs Adds a kept-member regression ensuring interface instantiation still marks required members under RUC suppression.
src/tools/illink/test/Mono.Linker.Tests.Cases/DataFlow/GenericParameterDataFlow.cs Updates expected warnings to reflect the new suppression behavior for interface generic analysis under RUC.

Copilot's findings

  • Files reviewed: 9/9 changed files
  • Comments generated: 1

Keep interface-list suppression limited to trimming diagnostics while
preserving the origin's independent AOT and single-file suppression scopes.
Name the ReflectionMarker suppression argument to clarify which diagnostic
axis it controls.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 89d21a2e-26e9-4e1c-b670-5ec5336c5e28
Assisted-by: GitHub Copilot CLI:gpt-5.6-sol
Copilot AI review requested due to automatic review settings August 6, 2026 18:06

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

Suppressed comments (2)

src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs:1503

  • If you add the non-RUC baseline interface implementation (ClassImplementingInterfaceWithWarning), it needs to be referenced/instantiated so the interface list is processed and the IL2091 expectation is exercised.
                var m = new GenericAnnotatedWithWarningWithRequires<int>();
                var n = new ClassImplementingInterfaceWithWarningOnGenericArgumentConstructor();
                var o = new ClassImplementingInterfaceWithWarningOnGenericArgumentConstructorWithRequires();
                var p = new ClassImplementingInterfaceWithWarningWithRequires();
                var q = new ClassImplementingInterfaceWithOtherCapabilityWarningsWithRequires();

src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs:1457

  • The new coverage for interface-list generic dataflow under type-level RUC doesn't include a non-RUC baseline for the IL2091 interface generic-argument mismatch. Adding one here would ensure the change suppresses IL2091 only under [RequiresUnreferencedCode] and doesn't accidentally suppress it unconditionally.

This issue also appears on line 1499 of the same file.

            [RequiresUnreferencedCode("--ClassImplementingInterfaceWithWarningWithRequires--")]
            public class ClassImplementingInterfaceWithWarningWithRequires : IRequiresAll<T>
            {
            }
  • Files reviewed: 9/9 changed files
  • Comments generated: 0 new

# Conflicts:
#	src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/GenericArgumentDataFlow.cs
Copilot AI review requested due to automatic review settings August 7, 2026 03:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot's findings

Suppressed comments (1)

src/tools/illink/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs:158

  • This change stops analyzing generic instantiations in base types entirely (the previous behavior analyzed both base types and interfaces). That would suppress IL2091 (and related) diagnostics for base-type generic instantiations even when the implementing type is not annotated with RequiresUnreferencedCode.

If the goal is to suppress only interface-list diagnostics under type-level RUC, the base-type analysis should remain (and, if needed, be suppressed separately based on the desired behavior).

                // Examine generic instantiations in the interface list
                context.RegisterSymbolAction(context =>
                {
                    var type = (INamedTypeSymbol)context.Symbol;

                    var location = GetPrimaryLocation(type.Locations);

                    var typeNameResolver = new TypeNameResolver(context.Compilation);

                    // The generic instantiations in the interface list are only reachable through the
                    // members of the type, which are all in the Requires scope of a type-level
                    // RequiresUnreferencedCode, so the attribute silences these warnings.
                    // This is not the case for the DynamicallyAccessedMembers hierarchy below, or for
                    // attributes on the type, which may be accessed via reflection from code which is
                    // not in a Requires scope.
                    if (!type.HasAttribute(RequiresUnreferencedCodeAnalyzer.RequiresUnreferencedCodeAttribute))
                    {
                        var genericArgumentDataFlow = new GenericArgumentDataFlow(dataFlowAnalyzerContext.TrimAnalyzer, FeatureContext.None, typeNameResolver, type, location, context.ReportDiagnostic);

                        foreach (var interfaceType in type.Interfaces)
                            genericArgumentDataFlow.ProcessGenericArgumentDataFlow(interfaceType);
                    }
  • Files reviewed: 9/9 changed files
  • Comments generated: 1

Comment thread src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/Dataflow/ReflectionMarker.cs Outdated
Comment thread src/tools/illink/src/linker/Linker.Steps/MarkStep.cs Outdated

@jtschuster jtschuster left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't love MarkStep._suppressWarningsForInterfaceImplementationDataFlow, but I'm okay if we can't find a cleaner solution right now.

sbomer and others added 4 commits August 9, 2026 20:43
Assisted-by: GitHub Copilot:gpt-5.6-sol
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 89d21a2e-26e9-4e1c-b670-5ec5336c5e28
Assisted-by: GitHub Copilot:gpt-5.6-sol
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 89d21a2e-26e9-4e1c-b670-5ec5336c5e28
Assisted-by: GitHub Copilot:gpt-5.6-sol
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 89d21a2e-26e9-4e1c-b670-5ec5336c5e28
Assisted-by: GitHub Copilot:gpt-5.6-sol
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 89d21a2e-26e9-4e1c-b670-5ec5336c5e28
Copilot AI review requested due to automatic review settings August 10, 2026 17:25

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review details

Suppressed comments (2)

src/tools/illink/src/ILLink.RoslynAnalyzer/DynamicallyAccessedMembersAnalyzer.cs:152

  • The HasAttribute helper only compares the attribute type's simple name (not its namespace), so a user-defined RequiresUnreferencedCodeAttribute could accidentally suppress these interface-list diagnostics. Use a fully-qualified attribute check to avoid false suppression.
                    if (!type.HasAttribute(RequiresUnreferencedCodeAnalyzer.RequiresUnreferencedCodeAttribute))

src/tools/illink/test/Mono.Linker.Tests.Cases/RequiresCapability/RequiresOnClass.cs:1539

  • These assignments exist only to keep the interface types rooted. Using a temporary local that is never read is unnecessary and can generate compiler warnings; use discard assignments (as this file already does) to keep the types referenced.
                Type interfaceType;
                interfaceType = typeof(IRequiresNew<>);
                interfaceType = typeof(IRequiresAll<>);
  • Files reviewed: 10/10 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area-Tools-ILLink .NET linker development as well as trimming analyzers linkable-framework Issues associated with delivering a linker friendly framework

Projects

Status: No status

3 participants