Skip to content

The shared source-walker blanks interpolated-string holes, so a call inside an interpolation is invisible to every scan built on it #2913

Description

@erikdarlingdata

Summary

StripCommentsAndStrings — copied into ViewerCommandTimeoutTests, ViewerFleetTimerGuardTests and the other source-walking pins — blanks the entire span of an interpolated string, including the {expr} holes. So a call written inside an interpolation is invisible to every scan built on it.

Raised by the review bot on #2910 and worth keeping: it produces no false negative today (nothing on the fleet-timer fan-out calls through an interpolation), so this is a latent gap, not a live defect.

// visible to the scan
var x = Foo();
// invisible: SkipRegularString consumes to the closing quote, holes included
Log($"count={Foo()}");

Why it is worth fixing rather than noting

It is the same category as the defect that bit #2910's pin during review, one shape further out. That pin claimed to reach a guard one level down; it did not, because RefreshAgAsync is => LoadAsync(); — a plain call in an expression body, matching neither call shape the walk looked for. The walk ran out of edges and reported the path safe without ever reaching the guard that makes it safe.

A pass for the wrong reason is worth less than a failure, and these pins exist precisely to convert an open question into a checked one. An interpolation hole is another way for an edge to go missing, and the failure direction is the dangerous one: a reachability scan under-reports, and an assertion that a count is zero (FetchStoreConnectionBorrowTests) is satisfied vacuously by an edge it cannot see.

Where it applies

StripCommentsAndStrings / SkipRegularString / SkipVerbatimString are duplicated across several test files rather than shared. The near-identical IlCallSiteScanner consolidation (#2898) is the precedent: five copies of an IL walk, two soundness problems, neither yet producing a wrong answer — fixed once, centrally, with the scanner carrying its own witnesses.

Worth checking whether the same treatment applies here, i.e. one shared source-walker with:

  • interpolation holes preserved as code, not blanked ($"...", $@"..." / @$"...", and raw string literals """...""", which the current skipper also does not know about);
  • nested braces inside a hole handled ($"{d[k]}", $"{(c ? a() : b())}");
  • {{ / }} escapes not mistaken for holes.

Proving it

Same rule as every other pin here: prove it red before green. A fixture whose only call to a guarded method sits inside an interpolation should make the walker report that call before the fix and after — and must be shown to report nothing with the current skipper, or the fixture is not testing what it claims. Do not rely on a real source file happening to have the shape; arrange it.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions