Skip to content

fix(bind): super reaches the base class; Rust variants and paths; Go literal receivers - #35

Merged
maxgfr merged 3 commits into
mainfrom
fix-binding-regressions
Oct 12, 2026
Merged

maxgfr merged 3 commits into
mainfrom
fix-binding-regressions

Conversation

@maxgfr

@maxgfr maxgfr commented Oct 12, 2026

Copy link
Copy Markdown
Owner

Why

We re-ran the large-repository evaluation on the released 2.31.8 (vite, TypeScript's Go port, django, terraform, ripgrep) and compared it with 2.31.5. The five 2.31.8 fixes held, and 24–32% more call sites were bound at no cost in speed. It also found one regression introduced by 2.31.8 and three binding errors that the larger call cap made more visible. An audit of the fix then found three more cases, which are fixed here as well.

Fixes

Before After
JS/TS super.f() lost its binding in 2.31.8: 7 sites in vite, 138 in TypeScript. Before that, inside an override, it bound to the override itself. super (JS/TS/Java super.f(), Python super().f()) reads as the enclosing class's base, taken from the file's extends relations. The lookup walks up the base chain the file declares (vite PluginContext → MinimalPluginContext → BasicMinimalPluginContext.warn). On django, 113 super() calls move from unrelated classes to their real base, e.g. super().to_python(): IntConverter → Field.
Rust super::check() in mod tests, called from a helper also named check, bound nothing. Nested inline mods were not handled. Inside an inline mod, super:: names the items of the enclosing scope: the file's top level, or the outer block.
Rust std Ok(…)/Some(…) bound to local enum variants: 525 + 466 wrong sites in ripgrep, from other crates too. A bare call reaches a variant only in its enum's own file, through a use of the enum. For Ok, Err, Some and None, the use must name the variant itself, because the index does not scope a use to its function. E::Ok(…) still binds.
Go addrs.Check{…}.Absolute() bound to an unrelated Absolute: its receiver was read from inside the literal. The receiver is the literal's type, so the call binds to Check.Absolute, InputVariable.Absolute and so on.

EXTRACTOR_VERSION 17 → 18, so 2.31.8's cached Go records re-extract once.

Validation

  • Whole caller indexes compared with 2.31.5:
    • vite: 0 sites lost.
    • terraform: 1 site lost, which now binds to the correct method.
    • ripgrep: only the variant sites are removed.
    • django: the 113 "lost" sites are all super() calls re-bound to their real base.
    • TypeScript: the 67 sites lost are super uses in compiler fixtures (object literals, mixins, a class with no base) that cannot be resolved statically.
  • pnpm typecheck, pnpm test (2,222 tests), pnpm check:build, pnpm test:e2e (98) and pnpm quality:report pass; the quality report is unchanged. The e2e command matrix passes on all 19 pinned repos (1,140 checks).
  • deadcode on the TypeScript repo: same time as 2.31.8, slightly less memory.

…o literals

Re-running the evaluation on 2.31.8 (vite, TypeScript's Go port, django,
terraform, ripgrep) against 2.31.5 found one regression and three binding
errors the larger call cap made more visible:

- JS/TS `super.f()` lost its binding (7 sites in vite, 138 in TypeScript):
  the Rust `crate`/`super` path receiver was read in every grammar. It is
  now read on Rust's scoped_identifier only.
- Rust `super::check(...)` inside `mod tests` from a helper also named
  `check` tied two candidates and bound nothing; inside an inline mod,
  `super::` now reaches only the items outside the block.
- Rust's prelude `Ok(...)`/`Some(...)` bound to local enum variants
  (`ParseResult::Ok`: 525 wrong sites in ripgrep, from other crates too).
  A bare call reaches a variant only in its enum's own file when that file
  imports the variants (`use self::E::*`); `E::Ok(...)` still binds.
- Go `addrs.Check{...}.Absolute()` read its receiver from inside the
  literal and bound to an unrelated `Absolute`; the receiver is now the
  literal's type, so it binds to `Check.Absolute`.

Against 2.31.8 on ripgrep, this changes only the variant sites (removed)
and the inline `super::check` (gained). Against 2.31.5, vite loses no
call site it found, TypeScript and terraform one each.
…variants

Found by the audit of the previous commit.

- `super.f()` read as a bare call bound an override's `super.render()` to
  the override itself. `super` (JS/TS/Java `super.f()`, Python
  `super().f()`) now reads as the enclosing class's base, from the file's
  `extends` relations: a base declared in the file is searched up its own
  chain (vite's PluginContext -> MinimalPluginContext ->
  BasicMinimalPluginContext.warn), one declared elsewhere is the type to
  prefer. The class is found by span when the call sits in a function
  nested in a method. On django, 113 `super()` calls move from unrelated
  classes (`super().to_python()` -> IntConverter) to their real base
  (Field); on TypeScript, self-calls and fixtures' invalid `super` uses
  stop binding.
- `super::` in a nested inline mod names the enclosing block's items, not
  the file's top level.
- A `use` in a fn body is not scoped in the index, so a glob import there
  made every std `Ok(…)` of the enum's file bind to `E::Ok`: the prelude's
  names (Ok, Err, Some, None) now reach a variant only when imported by
  name. Other variants still come into scope through the glob.
Records cached by 2.31.8 hold the old receiver of T{…}.M() calls; a version bump makes indexes re-extract them once.
@maxgfr
maxgfr merged commit 6dfe9f8 into main Oct 12, 2026
2 checks passed
github-actions Bot pushed a commit that referenced this pull request Oct 12, 2026
## [2.31.9](v2.31.8...v2.31.9) (2026-10-12)

### Bug Fixes

* **bind:** super reaches the base class; Rust variants and paths; Go literal receivers ([#35](#35)) ([6dfe9f8](6dfe9f8))
@github-actions

Copy link
Copy Markdown
Contributor

🎉 This PR is included in version 2.31.9 🎉

The release is available on:

Your semantic-release bot 📦🚀

@maxgfr
maxgfr deleted the fix-binding-regressions branch October 12, 2026 11:25
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