Skip to content

fix(cargo-gamma): complete cfg-tail and dashboard timing follow-ups - #356

Closed
Martin Taillefer (geeknoid) wants to merge 1 commit into
mainfrom
pr-follow-up
Closed

Martin Taillefer (geeknoid) wants to merge 1 commit into
mainfrom
pr-follow-up

Conversation

@geeknoid

@geeknoid Martin Taillefer (geeknoid) commented Nov 9, 2026 •

Copy link
Copy Markdown
Member

Summary

Addresses the three review conversations deferred from #352:

  • Nested cfg-active tail analysis: share cfg-aware statement selection across nested expected-type, inferred-type, numeric, and divergence analysis, preserving active items and semicolon barriers.
  • Dashboard clock injection: use one injected clock for lifecycle timing, redraw throttling, rendering, and throughput.
  • Process-reader constants: name and document the existing buffer size and polling interval without changing behavior.

Review follow-ups preserve declaration-scoped type evidence across calls, imports, fields, operators, constructor payloads, and reusable result payloads. The design contract is synchronized.

Latest correction: alias constructors and frozen operands

Reproduced all three new reports before changing production:

  • Omitted generic constructor aliases retained unmatched parameters instead of using the payload type. Constructor inference now recognizes omitted generic-alias arguments before freezing the owner and inserts the already-frozen payload evidence afterward. Regressions cover direct and composite payloads; concrete aliases and explicitly supplied arguments retain their declared types, including numeric arguments whose literal type is otherwise unavailable.
  • Standard operator classification reinterpreted frozen operands through caller imports. It now uses caller-independent frozen evidence, matching method inference. A declared String result plus a string literal cannot gain an invalid subtraction candidate when a caller rebinds std through an extern alias, self alias, or named import.
  • Parenthesized generic aliases bypassed source-argument normalization before canonical substitution. Alias preparation now clones the stripped type. The existing alias-argument regression covers both standard roots and unparenthesized, parenthesized, and doubly parenthesized forms.

The two new tests and expanded alias regression failed against the preceding production code and pass with the fixes. Supported originals compile with rustc under both core and std root-collision configurations.

Earlier provenance corrections

  • Genuine external imports retain a separate namespace marker through named imports. Source self aliases normalize before expansion; canonical declarations and frozen arguments are not reinterpreted as source paths. Relative child-module self aliases respect genuine extern bindings and named lexical overrides.
  • Source-absolute primitive and prelude recognition validates crate-root provenance. Literal primitive output selection also requires a trusted root. Local lookalikes cannot acquire standard identity through nested extern bindings; existing foreign-root rejection remains intact.
  • Frozen external methods, fields, and operator owners/RHS types do not consult same-named local inventories. Indexed constants and statics preserve frozen declaration evidence through direct/named imports, parentheses, and reference dereferences.
  • Composite, branch, resource, constructor rendering, method-origin, generic-isolation, shadowing, slice/pointer alias, and frozen-payload regressions remain included. Compatible core/std primitive identities compare consistently without changing inferred output roots.

Mutation regressions

The 1ca58f8d Windows campaign reported 1,210 mutants: 1,202 killed, eight survived, zero uncovered (job 129782715628).

Six effects targeted redundant local-root clauses; those clauses are removed rather than excluded. The constructor and primitive-length effects were individually injected and failed their executed regressions. Exact production bytes were restored, and the restored suites pass. A further isolated proof confirms the relative source-alias regression detects bypassing its normalization.

Earlier campaign follow-ups remain included: 14 individually detected effects from the 17-survivor de41011e campaign, deletion of the redundant constructor-inventory guard from the one-survivor e54bfa97 campaign, and five individually detected effects from 5f854b23. The earlier 99bd40fd head killed all 1,113 mutants. Existing exactly equivalent exclusions remain narrowly documented.

Fresh CI must confirm the new head. No standalone local mutation campaign or Miri run was performed.

