Suppress interface generic dataflow warnings under RUC - #131911
Open
sbomer wants to merge 4 commits into
Open
Conversation
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
Contributor
There was a problem hiding this comment.
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
Comment on lines
+49
to
+53
| var diagnosticContext = new DiagnosticContext( | ||
| origin, | ||
| !logger.ShouldSuppressAnalysisWarningsForRequires(origin.MemberDefinition, DiagnosticUtilities.RequiresUnreferencedCodeAttribute), | ||
| !suppressWarnings && !logger.ShouldSuppressAnalysisWarningsForRequires(origin.MemberDefinition, DiagnosticUtilities.RequiresUnreferencedCodeAttribute), | ||
| logger); | ||
| var reflectionMarker = new ReflectionMarker(logger, factory, flowAnnotations, typeHierarchyDataFlowOrigin: null, enabled: true); | ||
| var reflectionMarker = new ReflectionMarker(logger, factory, flowAnnotations, typeHierarchyDataFlowOrigin: null, enabled: true, suppressWarnings); |
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
Contributor
There was a problem hiding this comment.
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
RequiresUnreferencedCodeThis follows the existing base-type behavior while keeping the suppression local to interface-list analysis. Warnings from attributes and
DynamicallyAccessedMemberstype-hierarchy analysis remain unaffected because those can be reached through reflection outside the type'sRequiresUnreferencedCodescope.Fixes #108507
Fixes #108523
Testing
ILLink.RoslynAnalyzer.TestsILCompiler.Trimming.TestsMono.Linker.TestsNote
This content was created with assistance from AI.