feat: source-generate type descriptors; quarantine reflection for AOT (ADR 0006, #95) - #195
Merged
Merged
Conversation
Chris-Wolfgang
force-pushed
the
feat/sourcegen-descriptors
branch
2 times, most recently
from
August 2, 2026 23:20
7fca2c7 to
8d16c3f
Compare
Chris-Wolfgang
changed the base branch from
vNext
to
feat/bump-abstractions-0.20-testkit-0.13
August 2, 2026 23:20
… (ADR 0006, #95) Option B for the AOT-mapping gap the smoke surfaced (IL2070 in TypeMap's reflection). The generator now emits, per flat [BulkCopyable] type, a full GeneratedTypeDescriptor (schema/table/column metadata) mirroring TypeMap's rules; TypeMap.Create prefers it and builds the map reflection-free (delegates from the PR-B/C accessor registry). The reflection path is quarantined behind [RequiresUnreferencedCode] (+ netFx/netstandard polyfills) with a justified suppression on Create, so a [BulkCopyable] type's mapping no longer reflects over the type — clearing IL2070 under Native AOT. Guarded by a descriptor conformance test: the generated map equals the reflection map of a structurally-identical plain type across flat / enum / [Table]+[Column] / per-load-override cases. 273 unit tests green; all 5 TFMs build clean. Types with nested-table properties still use the reflection path (recursive nested descriptors are the next increment). Refs #95. Docs: ADR 0006. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ement 2) Closes the nested-table gap. The generator now emits a GeneratedNestedTableDescriptor per nested collection and includes it in the type descriptor — but only when the WHOLE graph is [BulkCopyable] (recursive IsFullyGeneratable eligibility check; cyclic or partly-unmarked graphs fall back to reflection, keeping AOT honest). TypeMap.BuildFromDescriptor resolves each child via Create (its own descriptor), and NestedTableMap gained a reflection-free ctor pulling the collection getter from the accessor registry — so a fully-marked graph maps with zero reflection. Conformance extended: generated nested tables (property, child table, child columns) match the reflection map of a plain twin graph. The AOT smoke now includes a nested [BulkCopyable] child, so the native run proves the nested descriptor path is IL2070-clean too. 275 unit tests green; all 5 TFMs build clean. Refs #95. Docs: ADR 0006. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Chris-Wolfgang
force-pushed
the
feat/sourcegen-descriptors
branch
from
August 3, 2026 01:53
8d16c3f to
c5fe6fc
Compare
Chris-Wolfgang
changed the base branch from
feat/bump-abstractions-0.20-testkit-0.13
to
vNext
August 3, 2026 01:53
Chris-Wolfgang
commented
Aug 5, 2026
Chris-Wolfgang
commented
Aug 5, 2026
Co-authored-by: Chris-Wolfgang <210299580+Chris-Wolfgang@users.noreply.github.com>
Address review feedback on BulkCopyAccessorGenerator.cs: the repeated IsStatic/IsIndexer/GetMethod-null(/[NotMapped]) or-chains are factored into intention-revealing predicates, mirroring TypeMap.IsReadableInstanceProperty on the reflection path so both providers filter identically: - IsReadableInstanceProperty — instance property with a getter - IsMappableProperty — readable + not [NotMapped] (was duplicated verbatim) - IsAccessorEmittableProperty — readable + non-ref-like + reachable getter Each of the four call sites collapses to one named line. Behaviour is unchanged (DescriptorConformanceTests: generated map == reflection map, 276 tests green). Also reflow the two .Add(string.Join(...)) blocks to the Allman multi-line argument style (opening paren on its own line) per review feedback. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Raise the four Option-B descriptor types to 100% line coverage so the per-module 90% gate passes at the vNext->main release: - ColumnMap: descriptor ctor throws when no generated getter is registered, and when an enum column type has no registered converter. - NestedTableMap: descriptor ctor throws when no generated getter is registered. - GeneratedAccessorRegistry.RegisterEnumConverter / GeneratedTypeMapRegistry.Register: ArgumentNullException guards. Adds TestModels/UnregisteredProbeEnum (never [BulkCopyable], never registered) to drive the enum-converter defensive branch. +7 tests (283 total, all green). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Merged
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.
Option B — fixes the IL2070 the AOT smoke surfaced. The generator emits full type descriptors for flat
[BulkCopyable]types soTypeMap.Createbuilds the map reflection-free; the reflection path is quarantined behind[RequiresUnreferencedCode](+ netFx/netstandard polyfills). Guarded by a descriptor conformance test (generated map == reflection map across flat/enum/[Table]+[Column]/override). 273 tests green, all 5 TFMs clean.Nested-table types still use reflection (recursive nested descriptors = next increment). The AOT Smoke check on this PR is the real verification that IL2070 is cleared.