Local validation

  • 2,020 engine tests passed on both the current toolchain and Rust 1.97.1.
  • 3,497 library tests passed (three ignored), along with seven discovery tests, all 19 mutation-correctness integration tests, and 28 regression tests.
  • Generated just anvil-fmt --fix, workspace just anvil-clippy, and git diff --check passed.
  • Both feature configurations passed the unchanged 99.4% engine coverage gate.

Copilot AI balanced review requested due to automatic review settings November 9, 2026 16:57

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The non-unit-arm check includes cfg-disabled match arms, which can incorrectly mark an active unit-returning call as undeletable and suppress a valid deletion candidate.

1 open issue
What changed in this PR

This PR follows up on #352 by extending cargo-gamma’s cfg-aware tail analysis, making dashboard timing controllable, and documenting process-reader constants.

Changes:

  • Share cfg-active statement selection across nested type, numeric, and divergence analysis, with regressions and design updates.
  • Inject one dashboard clock for lifecycle timing, redraws, rendering, and throughput.
  • Name the existing read-buffer size and polling interval without changing behavior.
File Description
crates/​cargo-gamma/​docs/​DESIGN.md Document nested cfg-active tail behavior.
crates/​cargo-gamma-process/​src/​process_tree.rs Name and document reader constants.
crates/​cargo-gamma-lib/​src/​commands/​run.rs Supply clocks when constructing dashboards.
crates/​cargo-gamma-lib/​src/​commands/​dashboard.rs Unify timing under an injected clock and add controlled-clock tests.
crates/​cargo-gamma-lib/​src/​commands/​console_events.rs Adapt dashboard tests to clock injection.
crates/​cargo-gamma-engine/​src/​ops/​collect/​collector/​tests.rs Add nested cfg-tail and barrier regressions.
crates/​cargo-gamma-engine/​src/​ops/​collect/​collector/​survivor_tests.rs Pass cfg context into existing regression helpers.
crates/​cargo-gamma-engine/​src/​ops/​collect/​collector/​predicates.rs Share active-statement filtering and apply it to divergence analysis.
crates/​cargo-gamma-engine/​src/​ops/​collect/​collector.rs Propagate cfg-aware selection through nested tail analysis.
crates/​cargo-gamma-engine/​docs/​DESIGN.md Specify recursive tail selection and preserved barriers.

Review effort: Balanced

@codecov-commenter

Codecov Comments Bot (codecov-commenter) commented Nov 9, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 99.03692% with 12 lines in your changes missing coverage. Please review.
✅ Project coverage is 99.2%. Comparing base (95fa400) to head (a675d23).
⚠️ Report is 1 commits behind head on main.

Files with missing lines Patch % Lines
...es/cargo-gamma-engine/src/ops/collect/collector.rs 98.9% 5 Missing ⚠️
...go-gamma-engine/src/ops/collect/collector/types.rs 97.9% 5 Missing ⚠️
...go-gamma-engine/src/ops/collect/collector/calls.rs 99.2% 2 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff            @@
##            main    #356      +/-   ##
========================================
- Coverage   99.5%   99.2%    -0.3%     
========================================
  Files        351     179     -172     
  Lines      64328   41244   -23084     
