fix: guard CFG002 constructor self-cycle hang and prep 0.7.22 release#107
Merged
Conversation
Fix an infinite-loop analyzer hang in the CFG002 constructor-overwrite proof. A public parameterless constructor with a zero-argument `: this()` initializer (a CS0516 self-cycle, but well-formed broken-compilation input) made TryResolveRuntimeConstructorEffect re-select the same constructor forever. The ThisConstructorInitializer branch now compares the resolved parameterless target against the current constructor and returns false (unprovable, so the satisfying default is conservatively rejected and the missing required key reported) instead of spinning. No valid compiling program is affected because self-delegating constructors are illegal. - TDD: RED regression hung pre-fix (confirmed via bounded timeout), passes post-fix; added a compiling parameterized-`:this()` guard and a CompilerDiagnostics.None verifier overload for the CS0516 repro. - CLAUDE.md: rule range corrected to CFG001-CFG009. - Untracked machine-specific tool artifacts (.mcp.json, .grok/, obsolete .pi/analyzer-health snapshots) and completed .gitignore; kept .plugin-config and .pi/extensions tracked. - Repaired the .pi analyzer-health extension: monitor-only on an empty shortlist (no fabricated lowest-score target), release tagging opt-in via --release; fixed the matching analyzer-health.md automation note. - Refreshed analyzer-health.md evidence (iteration 123, base commit 04fc74e). - Version bump 0.7.21 -> 0.7.22 (both csproj, PackageReleaseNotes, README, CHANGELOG, health-doc header). No new diagnostic ID or severity. Verification: 932 tests passed (682 analyzer + 250 core), CI-mode build 0 warnings/0 errors, format + git diff --check clean, codex review found no actionable defects.
Codecov Report✅ All modified and coverable lines are covered by tests. 📢 Thoughts on this report? Let us know! |
…erage Add a parameterized-`: this()`-with-no-parameterless-target regression (CS1729 broken code) that exercises the null-target fall-through in the ThisConstructorInitializer branch, completing coverage of the iteration-123 fix. Update analyzer-health.md test counts (683 analyzer + 250 core = 933) and regression-test lists to match.
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.
Summary
Fixes an infinite-loop analyzer hang in the
CFG002constructor-overwrite proof and bundles the codex-verified hygiene/release-prep work for the0.7.22release.The fix (headline)
OptionsTypeMetadata.TryResolveRuntimeConstructorEffectwalked the runtime constructor chain in an unguardedwhile (true). A public parameterless constructor with a zero-argument: this()initializer — aCS0516self-cycle, but well-formed broken-compilation input the analyzer must survive — re-selected the same parameterless constructor forever (theArguments.Count > 0guard skips zero arguments, an empty body classifies as a non-write, and theThisConstructorInitializerbranch looped with no visited set and no cancellation-token check). BecauseOptionsTypeMetadata.Createruns for every recognizedOptionsBuilder<T>registration before any appsettings gating, the shape hung the analyzer.The
ThisConstructorInitializerbranch now compares the resolved parameterless target against the current constructor (SymbolEqualityComparer.Default) and returnsfalse(unprovable → conservativeCFG002report) instead of spinning. No hot-path allocation; the base-chain walk stays monotonic; no valid compiling program is affected because self-delegating constructors are illegal.Cfg002_reports_required_with_satisfying_initializer_when_parameterless_constructor_chains_to_itselfhung pre-fix (confirmed via a bounded 60s timeout) and passes in ~1s post-fix; plus a compiling parameterized-:this()-to-parameterless guard and a parameterized-:this()-with-no-parameterless-target regression covering the null-target fall-through. Added aCompilerDiagnostics.Noneverifier overload because the repros areCS0516/CS1729.Hygiene (codex-verified)
CLAUDE.md: rule range correctedCFG001–CFG007→CFG001–CFG009..mcp.json,.grok/, obsolete.pi/analyzer-health/snapshots) and ignored them plus.claude/settings.local.json,.superpowers/. Kept.plugin-config/(portable) and.pi/extensions/(project tooling) tracked..pianalyzer-health extension:selectHighestPriorityWorkreturnsundefinedon an empty shortlist (no more fabricating the lowest-scored Health Baseline rule), the iterate handler stops with a monitor-only notice, and release tagging is now opt-in via--release. Fixed the matchinganalyzer-health.mdline-38 automation contradiction.analyzer-health.mdevidence block (iteration-123 row, CFG002 Rule Notes, base commit advanced to04fc74e).Release prep
0.7.21→0.7.22across both.csproj(incl.PackageReleaseNotes), README install snippet, CHANGELOG, and the health-doc header.AnalyzerReleases.Unshipped.mdunchanged (no new diagnostic ID or severity).Verification
ContinuousIntegrationBuild=true): 0 warnings / 0 errors.dotnet format --verify-no-changes: clean ·git diff --check: clean.codex review --uncommitted: no actionable defects.