Skip to content

Fix proxy generator emitting different modules in Debug vs Release - #2548

Merged
einari merged 6 commits into
mainfrom
fix/source-file-resolver-debug-release-inconsistency
Aug 14, 2026
Merged

Fix proxy generator emitting different modules in Debug vs Release#2548
einari merged 6 commits into
mainfrom
fix/source-file-resolver-debug-release-inconsistency

Conversation

@einari

@einari einari commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Fixed

  • Fixed the TypeScript proxy generator producing a different module layout for the same C# source depending on whether the project was built Debug or Release — an enum declared in its own file could end up as its own module in one configuration and folded into a neighbouring module in the other, with whichever configuration was built last deleting the other's output from disk (Proxy generator emits different module layout in Debug and Release #2547)

einari added 3 commits August 14, 2026 14:11
SourceFileResolver mapped an enum (or other methodless type) to a
source file by checking whether every other resolved type in its
namespace pointed at exactly one file, and folding the enum into it
when so. Which sibling types resolve at all depends on PDB
sequence-point data emitted for that specific compilation, and that
can differ between a Debug and a Release build of the same source -
so the same C# layout could produce an enum as its own TypeScript
module in one configuration and folded into a neighbouring module in
the other, with whichever configuration built last deleting the
other's output.

Remove the sibling-namespace guess. A type without resolvable debug
information of its own is now always left unmapped, which means it
always gets its own output file - deterministic in every
configuration, and matching the source layout.
Adds a compiled fixture (an enum declared in its own file next to a
type with a real method, same namespace) so BuildTypeToSourceFileMap
can be exercised against a real PDB. Asserts the enum is never
resolved via a sibling guess while the type with its own debug
information still resolves correctly.
Debug carries the fullest, most reliably-emitted PDB debug
information the proxy generator relies on, and running it on Debug
first (then skipping regeneration on a Release-only compile check
with -p:CratisProxiesOutputPath=) avoids the generator re-running
against a different compilation. Updates every place in the AI
instruction corpus that pointed at Release as the proxy-generating
build.
@einari einari added the patch label Aug 14, 2026
einari added 3 commits August 14, 2026 14:22
The project inherited its TargetFramework(s) from the repo-wide
Directory.Build.props default, which only applies when neither
TargetFramework nor TargetFrameworks is already set. In CI, the
Release solution build (net8.0;net9.0;net10.0) referenced this
brand-new project before that inference had resolved it the same
way, and it came back single-targeted at net10.0 - which a net9.0/
net8.0 leg of the multi-targeted parent cannot reference. Declaring
the frameworks directly removes the dependency on that inference.
The Configuration-conditioned declaration from the previous commit
still resolved to a single net10.0 in CI: the cross-targeting
negotiation that a multi-targeted parent runs against this project
doesn't reliably see Configuration=Release during that specific
evaluation, so the Release branch never applied for a fresh reference.
Declaring net8.0;net9.0;net10.0 unconditionally sidesteps the
negotiation-time Configuration dependency altogether - a Debug parent
picks its one matching net10.0 leg, a Release parent finds all three.
Directory.Build.props's Configuration-conditioned default (imported
as part of Sdk.props, ahead of this project's own PropertyGroup) was
still winning: it only skips its own assignment when TargetFramework/
TargetFrameworks is already non-empty at that point, and my prior
attempt set TargetFrameworks too late in evaluation order to satisfy
that check during the ambiguous-Configuration negotiation. Switching
to the explicit long-form SDK import lets the property group ahead of
Sdk.props set TargetFrameworks before Directory.Build.props ever
looks at it, closing the gap for good regardless of what Configuration
resolves to during that negotiation.
@einari
einari merged commit bf3f5e8 into main Aug 14, 2026
56 checks passed
@einari
einari deleted the fix/source-file-resolver-debug-release-inconsistency branch August 14, 2026 12:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant