weasel#263: Add Weasel.Core.AotSmoke + per-provider IsAotCompatible audit#283
Merged
Merged
Conversation
…udit
Part 1 — Weasel.Core.AotSmoke
New console project src/Weasel.Core.AotSmoke/ that mirrors the
src/JasperFx.AotSmoke/ pattern (jasperfx commit d4077d8):
- Microsoft.NET.Sdk console Exe, IsAotCompatible=true, TrimMode=full
- WarningsAsErrors=IL2026;IL2046;IL2055;IL2065;IL2067;IL2070;IL2072;
IL2075;IL2090;IL2091;IL2111;IL3050;IL3051 (mirroring jasperfx)
- ProjectReference to Weasel.Core only (no provider deps — that's
intentionally separate, per the chip)
Program.cs touches a representative cross-section of Weasel.Core's
post-#270 consolidation surface:
- DbObjectName(schema, name) + .QualifiedName
- Cross-provider enums: CascadeAction, EnumStorage, CreationStyle,
SchemaPatchDifference, SqlFormatting, BulkInsertMode, AutoCreate
- ForeignKeyBase.Parse + LinkColumns + structural Equals (the #270
step 4 consolidation outputs)
- TableBase<TColumn, TIndex, TForeignKey>: AddColumn,
AddPrimaryKeyColumn, HasColumn, ColumnFor, AddForeignKey,
PrimaryKeyName (via DefaultPrimaryKeyName hook), RemoveColumn,
IgnoreIndex (#270 step 9)
- IDdlSyntaxStrategy: implement + call WriteDropTable +
WriteCreateTableHeader + the property surface (#270 step 8)
Minimal SmokeColumn / SmokeIndex / SmokeForeignKey / SmokeTable /
SmokeMigrator / SmokeSyntax stubs implement just enough of each
abstract base to instantiate it from this consumer project. Bodies
that aren't exercised throw — the smoke test only cares whether the
surface compiles cleanly under IsAotCompatible=true + TrimMode=full.
Wired into Weasel.slnx so CI workflows (which run plain dotnet build)
pick it up automatically. No CI-yml changes needed.
Part 1.5 — Fix two pre-existing IL warnings in Weasel.Core
The smoke project's IsAotCompatible build immediately surfaced two
defects from PR #272 that the original IL3050/IL2075 cleanup hadn't
quite landed correctly:
IL3051 in AssertCommand.cs:31 — the [RequiresDynamicCode] override
didn't match the unannotated base (JasperFxAsyncCommand<T>.Execute).
Removed [RequiresDynamicCode] and kept the [UnconditionalSuppressMessage]
for IL3050, which actually silences the underlying warning.
IL2098 in CommandBuilderBase.cs:291 — [DynamicallyAccessedMembers]
on an `object` parameter is invalid (the attribute only works on
Type/string parameters). Removed the attribute and updated xmldoc
to point at the [RequiresUnreferencedCode] already on the method
as the actual caller-contract.
Part 2 — Per-provider IsAotCompatible audit
| Provider | IsAotCompatible | Notes |
|---|---|---|
| Weasel.Postgresql | true | + 3 wrapper annotations: ICommandBuilder.AddParameters(object) marked [RequiresUnreferencedCode] to match the base; BatchBuilder.AddParameters(object) likewise + IL2075 suppression at the GetType().GetProperties() call site; PostgresqlProvider.determineParameterType suppresses IL2070 at the typeInfo.ImplementedInterfaces lookup (cold-path IEnumerable<T> detection), GetNullableType marked [RequiresDynamicCode] for the Type.MakeGenericType(Nullable<>) call, AddTimespanTypes + CustomizableWhereFragment.Apply suppress the resulting cascade with Justifications. Pre-register types via storeMappings / RegisterMapping to avoid these paths under AOT. |
| Weasel.SqlServer | true | + 2 wrapper annotations: ICommandBuilder.AddParameters(object) and BatchBuilder.AddParameters(object) — same RUC pattern as PG. |
| Weasel.Oracle | true | Clean out of the box. |
| Weasel.MySql | true | Clean out of the box. |
| Weasel.Sqlite | true | Clean out of the box. |
| Weasel.EntityFrameworkCore | true | + 4 wrapper suppressions on EF Core's reflective surfaces (FindEntityType, AddTransient<TImpl>, GetType().GetProperty by name). EF Core upstream is not AOT-ready (dotnet/efcore#29761); consumers of Weasel.EntityFrameworkCore targeting AOT inherit that limitation. Justifications point at the upstream issue. |
Acceptance criteria:
- dotnet build clean on the entire solution (Weasel.slnx); the smoke
project's WarningsAsErrors list is fully satisfied.
- The smoke executable exits cleanly under net10.0:
"Weasel.Core AOT smoke OK — exercised DbObjectName, ForeignKeyBase.Parse,
TableBase, IDdlSyntaxStrategy."
- Per-provider audit table documented above.
- The "smoke test catches regressions" sanity criterion: empirically
proven by the two pre-existing Weasel.Core IL warnings (IL3051 +
IL2098) that the smoke build immediately surfaced and are now
fixed in Part 1.5.
Behavioural impact: none. All annotations are AOT/trim diagnostics
that affect compile-time analyzer output, not runtime behaviour.
Test suites that ran:
- Weasel.Core: 6/6
- Weasel.Postgresql: 634/640 (6 pre-existing skips)
- Weasel.Sqlite: 360/361 (1 pre-existing timezone-boundary flake)
- Weasel.EntityFrameworkCore: 18/35 (17 pre-existing failures
against bare master — confirmed via `git stash`; require SQL
Server connectivity not available locally)
References weasel#263, JasperFx/jasperfx#213.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This was referenced May 18, 2026
Closed
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.
Ticks off two boxes on the Weasel 9.0 master tracker (#263):
JasperFx.AotSmokein jasperfx).Weasel.Postgresql/Weasel.SqlServer/Weasel.Oracle/Weasel.MySql/Weasel.Sqlite/Weasel.EntityFrameworkCore.Part 1 —
Weasel.Core.AotSmokeNew console project
src/Weasel.Core.AotSmoke/modelled onsrc/JasperFx.AotSmoke/in jasperfx (commitd4077d8):Microsoft.NET.Sdkconsole Exe,IsAotCompatible=true,TrimMode=fullWarningsAsErrors=IL2026;IL2046;IL2055;IL2065;IL2067;IL2070;IL2072;IL2075;IL2090;IL2091;IL2111;IL3050;IL3051(mirroring jasperfx)Weasel.Coreonly — no provider deps, per the chipProgram.csexercises the #270 consolidation surface:DbObjectName, the cross-provider enums,ForeignKeyBase.Parse/LinkColumns/Equals,TableBase<TColumn, TIndex, TForeignKey>(via aSmokeTablesubclass that overrides every abstract), andIDdlSyntaxStrategy(via aSmokeSyntaximplementation). Wired intoWeasel.slnxso CI workflows pick it up.Part 1.5 — Fix two pre-existing Weasel.Core warnings the smoke test surfaced
The smoke project's
IsAotCompatiblebuild immediately flagged two defects from PR #272 that the original IL3050/IL2075 cleanup hadn't quite landed correctly:AssertCommand.cs— the[RequiresDynamicCode]override didn't match the unannotated base (JasperFxAsyncCommand<T>.Execute). Removed[RequiresDynamicCode]and kept the[UnconditionalSuppressMessage]for IL3050, which actually silences the underlying warning.CommandBuilderBase.cs—[DynamicallyAccessedMembers]on anobjectparameter is invalid (the attribute only works onType/stringparams). Removed the attribute; updated xmldoc to point at the[RequiresUnreferencedCode]already on the method as the actual caller-contract.This is direct evidence the smoke test works as designed.
Part 2 — Per-provider audit table
IsAotCompatibleWeasel.PostgresqltrueICommandBuilder.AddParameters(object)marked[RequiresUnreferencedCode]to match the base;BatchBuilder.AddParameters(object)likewise + IL2075 suppression at theGetType().GetProperties()call site;PostgresqlProvider.determineParameterTypesuppresses IL2070 at thetypeInfo.ImplementedInterfaceslookup (cold-pathIEnumerable<T>detection),GetNullableTypemarked[RequiresDynamicCode]for theType.MakeGenericType(Nullable<>)call,AddTimespanTypes+CustomizableWhereFragment.Applysuppress the resulting cascade with Justifications. Pre-register types viastoreMappings/RegisterMappingto avoid these paths under AOT.Weasel.SqlServertrueICommandBuilder.AddParameters(object)andBatchBuilder.AddParameters(object)— same[RequiresUnreferencedCode]pattern as PG.Weasel.OracletrueWeasel.MySqltrueWeasel.SqlitetrueWeasel.EntityFrameworkCoretrueFindEntityType,AddTransient<TImpl>,GetType().GetPropertyby name). EF Core upstream is not AOT-ready (dotnet/efcore#29761); consumers of Weasel.EntityFrameworkCore targeting AOT inherit that limitation. Justifications point at the upstream issue.Test plan
dotnet build Weasel.slnx— 0 warnings, 0 errorsWeasel.Core AOT smoke OK — exercised DbObjectName, ForeignKeyBase.Parse, TableBase, IDdlSyntaxStrategy.Weasel.Core6/6,Weasel.Postgresql634/640 (6 pre-existing skips),Weasel.Sqlite360/361 (1 pre-existing timezone-boundary flake),Weasel.Core.Tests6/6Weasel.EntityFrameworkCore.Testsshows 17 failures but these are pre-existing on baremaster(confirmed viagit stashtoggle) — require SQL Server connectivity not available locallyReferences #263, JasperFx/jasperfx#213.
🤖 Generated with Claude Code