Skip to content

Commit 1d59c92

Browse files
committed
Address PR review: fix AOT warning fixture comments and harden per-API check.
1 parent aff579d commit 1d59c92

4 files changed

Lines changed: 48 additions & 25 deletions

File tree

default.proj

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -100,15 +100,25 @@
100100
fails. Unlike VerifyAot proper, this needs no native toolchain - a plain build
101101
surfaces the analyzer diagnostics - so it is cheap to run anywhere.
102102
103-
Keep ExpectedAotWarningCodes in sync with the diagnostics produced by
104-
test/Autofac.Test.AotWarnings/Program.cs.
103+
The check is PER CALL SITE, not just per diagnostic code: each ExpectedAotWarning
104+
item names both the code (IL2026/IL3050) and a distinctive substring of the
105+
annotated member's signature as it appears in the warning text. Multiple call
106+
sites share a code (e.g. RegisterGeneric and RegisterGenericDecorator are both
107+
IL3050), so asserting only "IL3050 appears somewhere" would not catch losing the
108+
annotation on just one of them. Matching the member signature catches each one.
109+
110+
Keep the ExpectedAotWarning items in sync with the calls in
111+
test/Autofac.Test.AotWarnings/Program.cs - one item per annotated call.
105112
-->
106113
<PropertyGroup>
107114
<AotWarningsProjectDirectory>$([System.IO.Path]::Combine($(MSBuildProjectDirectory),'test/Autofac.Test.AotWarnings'))</AotWarningsProjectDirectory>
108115
</PropertyGroup>
109116
<ItemGroup>
110-
<ExpectedAotWarningCode Include="IL3050" />
111-
<ExpectedAotWarningCode Include="IL2026" />
117+
<!-- Identity = the IL code; Member = a substring uniquely identifying the API in the warning text. -->
118+
<ExpectedAotWarning Include="IL3050" Member="RegisterGeneric(ContainerBuilder, Type)" />
119+
<ExpectedAotWarning Include="IL3050" Member="RegisterGenericDecorator(ContainerBuilder, Type, Type" />
120+
<ExpectedAotWarning Include="IL2026" Member="RegisterAssemblyTypes(ContainerBuilder, params Assembly" />
121+
<ExpectedAotWarning Include="IL2026" Member="RegisterAssemblyModules(ContainerBuilder, params Assembly" />
112122
</ItemGroup>
113123
<Target Name="VerifyAotWarnings">
114124
<Message Text="****************************************" Importance="high" />
@@ -123,8 +133,9 @@
123133
<PropertyGroup>
124134
<AotWarningsBuildText>@(AotWarningsBuildOutput, '%0a')</AotWarningsBuildText>
125135
</PropertyGroup>
126-
<Error Condition="!$(AotWarningsBuildText.Contains('warning %(ExpectedAotWarningCode.Identity)'))"
127-
Text="Expected AOT/trim diagnostic %(ExpectedAotWarningCode.Identity) was NOT emitted by Autofac.Test.AotWarnings. A [RequiresDynamicCode]/[RequiresUnreferencedCode] annotation may have been lost in core Autofac." />
128-
<Message Text="All expected AOT/trim warnings (@(ExpectedAotWarningCode, ', ')) were emitted." Importance="high" />
136+
<!-- Each expected warning must appear with BOTH its code and the specific member signature. -->
137+
<Error Condition="!($(AotWarningsBuildText.Contains('warning %(ExpectedAotWarning.Identity)')) and $(AotWarningsBuildText.Contains('%(ExpectedAotWarning.Member)')))"
138+
Text="Expected AOT/trim diagnostic %(ExpectedAotWarning.Identity) for '%(ExpectedAotWarning.Member)' was NOT emitted by Autofac.Test.AotWarnings. A [RequiresDynamicCode]/[RequiresUnreferencedCode] annotation may have been lost in core Autofac." />
139+
<Message Text="All expected AOT/trim warnings were emitted (@(ExpectedAotWarning->'%(Identity): %(Member)', '; '))." Importance="high" />
129140
</Target>
130141
</Project>

test/Autofac.Test.Aot/Program.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,11 @@ public static int Main()
136136
// --- Scenarios that MUST throw under Native AOT (dynamic-code boundary) ---
137137

138138
// Closing an open generic over a VALUE type requires MakeGenericType over a
139-
// value type, which Native AOT cannot generate.
139+
// value type, which Native AOT cannot generate. This assertion is deliberately
140+
// runtime/environment sensitive: if a future runtime adds universal shared
141+
// generics for value types, this could start SUCCEEDING and fail the check.
142+
// That is by design - a failure here likely means "the AOT boundary moved"
143+
// (update this test and the AOT docs), not "Autofac is broken".
140144
CheckThrows(failures, "Resolve IGenericHolder<int> (value-type close)", () => container.Resolve<IGenericHolder<int>>());
141145

142146
if (failures.Count > 0)

test/Autofac.Test.AotWarnings/Autofac.Test.AotWarnings.csproj

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,23 @@
22
<!--
33
AOT/trim WARNING fixture.
44
5-
This project's job is to FAIL TO BUILD. It calls the Autofac APIs that are
6-
annotated [RequiresDynamicCode] / [RequiresUnreferencedCode], with
7-
IsAotCompatible=true (which turns on the trim/AOT analyzers) and
8-
TreatWarningsAsErrors=true, so the analyzer diagnostics become build errors.
5+
This project is EXPECTED TO BUILD SUCCESSFULLY and, in doing so, emit the
6+
trim/AOT analyzer warnings (IL2026 / IL3050) for the Autofac APIs that are
7+
annotated [RequiresUnreferencedCode] / [RequiresDynamicCode]. Setting
8+
IsAotCompatible=true turns on those analyzers, and TreatWarningsAsErrors is left
9+
OFF so the warnings stay warnings (and the build still succeeds).
910
10-
The 'VerifyAotWarnings' target in default.proj builds this project EXPECTING
11-
failure and asserts that the expected IL2026/IL3050 codes appear. That guards
11+
The 'VerifyAotWarnings' target in default.proj builds this project and asserts
12+
the expected IL codes appear in the (successful) build output. That guards
1213
against silently LOSING a [Requires*] attribute in a future refactor: if an
13-
annotation is dropped, the corresponding warning stops firing, this project
14-
starts building successfully, and the verification target fails.
14+
annotation is dropped, the corresponding warning stops firing and the target
15+
fails because an expected code is missing.
1516
1617
Unlike the runtime smoke test (Autofac.Test.Aot) this needs no native toolchain -
1718
plain 'dotnet build' surfaces the analyzer diagnostics - so it runs in normal CI.
1819
19-
It is intentionally NOT part of Autofac.sln so the normal build does not try to
20-
compile a project that is designed not to compile.
20+
It is intentionally NOT part of Autofac.sln; it exists only to be built by the
21+
verify target.
2122
-->
2223
<PropertyGroup>
2324
<OutputType>Exe</OutputType>
@@ -26,14 +27,17 @@
2627
<ImplicitUsings>enable</ImplicitUsings>
2728
<IsPackable>false</IsPackable>
2829
<IsTestProject>false</IsTestProject>
30+
<!-- Sign to match the rest of the repo's assemblies (and the sibling AOT test project). -->
31+
<AssemblyOriginatorKeyFile>../../Autofac.snk</AssemblyOriginatorKeyFile>
32+
<SignAssembly>true</SignAssembly>
2933
<!-- Turn on the trim/AOT analyzers so the [Requires*] diagnostics are emitted. -->
3034
<IsAotCompatible>true</IsAotCompatible>
3135
<TrimmerSingleWarn>false</TrimmerSingleWarn>
3236
<!--
33-
This project is verified by building it and asserting it fails. Do not let a
34-
stray analyzer/style rule turn into an error that masks the IL diagnostics, and
35-
do not treat the deliberate IL warnings as errors here - the verify target reads
36-
them from the (failed-by-design) build output instead.
37+
Keep TreatWarningsAsErrors OFF: this project is supposed to build successfully
38+
WITH the trim/AOT warnings present, and the verify target reads the IL codes
39+
from that successful build output. Treating them as errors would fail the build
40+
and there would be no output to inspect.
3741
-->
3842
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
3943
<RunAnalyzers>true</RunAnalyzers>

test/Autofac.Test.AotWarnings/Program.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,13 @@
99
// Each statement below calls an Autofac API that is annotated [RequiresDynamicCode]
1010
// or [RequiresUnreferencedCode]. With IsAotCompatible=true the trim/AOT analyzers
1111
// run and emit the IL codes noted in the comments. The 'VerifyAotWarnings' target in
12-
// default.proj builds this project and asserts those codes are present in the output;
13-
// if an annotation is ever lost, the corresponding warning disappears and the target
14-
// fails. The expected codes are duplicated in that target - keep them in sync.
12+
// default.proj builds this project and asserts, PER CALL SITE, that the expected
13+
// warning appears (matching both the IL code and the member signature - several call
14+
// sites share a code, so a code-only check would miss losing one of them). If an
15+
// annotation is ever lost, the matching warning disappears and the target fails.
16+
//
17+
// Keep these calls in sync with the ExpectedAotWarning items in default.proj - one
18+
// item there per annotated call here.
1519
var builder = new ContainerBuilder();
1620

1721
// IL3050 (RequiresDynamicCode): open generic registration constructs closed types

0 commit comments

Comments
 (0)