Skip to content

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers#8686

Open
Evangelink wants to merge 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute
Open

Convert AOT/trim pragma suppressions to attributes so they propagate to consumers#8686
Evangelink wants to merge 3 commits into
microsoft:mainfrom
Evangelink:dev/amauryleve/aot-pragma-to-suppress-attribute

Conversation

@Evangelink
Copy link
Copy Markdown
Member

@Evangelink Evangelink commented May 29, 2026

Motivation

PR #8586 enables a Native AOT integration test that exercises MSTest.TestAdapter. When that test publishes with PublishAot=true + MSBuildTreatWarningsAsErrors=true + TrimmerSingleWarn=false, the ILC trim/AOT analyzer surfaces every individual warning from MSTest's libraries as an error.

Many of those warnings are already suppressed in source via #pragma warning disable ILxxxx — but the C# #pragma only silences the compile-time warning. It has no effect on the linker/ILC analyzer warnings that fire at a downstream consumer's publish time. To silence those, suppressions must be expressed as attributes ([UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that survive into the IL where ILC can see them.

This PR is a focused mechanical conversion of MSTest's existing IL pragmas to attribute form, addressing ~31 of the warnings #8586 currently surfaces. It is independent of #8586 and can land first.

Changes (product code)

File Change
TestFramework/Internal/ReflectionTestMethodInfo.cs Add [RequiresUnreferencedCode] (NET5+) and [RequiresDynamicCode] (NET7+) on the MakeGenericMethod override to match the base member's annotations (fixes IL2046 / IL3051)
MSTestAdapter.PlatformServices/Services/TestSourceHost.cs [UnconditionalSuppressMessage("SingleFile", "IL3000")] on GetResolutionPaths
MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.cs Same on Deploy
Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.cs Same on GetAssemblyPath
MSTestAdapter.PlatformServices/AssemblyResolver.cs [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2026")] on LoadAssemblyFrom
MSTestAdapter.PlatformServices/Services/ReflectionOperations.cs Per-method suppressions (10 methods) for IL2026/IL2057/IL2070
MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.cs Lambdas extracted to named methods so attributes apply (ILC reports on the generated method, not the source-level enclosing method); per-method [UnconditionalSuppressMessage] for IL2026/IL3050
MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.cs Per-method suppressions for IL2026 / IL2070
MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.cs Per-method suppression for IL2060 / IL3050 on ConstructGenericMethod
MSTestAdapter.PlatformServices/TestMethodFilter.cs [UnconditionalSuppressMessage("ReflectionAnalysis", "IL2072")] on GetTestCaseFilterFromDiscoveryContext

What the attributes actually do for end users

[UnconditionalSuppressMessage("...", "ILxxxx")] does two things at different times:

  • At MSTest's build time: silences the C# warning at the source location (same as the old #pragma).
  • At the end user's dotnet publish /p:PublishTrimmed=true (or PublishAot=true) time: the suppression is baked into IL metadata, so ILC's analyzer reads it and stops reporting the corresponding warning from MSTest's assemblies into the consumer's build output.

Important caveat — these attributes do not make the reflection-mode adapter trim/AOT-safe at runtime. They only stop the analyzer noise. MSTest's source-generator path remains the only AOT-safe entry point. The justifications make that explicit.

[RequiresUnreferencedCode] / [RequiresDynamicCode] on ReflectionTestMethodInfo.MakeGenericMethod do the opposite — they propagate a requirement to callers, matching the base MethodInfo.MakeGenericMethod annotations and restoring override consistency (which itself was an analyzer error: IL2046/IL3051).

New acceptance test

This PR also adds MSTest.Acceptance.IntegrationTests.TrimTests.Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources. It:

  • generates a project referencing MSTest.TestAdapter + MSTest.TestFramework + Microsoft.Testing.Platform,
  • enables PublishTrimmed=true + TrimmerSingleWarn=false,
  • uses <TrimmerRootAssembly> to force trim analysis of the full surface of the assemblies we changed (MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, MSTest.TestFramework),
  • asserts that the source files we suppressed (TestSourceHost.cs, DeploymentUtilityBase.cs, ReflectionOperations.cs, etc.) no longer appear in publish output.

The trimmer includes source-file paths in its IL2xxx/IL3xxx messages, so absence ≡ the suppression attributes are being honored. The test does not enable TreatWarningsAsErrors because out-of-scope warnings (vstest submodule, System.Private.DataContractSerialization internals) would otherwise fail it; the assertions on specific source-file names are scoped to MSTest's own code.

Out of scope (deferred)

These warnings from the same #8586 test output are intentionally not addressed here:

  • MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 — belongs in the source generator emitter (fix in Add MSTest reflection source generator (issue #1837) #8586 or a generator-side follow-up).
  • Microsoft.TestPlatform.ObjectModel warnings (TestObject.cs, TestProperty.cs, CustomKeyValueConverter.cs, CustomStringArrayConverter.cs) — that's the vstest submodule, not this repo.
  • Transitive DataContract IL3050 warnings emitted from inside System.Private.DataContractSerialization.
  • Broader interface-level refactor (e.g. propagating [RequiresUnreferencedCode] onto IReflectionOperations) — out of scope for a mechanical conversion.

Local validation

  • Release builds of MSTestAdapter.PlatformServices, TestFramework, Microsoft.Testing.Extensions.VSTestBridge and the acceptance test project all build with 0 warnings / 0 errors.
  • The new acceptance test will run in CI.

…to consumers

#pragma warning disable IL2xxx/IL3xxx only silences C# compile-time warnings; it does not affect ILC analyzer warnings at downstream consumers' publish time. Convert MSTest's existing pragma suppressions into attribute-based suppressions (UnconditionalSuppressMessage / RequiresUnreferencedCode / RequiresDynamicCode) that survive into IL and are honored by ILC.

This is motivated by microsoft#8586 which switches the NativeAOT integration test to reference MSTest.TestAdapter, surfacing all of MSTest's previously-pragma'd warnings as errors. This change addresses ~31 of those warnings independently of microsoft#8586.

Out of scope (future work): warnings from vstest's Microsoft.TestPlatform.ObjectModel (submodule), the MSTestSourceGeneratedReflectionMetadata.g.cs IL2070 (belongs in microsoft#8586's generator emitter), and transitive DataContract warnings inside System.Private.DataContractSerialization.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 29, 2026 17:28
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

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 updates MSTest/TestAdapter code to ensure existing ILLink/NativeAOT/single-file warning suppressions propagate to downstream consumers by converting #pragma warning disable ILxxxx suppressions into attribute-based suppressions (e.g., [UnconditionalSuppressMessage], [RequiresUnreferencedCode], [RequiresDynamicCode]) that are preserved in emitted IL.

Changes:

  • Convert IL3000 (single-file Assembly.Location) pragma suppressions to [UnconditionalSuppressMessage] in adapter/bridge paths.
  • Convert reflection/trimming/AOT-related pragma suppressions (IL2026/IL2057/IL2060/IL2067/IL2070/IL2072/IL3050) to per-member attribute suppressions in reflection-heavy helpers/services.
  • Refactor DataSerializationHelper serializer-cache lambdas into named methods so suppressions attach to the analyzer-reported call sites.
Show a summary per file
File Description
src/TestFramework/TestFramework/Internal/ReflectionTestMethodInfo.cs Adds Requires* attributes to MakeGenericMethod override (guarded by TFM) so downstream trimming/AOT analyzers see the annotations.
src/Platform/Microsoft.Testing.Extensions.VSTestBridge/SynchronizedSingleSessionVSTestAndTestAnywhereAdapter.cs Replaces IL3000 pragmas with an attribute on GetAssemblyPath so single-file suppression survives into consumer publish.
src/Adapter/MSTestAdapter.PlatformServices/Utilities/DeploymentUtilityBase.cs Adds IL3000 suppression attribute to deployment path and removes localized pragma usage.
src/Adapter/MSTestAdapter.PlatformServices/TestMethodFilter.cs Adds IL2072 suppression attribute for reflection-based VSTest discovery-context filter extraction.
src/Adapter/MSTestAdapter.PlatformServices/Services/TestSourceHost.cs Adds IL3000 suppression attribute to resolution-path logic and removes pragmas.
src/Adapter/MSTestAdapter.PlatformServices/Services/ReflectionOperations.cs Replaces broad pragma block with targeted per-method suppression attributes for trimming/reflection warnings.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/ManagedNameHelper.cs Adds per-method suppression attributes for reflection-based managed-name lookup.
src/Adapter/MSTestAdapter.PlatformServices/Helpers/DataSerializationHelper.cs Adds IL2026/IL3050 suppressions and extracts serializer factories into named methods so suppressions apply correctly.
src/Adapter/MSTestAdapter.PlatformServices/Extensions/MethodInfoExtensions.cs Adds IL2060/IL3050 suppression attributes to generic-method construction helper.
src/Adapter/MSTestAdapter.PlatformServices/AssemblyResolver.cs Adds IL2026 suppression attribute to LoadAssemblyFrom and removes pragma wrapper.

Copilot's findings

  • Files reviewed: 10/10 changed files
  • Comments generated: 0

Adds Publish_WithTestAdapter_DoesNotSurfaceWarningsFromSuppressedSources to MSTest.Acceptance.IntegrationTests/TrimTests.cs. Publishes a small project that references MSTest.TestAdapter with PublishTrimmed=true and TrimmerRootAssembly forcing trim analysis of MSTestAdapter.PlatformServices, Microsoft.Testing.Extensions.VSTestBridge, and MSTest.TestFramework. Asserts that the source files we suppressed in this PR no longer appear in publish output (the IL trimmer includes source paths in its warnings, so absence == suppression worked).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…FromSuppressedSources

DotnetCli.RunAsync defaults warnAsError to true, which auto-injects

-p:MSBuildTreatWarningsAsErrors=true -p:TreatWarningsAsErrors=true into the publish

command. The acceptance test for this PR was written assuming TreatWarningsAsErrors

is OFF (so out-of-repo trim warnings from the vstest ObjectModel submodule and

App Insights stay as warnings, and the test can grep the publish output for

the absence of suppressed source file names).

Without this fix the publish fails with NETSDK1144 (Optimizing assemblies for size

failed) due to dozens of trim warnings that are explicitly out of scope for this PR.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings May 29, 2026 20:13
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Copilot's findings

  • Files reviewed: 11/11 changed files
  • Comments generated: 0 new

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants