Resolve 21,881 Rust callsites in the Linux kernel. - #81
Merged
rikvanriel merged 5 commits intoAug 28, 2026
Merged
Conversation
Every Rust dispatch site in the kernel was untyped: 18,011 of them, against 19,679 typed out of 56,140 in C. Not a hard residue — the pass that types a receiver reads `function_definition`, `declaration` and `parameter_declaration`, which are C grammar, so on a Rust tree it matched nothing and every site fell through untyped. Rust states what C leaves to a header: parameters and annotated bindings carry their type in the source, and `self` is whatever the enclosing `impl` names. Read those. 7,459 of 18,011 sites now carry a receiver type, and the commonest untyped receiver, `self` at 1,345 sites, is among them. A reference is stripped, since `&T` reaches T's methods by autoderef. A raw pointer is not: `(*mut request).cast()` is a method of the pointer, and typing that receiver as `request` claims a member the struct has not got. Keeping raw pointers out drops 129 such claims. An inferred binding still states nothing, and `Arc<TagSet>` is recorded as `Arc`, so a call reaching through it does not join yet. Assisted-by: claw:claude-opus-5 Signed-off-by: Rik van Riel <[email protected]>
A call through `Arc<TagSet>` dispatches on TagSet, by Deref, so recording the
receiver as `Arc` files the site under a type that has no such member and it
joins with nothing. 96 sites were typed that way.
Unwrap the pointers that deref to their argument. `Vec<Request>` is not one of
them: `.len()` is a method Vec has itself, and unwrapping would file it under
Request.
rust sites still typed as a smart pointer: 96 -> 0
Three sites stop being typed at all, all `Arc<dyn Trait>`: the held type is a
trait object, and naming the wrapper was never an answer.
Assisted-by: claw:claude-opus-5
Signed-off-by: Rik van Riel <[email protected]>
`arm_delay_ops.delay(n)` is written in a header whose variable is declared
`extern` in that same header and defined in another file, so the analyzer sees
a plain name it cannot type and `callers __loop_delay` reported nothing. 3,631
C dispatch sites are shaped like this, most of them arch and driver ops tables.
Record file-scope variables of aggregate type and use them to type a receiver
that is a plain name, once the whole tree is available:
(semcode) callers __loop_delay
=== Indirect Callers ===
1 call sites can reach it through a function pointer:
1. __delay at arch/arm/include/asm/delay.h:58 [member_dot]
installed in arm_delay_ops::delay at arch/arm/lib/delay.c:20 (receiver type matches)
237,629 declarations over 164,549 names. Of 7,748 untyped plain-name sites,
2,177 get a type and 732 land on a slot that has something installed in it;
the rest name a variable of a type nothing is installed in, which is an
answer.
A name declared with two different aggregates at one revision is left alone.
Filing a site under the wrong type joins it with the wrong registrations,
which is worse than saying the type is unknown.
Assisted-by: claw:claude-opus-5
Signed-off-by: Rik van Riel <[email protected]>
None of the 1,169 Rust types in the kernel recorded a single member. The parser handles C's field declarations and Zig's container fields; Rust's `field_declaration_list` fell through to a string fallback that found nothing. Without members, a chain like `self.inner.write()` has nothing to walk, so the receiver cannot be typed however well the base is known. Read them. 613 of the 1,169 now carry fields; the rest are unit structs, tuple structs and enums, which have no named members. A member's type is reduced to the aggregate it names, the same reduction a receiver's type gets, so the two can be compared when the chain is walked. C names its struct body `field_declaration_list` as well, and its fields carry a declarator rather than a name, so the branch is taken only for Rust. Assisted-by: claw:claude-opus-5 Signed-off-by: Rik van Riel <[email protected]>
A receiver written as `self.inner.write()` was left untyped: the pass handled
a plain name and gave up on anything with a field in it, so 5,400 sites went
unrecorded where C records the base type and the path for exactly this shape.
Record them the same way. 2,918 Rust sites now carry a base and a path, and
1,191 of those walk to a type against the types table:
Falcon.bar : Bar0 -> .write()
which is `bar: Bar0<'a>` at drivers/gpu/nova-core/falcon.rs:360.
The remainder name a type the tree does not define, mostly core and crate
types, and stop at the first field that is not indexed rather than guessing.
Assisted-by: claw:claude-opus-5
Signed-off-by: Rik van Riel <[email protected]>
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.
Resolve 21,881 Rust callsites in the Linux kernel.
f851438 record the base and the field path of a Rust receiver
ba5a825 index the fields of a Rust struct
7a6a829 type a receiver that names a variable declared elsewhere
7998c56 see through a smart pointer to the type it holds
ac3b79e type a Rust dispatch receiver from its declaration