Track what a primary module interface imports #29
No reviewers
Labels
No labels
bug
claude:blocked
claude:done
claude:failed
claude:in-progress
claude:ready
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
bug
duplicate
enhancement
help wanted
invalid
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
Catcrafts/Crafter.Build!29
Loading…
Reference in a new issue
No description provided.
Delete branch "claude/issue-26"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
What was wrong
A primary module interface unit —
export module Widget;, no partitions — recorded nothing about what it imported.GetInterfacesAndImplementationsregistered theModuleand then erased the file from the scan list, so the import-resolution pass only ever saw partition files, andModulehad no vectors to hold an edge anyway.Two consequences, both of them issue #26:
Module::Checkconsulted only its own.cppmand its partitions. A data member added to an imported module leftWidget.pcm,Widget.oand every consumer object untouched, while the imported library rebuilt and both binaries relinked. One executable, two class layouts, no diagnostic — and a crash far from the cause that stays reproducible until someone wipesbuild/.Module::Compilewaited on nothing. Two modules in oneConfigurationcompile on concurrent threads, so a primary interface importing a sibling was a coin flip between working andfatal error: module 'Base' not found.Partitions never had either problem — they carry the same three vectors and
Check/Compilehonour them — which is why the gap only surfaced on a module whose interface is one flat unit.tests/IncrementalInterfaceChangecovers the neighbouring consumer-side edge (#27); this is the edge one hop further up.Reproduction, before the fix
baseexportsPayload;widget's primary interface doesexport import Base;and embeds aPayloadby value; a test constructsThingon the stack. Adding 4 KiB toPayload:sizeof(Thing)=8is the old layout;first=1is the corruption — the library'sStamp()wrote at the new offset. Same shape as the issue'scrafter-build test 'ShouldSendRecieveHTTP1'log: interface rebuilt, library relinked, test relinked,main.cppnever compiled.After the fix the same edit produces
Compiling interface Widget,Compiling Widget.cpp,Compiling main.cppand a pass.The change
ModulegainsmoduleDependencies,externalModuleDependenciesandpendingImports, with the same meanings they already have onModulePartition.importlines land on those vectors. All primaries are registered before any import is resolved, so declaration order doesn't matter (a module may import a sibling declared after it).Module::Checksees through the new edges — recursively for a local sibling, by PCM mtime for a dependency's module.Module::Compileorders itself behind a local sibling it imports.ResolvePendingImportssweeps module-level pending names, so the edge survivescfg.dependenciesbeing assigned after the scan.Build()nowChecks every interface before spawning any compile thread. Thecompiledflag a waiter blocks on is raised either by aCompilethat runs or by theCheckthat decides none is needed, so aCheckstill pending while another module's thread was already waiting would have hung the build outright.needsRecompilinggets a default initializer (it was read-before-write on a dependency cycle).Verification
tests/TransitiveInterfaceChange: asserts the scan records a primary unit's imports and that pending/resolve reaches them; asserts a sibling import resolves locally even when declared first, and clean-builds four times over to pin the ordering; then end-to-end growsPayloadand asserts the importing interface unit, that module's implementation unit and the consumer's TU are all recompiled and the binary agrees on the layout. Against the unfixed library it reports 11 failed assertions.crafter-build test: 19 passed, including the pre-existing 18.crafter-build lint: clean, 42 files, 15 rules.Resolves #26
🤖 Generated with Claude Code