Skip to content

Dapper / DapperAOT parity tracking - #186

Merged
mgravell merged 42 commits into
mainfrom
parity-notes
Aug 19, 2026
Merged

Dapper / DapperAOT parity tracking#186
mgravell merged 42 commits into
mainfrom
parity-notes

Conversation

@mgravell

@mgravell mgravell commented Aug 18, 2026

Copy link
Copy Markdown
Member

Parity tracking for the Dapper → Dapper.AOT unification work: the gap table (impact/complexity per row), token semantics, Type-vs-generic API notes, the test-suite and generator audits, and the running harness baseline (round-by-round measurements against the Dapper test suite).

Landing this on main makes the table part of the review surface: from here, each feature PR flips its own cells, so the table and the merge history can't drift apart. Rows with an open PR say so (#195#200 currently); the flip to a settled status is that PR's job.

The goal on record: enable Dapper.AOT in the Dapper test suite, announce
types via attributes, and have it swallow everything - AOT-clean.

- parity.md: the feature table, with impact/complexity per gap (several
  'gaps' score zero because the concept doesn't exist under AOT, e.g.
  the ref-emit plan cache)
- tokens.md: @ids expansion, {=literal}, ?foo? pseudo-positional, param
  filtering
- type-vs-generic.md: the announced-types design space for Type-based APIs
- test-suite-audit.md: the Dapper tests as acceptance corpus, sequenced
With announced types it's the same dispatch map (boxed materializer), and
its generic strengthening already exists as GetRowParser<T>. The real hole
is the write side: CreateParamInfoGenerator has no generic counterpart -
recorded the GetParameterBinder<T> proposal, and the question of blessing
CommandFactory<T>/RowFactory<T> as the supported surface. ReadChar and
friends are plain AOT-safe statics, nothing to do.
PublicAPI.Shipped.txt is the checklist; the contract is what reaches the
provider and what comes back, never Dapper's internals. Cuts both ways:
the dynamic row needs behavioral fidelity only (the type is internal),
while the public infrastructure statics ARE in scope because extenders
call them.
Plan-cache surface, CommandFlags.NoCache, possibly ConnectionStringComparer:
supported-and-meaningless under AOT, which is a different statement to
DAP001's unsupported-but-meaningful. Warning, not error - the code runs.
Some failure modes are silent until executed - handled means intercepted,
not correct. Only the DB-backed test run catches silent divergence.
Two root-cause generator bugs (array-of-anonymous parameter emits the
display string and wrecks the parse; inaccessible row types are emitted
rather than refused), plus two scorecard honesty problems (the denominator
excludes unattempted APIs; handled does not mean compiles) and a zero-
analyzer-diagnostics anomaly to re-check once the compile is clean.
Both generators' cached SourceState hold IMethodSymbol/ITypeSymbol/
Location (MemberMap even holds an IOperation), and the pipeline combines
the raw CompilationProvider into the source output - so it behaves as a
full-recompute generator with a memory leak. Recorded as a sequencing
gate ahead of the gap-closing features, with the fix shape that worked
for protobuf-net (plain equatable model, span-based locations, separate
diagnostics branch, shape-enforcing test).
The line that resolves the phase-1/2 tension: nothing that adds
parse-time state lands before the model rework completes; refusals and
scorecard fixes are allowed ahead of it, which is what lets phase 1 see.
@mgravell
mgravell merged commit 86bc7b5 into main Aug 19, 2026
2 checks passed
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.

1 participant