Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

Rust extractor: lossy structure and name-only call resolution (generic impls, traits, mods, use-lists, receivers)

Đang mở
#4,285 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức phù hợp với người mới
18/100
Loại issue
Lỗi
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
python, rust
Lĩnh vực
devtools

Hướng nghiên cứu

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.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

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

  1. Generic impls create orphan nodes. impl<T> Foo<T> / impl Foo<u8> produce nodes Foo<T> / Foo<u8>, separate from the Foo struct node. Methods hang off the orphans.
  2. Trait is dropped from impl Trait for Type. No implements edge; trait impls look like inherent impls, and several impls of the same method name for one type (e.g. three impl From<_> for E) share one ID scheme.
  3. trait_item returns without descending. Trait methods produce no nodes, so calls from default method bodies (skip -> helper) are lost.
  4. IDs ignore the inline mod path, and are case-folded. inner::helper and top-level helper get the same ID, as do inner::Foo and Foo; nodes merge and inner::helper() becomes a dropped self-call. Because _make_id lower-cases, const ITEM and fn item() also collide (first label wins). Across files, _file_stem is parent.stem, so every src/lib.rs shares src.lib.
  5. Missing node kinds: mod, type, const, static, union, macro_rules!.
  6. use handling is lossy: use std::fmt::{self, Display} yields one edge (the text before {), losing Display; 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 local fn 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 named inline / the type node.
  • validator.enter_item(..) is linked to an unrelated free fn enter_item, not the method on validator's type.
  • Conversely, true calls are missed: self.m() when several types in the file define m, Type::f() when Type has 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 + mod path and tagged by kind; generics stripped so impl<T> Foo<T> attaches to Foo; implements edges (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 with Result/Option/Box/Arc unwrapped, if let Some(x), generic bounds, for/closure element types over Vec/slice/array). When a call can reach several impls, an edge goes to each candidate with INFERRED confidence. 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.

Ngôn ngữ chính
Python
Star
124k
Fork
11.9k
Chỉ số merge pull request
Không có pull request nào được merge trong 30 ngày

Chuẩn bị môi trường

Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của Graphify-Labs/graphify

Tất cả issue của Graphify-Labs/graphify

Issue tương tự

Thêm issue về Python

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.