[Bug] A Rust impl block reads as private although rust.scm says it inherits its target's visibility
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 52/100
Research direction
This spans packages/core/src/repowise/core/ingestion/queries/rust.scm and analyzer.py, with refinement behavior modeled by the fix in #2376. First confirm #2388 lands, then inspect the four impl_item query shapes and the existing Rust visibility refinement chain. Add fixtures for public and private targets across all shapes, plus the unused_export regression fixture; done means visibility is inherited without reporting impl blocks as unused exports.
Written by the indexing model from the issue text.
Description
Summary
rust.scm states that an impl block inherits its visibility from the type or trait it implements. It does not. No visibility is captured, the modifier text is empty, and every impl block in every Rust repository reads private, including the roughly 6,600 that implement a pub type.
Mechanism
The query captures the target type's name and nothing else, and says so in a comment that describes an inheritance that is never performed.
packages/core/src/repowise/core/ingestion/queries/rust.scm:71-76
; impl block — the "type" field identifies what is being implemented
; impl does NOT need visibility capture (inherits from type/trait)
(impl_item
type: (type_identifier) @symbol.name
) @symbol.def
The other three impl_item patterns at :77-95, covering generic, scoped and reference target types, capture no @symbol.modifiers either. With no modifier text, rust_visibility returns private, so the "inherits from type/trait" claim resolves to a constant.
This is the same shape as the trait-item defect fixed in #2376, where Rust forbids a visibility modifier on a trait item and rust_visibility therefore read private for every method of a pub trait. That fix added refine_rust_visibility, which reads the enclosing trait_item's own modifier and is wired into the existing cpp / csharp / ts refinement chain. It matches an exact node shape rather than walking ancestors, and it is the template here.
Evidence
Counted over the Rust corpus at the current commit:
| repo | impl symbols |
targeting a pub type |
|---|---|---|
| serde | 367 | 213 |
| ripgrep | 442 | 276 |
| rtk | 68 | 43 |
| goose | 811 | 622 |
| bevy | 6,468 | 5,493 |
All 8,156 read private. On the figures above, 6,647 should read public.
Impact
Visibility is wrong on a large symbol population, which matters anywhere visibility is read: the public-surface view, unused_export eligibility, and any published-API work.
This is blocked on #2388, and landing it first would cause a regression. _detect_unused_exports skips a symbol whose visibility is not public (analyzer.py:1201), and impl is in neither _UNIVERSAL_NON_IMPORTABLE (analyzer.py:257-269) nor _UNCALLABLE_TYPE_KINDS (analyzer.py:351-358). The private reading is the only thing keeping impl blocks out of that pass. Correct the visibility while impl is still a callable kind and roughly 6,600 symbols that nothing can ever call by name become eligible to be reported as unused exports. Land the exclusion first, then this.
Done looks like
An impl block carries the visibility of the type or trait it implements, matching what rust.scm:72 already claims, following #2376's refinement-function shape.
Keep this scoped to impl_item. Do not widen it to other node types whose visibility may also be wrong; each needs its own measurement.
Tests: fixtures asserting that an impl block on a pub type reads public and one on a private type reads private, across all four target shapes the query covers (plain, generic, scoped, reference); plus a regression fixture asserting no unused_export finding is produced for an impl block whose visibility now reads public.
Note for whoever picks this up: rust.scm has two open PRs against it (#2327, #2386), both scoped to type_use captures. They do not overlap with this, but a rebase may be needed.
- Dominant language
- Python
- Stars
- 6.7k
- Forks
- 711
- Avg merge
- 1d 13h
- Merged PRs (30d)
- 439
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from repowise-dev/repowise
-
bug help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
repowise-dev/repowise#2471 · 1 comment ·
-
bug help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
repowise-dev/repowise#2469 · 1 comment ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 86/100
repowise-dev/repowise#2379 ·
-
documentation good first issue
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
repowise-dev/repowise#2354 · 1 comment ·
-
documentation good first issue
Difficulty 1/5 Under an hour Newbie friendliness 92/100
repowise-dev/repowise#2353 ·
All issues in repowise-dev/repowise
Similar issues
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
bancolombia/sentinel#23 ·
-
test md OpenCI
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
-
integration:quickjs org:external priority:backlog topic:code-interpreter topic:middleware type:feature
Difficulty 2/5 1-3 hours Newbie friendliness 74/100
langchain-ai/deepagents#6450 ·
-
bug client
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100