========================================
- Hits       64029   40949   -23080     
+ Misses       299     295       -4     
Flag Coverage Δ
linux 99.2% <99.0%> (-0.3%) ⬇️
linux-arm 99.2% <99.0%> (-0.3%) ⬇️
scheduled ?
windows 99.2% <99.0%> (-0.3%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copilot AI balanced review requested due to automatic review settings November 9, 2026 17:10
@geeknoid

Copy link
Copy Markdown
Member Author

The original Windows Fast Checks failure occurred in the cargo-binstall installation step: its download connection closed unexpectedly, before the Anvil checks started (job 129309191394). No workflow change is needed for that infrastructure failure. The amended head ae98a54 triggers a fresh CI run, which I will continue monitoring.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Cfg-disabled nested match arms still affect branch-type inference, incorrectly suppressing valid stmt.delete_call candidates in active outer siblings.

1 open issue
1 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Labeled-block handling suppresses valid numeric return mutations, while substring-based dashboard assertions can pass with incorrect throughput values.

2 open issues
1 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Block inference resolves a shadowed local to an outer parameter’s type, incorrectly suppressing a valid stmt.delete_call candidate in another match arm.

1 open issue
2 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Match-arm type inference mishandles binding scope and known callee return types, suppressing a valid deletion while allowing a continue deletion that changes a value-required arm to unit.

2 open issues
1 resolved since last review

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings November 9, 2026 18:16
@geeknoid

Copy link
Copy Markdown
Member Author

The current-head Anvil workflow failed before its check groups started with GitHub reporting: Internal server error (correlation ID 94f421c5-9b62-48b9-a882-17e680f577bc). The successful impact-analysis job was the only executed job; there is no code-check failure log to fix. I retried Anvil (42672649154), regenerate-check (42672648997), and Windows coverage diagnostics (42672648567), the latter two having failed before creating jobs. No source or workflow changes were made. GitHub rejected retrying the separate Copilot review run (42674029533) with This workflow run cannot be retried. Monitoring the CI retries and ADO build continues.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot AI balanced review requested due to automatic review settings November 10, 2026 04:04

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved type-freezing and import-resolution bugs can admit invalid replacements, suppress valid ones, and erase evidence that protects a continue statement from removal.

3 open issues
3 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical type-identity and path-resolution bugs can erase constructor payload types or resolve frozen standard-library types to caller-local lookalikes, allowing incompatible operator mutations and incorrect replacements.

3 open issues
3 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical alias-handling defects create malformed wrapper-constructor types and omit required dereferences in extern-self field rewrites.

2 open issues
3 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The interacting inference, provenance, type-identity, and operator-compatibility changes warrant human review alongside the requested fresh mutation-CI results before approval.

No open issues 🎉

2 resolved since last review

Review effort: Balanced

@sgalkin

Copy link
Copy Markdown
Contributor

Reviewed head 99bd40fd04c02a255646e63137d3f8c0916695a5. The previous three concerns are addressed in source. Two nonblocking correctness issues and one documentation correction remain:

Field-backed method chains lose the output's declaration context

Could indexed_method_scope handle field receivers, as full method inference already does? For example:

struct Maker;
impl Maker {
    fn unwrap(self) -> Option<&'static bool> { Some(&true) }
}
mod caller {
    extern crate self as std;
    struct Holder { maker: crate::Maker }
    fn f(h: Holder) -> bool {
        !h.maker.unwrap().unwrap()
    }
}

The inner method's frozen output retains its declaration's genuine standard Option, but origin lookup misses the field receiver and falls back to the caller's rebound std environment. The outer payload extraction loses known borrowed-boolean evidence, so unary removal emits the plain operand instead of *(h.maker.unwrap().unwrap()). The existing direct-field and simple chained-method regressions cover these boundaries separately, not this composition.

A lexical generic disables the frozen-field progress proof

Could the generic-root rejection apply only to paths without a leading ::, as in Types::has_generic_root? Adding an otherwise unused caller generic named std to the field-backed character-scan fixture rejects its frozen ::std::vec::Vec<char> evidence:

struct Owner { characters: Vec<char> }
fn f<std>(owner: &Owner, mut index: usize, end: usize) {
    while index < end && owner.characters[index] == 'x' {
        index += 1;
    }
}

That removes the projected VecChar binding and admits deletion of the scan's sole index increment. For characters = ['x'], index = 0, and end = 1, the condition then remains true indefinitely. Extending the existing field-scan regression with this generic would cover the new freezing boundary without adding another inference mechanism.

Qualify the earlier negation contract

Could the earlier design paragraph distinguish unavailable inference from present-but-incomplete evidence? "Each negation site emits one replacement" is no longer unconditional: incomplete inferred evidence deliberately emits nothing, as the later design paragraph correctly states.

These are source-analysis findings; no builds or tests were run for this review. All three are nonblocking suggestions.

🤖 Authored by Copilot.

@geeknoid

Copy link
Copy Markdown
Member Author

Addressed all three points from the follow-up review in c91af69.

  • Both correctness reports reproduced before production edits. Field-backed method-origin lookup now uses existing full receiver inference and selects the indexed output declaration context. Bare/parenthesized fields and both unwrap/build method names retain the required dereference through the outer extraction.
  • Generic-root rejection now applies only to relative paths. Field character-scan regressions cover abstract and Default-bounded std generics; separate controls retain relative generic and enclosing-alias shadowing.
  • The earlier design paragraph now states at most one negation replacement, distinguishing unavailable inference from present-but-incomplete evidence.

Representative originals compile with rustc. All 1,990 engine tests pass on stable and Rust 1.97.1, affected library/integration suites pass, generated formatting/Clippy are clean, and both coverage configurations meet the unchanged 99.4% gate. The preceding head killed all 1,113 mutants; fresh CI is running for this amendment. No standalone local mutation campaign or Miri run was performed.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Type-identity and import-shadowing defects can admit Add/Sub mutations with incompatible return types and omit required dereferences in generated output.

2 open issues

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Directly declared struct constructors are not registered as value shadows, allowing an enclosing constant’s type to cause an incorrect rewrite of !X to *(X).

1 open issue
2 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Inconsistent crate-root alias normalization inside generic types can prevent matching the declared Add operator, allowing add-to-sub candidates even when Add and Sub return incompatible types.

1 open issue
1 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Generated constructor replacements lose the leading :: and can resolve to shadowing local modules, while incomplete slice and pointer alias normalization incorrectly suppresses valid operator mutations.

3 open issues

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Primitive normalization misresolves absolute crate-root paths under nested extern rebinding, causing unary.remove_not to emit a replacement with the wrong value type.

1 open issue
3 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved absolute self-alias import handling can bypass arithmetic output-compatibility checks and produce incorrect unary mutations by losing constant type information.

3 open issues

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

A critical provenance-loss bug conflates genuine external types with local types, allowing an incompatible arithmetic replacement when crate aliases collide.

1 open issue
3 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved core root-collision bugs corrupt type provenance, causing valid mutation candidates to be omitted and incorrect replacements to be generated.

3 open issues
1 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical path-provenance errors misidentify local core/std aliases as standard primitive or prelude types, allowing incompatible replacements.

2 open issues
3 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Critical alias-inference and caller-root rebinding bugs misidentify operand types, causing operator lookup to miss matching implementations and admit incompatible mutations.

3 open issues
2 resolved since last review

Review effort: Balanced

Apply cfg-active tail selection consistently through nested expected-type,
block-inference, numeric, and divergence analysis, preserving active tail
barriers and covering the deferred cases with focused regressions.

Inject a shared dashboard clock for lifecycle timing, redraw throttling,
and throughput measurements. Name and document the process-reader chunk
size and polling interval without changing behavior.

Preserve declaration-scoped type evidence through indexed values, calls,
fields, operators, aliases, and constructor payloads. Keep genuine external
namespaces separate from source self aliases, and retain frozen identities
when crossing caller scopes. Select primitive output roots using lexical
and crate-root provenance instead of accepting local lookalikes.

Cover demonstrated review regressions and campaign survivors with focused
candidate controls, remove redundant equivalent branches, and synchronize
the engine design contract.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot-Session: 20685d26-9888-4c4d-a75f-e85c49d00b4e

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

Unresolved crate-alias resolution errors can misidentify external types and lose borrowed-boolean or iterator type evidence, causing incorrect replacements or suppressing valid rewrites.

3 open issues
3 resolved since last review

Review effort: Balanced

// #[gamma::skip(return_value.default, reason = "None is already Option::default(); replacing just this value cannot change an outcome.", tag = "equivalent")]
None;
}
"crate".clone_into(&mut names[0]);
Comment on lines +457 to +459
if let Some(imported) = imports.get(root) {
let _old = names.splice(..1, imported.as_ref()?.iter().cloned());
}
Comment on lines +722 to +723
let root = roots.iter().find(|root| self.standard_external_root(root))?;
Some(vec![(*root).into(), module.into(), name.clone()])
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.

7 participants