Rust extractor: lossy structure and name-only call resolution (generic impls, traits, mods, use-lists, receivers)
I maintainer di solito rispondono entro 1 giorno
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 5/5
- Tempo stimato
- Più di una settimana
- Idoneità per principianti
- 18/100
Direzione di ricerca
Start in graphify/extract.py at extract_rust, plus _make_id, _file_stem and the label_to_nid lookup in extract(), and reproduce with the sample file in the issue. The author has a patch and 10 regression tests, so the work is mostly reviewing the design: scoped IDs, trait impls, receiver-based call resolution and cross-file resolution. Done means the sample's orphan nodes, merged IDs and name-only edges are gone, and the regression tests pass.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Version: graphifyy 0.7.0 (graphify/extract.py, extract_rust)
extract_rust loses most of the structure of idiomatic Rust. Reproduced with this file:
use std::fmt::{self, Display};
pub trait Reader { fn read(&self) -> u8; fn skip(&self) { helper(); } }
pub struct Foo<T> { x: T }
impl<T> Foo<T> { pub fn new(x: T) -> Self { Self { x } } pub fn go(&self) { Self::new(1); helper(); } }
impl Display for Foo<u8> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { Ok(()) } }
impl Reader for Foo<u8> { fn read(&self) -> u8 { 0 } }
mod inner { pub fn helper() {} pub struct Foo; }
pub fn helper() { inner::helper(); println!("x"); }
pub type Alias = u8; pub const K: u8 = 1; macro_rules! m { () => {} }
Structure problems
- Generic impls create orphan nodes.
impl<T> Foo<T>/impl Foo<u8>produce nodesFoo<T>/Foo<u8>, separate from theFoostruct node. Methods hang off the orphans. - Trait is dropped from
impl Trait for Type. Noimplementsedge; trait impls look like inherent impls, and several impls of the same method name for one type (e.g. threeimpl From<_> for E) share one ID scheme. trait_itemreturns without descending. Trait methods produce no nodes, so calls from default method bodies (skip -> helper) are lost.- IDs ignore the inline
modpath, and are case-folded.inner::helperand top-levelhelperget the same ID, as doinner::FooandFoo; nodes merge andinner::helper()becomes a dropped self-call. Because_make_idlower-cases,const ITEMandfn item()also collide (first label wins). Across files,_file_stemisparent.stem, so everysrc/lib.rssharessrc.lib. - Missing node kinds:
mod,type,const,static,union,macro_rules!. usehandling is lossy:use std::fmt::{self, Display}yields one edge (the text before{), losingDisplay; nested/aliased lists are not flattened.
Call-resolution problems
The extractor resolves calls by bare name only (label_to_nid[name.lower()], last definition wins), ignoring qualifiers and receivers, so on a real workspace most edges for common names are wrong. Examples found by auditing the old output line by line:
Vec::new(),Cursor::new(..),HashMap::new(),u64::from(x),Default::default()are linked to any localfn new/fn from/fn default.v.len()/s.is_empty()/file.seek(..)on std types are linked to local methods with the same name.Value::Inline(..)/VrIndex(..)(enum variant / tuple-struct constructors) are linked to a function namedinline/ the type node.validator.enter_item(..)is linked to an unrelated freefn enter_item, not the method onvalidator's type.- Conversely, true calls are missed:
self.m()when several types in the file definem,Type::f()whenTypehas several impls, trait-qualified calls (Seek::seek(&mut s)), calls through generic bounds (V: Trait),if let Some(x) = x, loop/closure variables, and everything crossing a file boundary other than by unique name.
Patch
I have a patch (extract_rust replacement + a small Rust pass in extract() for cross-file resolution) and 10 regression tests. Happy to open a PR. Summary of the behaviour:
- IDs scoped by file path +
modpath and tagged by kind; generics stripped soimpl<T> Foo<T>attaches toFoo;implementsedges (also cross-file); trait methods as nodes; nodes for mod/type/const/static/macro; use-trees flattened. - Calls resolved with light receiver-type inference (parameters, typed/constructor
let, struct field types,Self, fn/method return types withResult/Option/Box/Arcunwrapped,if let Some(x), generic bounds,for/closure element types overVec/slice/array). When a call can reach several impls, an edge goes to each candidate withINFERREDconfidence. Calls on external types (Vec::new,u64::from, ...) and enum-variant/tuple-struct constructors produce no edge. Typed calls whose type lives in another file are resolved in a cross-file pass.
Measured on a real workspace
179 .rs files (a DICOM parser; calls counted over the whole graph, incl. cross-file), old extractor vs patched:
| old | patched | |
|---|---|---|
| nodes (in-file extraction) | 2658 | 5782+ |
calls edges |
3544 | 4607 (2482 EXTRACTED, 2125 INFERRED) |
The 134 old call edges that disappear were classified by source line: 68 Type::f() on external types, 43 enum-variant/tuple-struct constructors and chains on external types, 23 recv.f() on std types (len/is_empty/seek/read) — plus 4 validator.enter_* calls that used to point at the wrong free function and now point at the method. None was a Type::f() call on a type defined in the workspace.
Remaining limit
Where the type is only known to a real type checker (results of .map(..) / .collect(), macro-generated code), no edge is emitted rather than a guessed one.
- Lingua principale
- Python
- Stelle
- 124k
- Fork
- 11.9k
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Preparare l'ambiente
Questo progetto non fornisce container di sviluppo, Dockerfile né guida per i contributori, quindi l'ambiente è a tuo carico: parti dal suo README e consulta la nostra guida al primo contributo per i passaggi generali.
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di Graphify-Labs/graphify
-
[Bug] Pi skill uses unsupported general-purpose subagent instead of delegateForse già presa @bercedev l’ha presa oggi. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
Graphify-Labs/graphify#4494 · 5 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
ID collision: a node with no source_file beats a sourced node with the same id (dedup._collision_rank)Forse di nuovo libera Una pull request per questa issue è stata chiusa senza essere unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 70/100
Graphify-Labs/graphify#4492 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 86/100
Graphify-Labs/graphify#3763 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
Graphify-Labs/graphify#3611 · 1 commento ·
I maintainer di solito rispondono entro 1 giorno
-
Nix supportAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 62/100
Graphify-Labs/graphify#3193 · 2 reazioni ·
I maintainer di solito rispondono entro 1 giorno
Tutte le issue di Graphify-Labs/graphify
Issue simili
-
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
aws-samples/sample-per-model-bedrock#261 ·
I maintainer di solito rispondono entro 1 giorno
-
[UI/Accessibility] Low contrast text visibility in country selection dropdown on settings pageAperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 65/100
pwncollege/dojo#1188 ·
I maintainer di solito rispondono entro 1 giorno
-
bug launcher packaging
Difficoltà 1/5 Meno di un'ora Idoneità per principianti 88/100
tenstorrent/tt-studio#1426 ·
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
python-attrs/cattrs#796 ·
I maintainer di solito rispondono entro 1 giorno