@@ -616,7 +616,9 @@ fn extract_file_data(
616616 // when there's no enclosing class at all — not valid Rust for
617617 // a real `Self::` call, so this can't regress a working case.
618618 let effective_receiver = if lang == "rust" && receiver == "Self" {
619- c. enclosing_class . clone ( ) . unwrap_or_else ( || receiver. clone ( ) )
619+ c. enclosing_class
620+ . clone ( )
621+ . unwrap_or_else ( || receiver. clone ( ) )
620622 } else {
621623 receiver. clone ( )
622624 } ;
@@ -6128,115 +6130,115 @@ impl StructB {
61286130 let _ = std:: fs:: remove_dir_all ( & dir) ;
61296131 }
61306132
6131- #[ test]
6132- fn rust_self_colon_colon_call_resolves_to_the_enclosing_impl_type ( ) {
6133- // 2026-08-03 regression test: `Self::method()` inside an `impl Type { .. }`
6134- // block used to resolve to ZERO callers, not even `ambiguous`, because
6135- // `extract_file_data` set `target_class` to the literal keyword text
6136- // "Self" instead of substituting the enclosing impl's real type name --
6137- // "Self" is never itself a registered symbol/class, so the
6138- // `by_name_class` lookup in `resolve_sites_to_edges` could never match.
6139- // Found via a live CALM-vs-CodeGraph benchmark: fd's `replace_separator`
6140- // (called 5x in-file via `Self::replace_separator(...)`) and this exact
6141- // codebase's `ConservativeResolver::default` -> `Self::new()` both had 0
6142- // callers before this fix. `resolve_tier2` already does the equivalent
6143- // substitution for lowercase `self`/`this`; this is the same fix for
6144- // Rust's capitalized `Self`, applied one branch earlier.
6145- let dir = std:: env:: temp_dir ( ) . join ( format ! ( "ci_rust_self_colon_{}" , std:: process:: id( ) ) ) ;
6146- let _ = std:: fs:: remove_dir_all ( & dir) ;
6147- std:: fs:: create_dir_all ( & dir) . unwrap ( ) ;
6148-
6149- std:: fs:: write (
6150- dir. join ( "widget.rs" ) ,
6151- "struct Widget;\n \
6133+ #[ test]
6134+ fn rust_self_colon_colon_call_resolves_to_the_enclosing_impl_type ( ) {
6135+ // 2026-08-03 regression test: `Self::method()` inside an `impl Type { .. }`
6136+ // block used to resolve to ZERO callers, not even `ambiguous`, because
6137+ // `extract_file_data` set `target_class` to the literal keyword text
6138+ // "Self" instead of substituting the enclosing impl's real type name --
6139+ // "Self" is never itself a registered symbol/class, so the
6140+ // `by_name_class` lookup in `resolve_sites_to_edges` could never match.
6141+ // Found via a live CALM-vs-CodeGraph benchmark: fd's `replace_separator`
6142+ // (called 5x in-file via `Self::replace_separator(...)`) and this exact
6143+ // codebase's `ConservativeResolver::default` -> `Self::new()` both had 0
6144+ // callers before this fix. `resolve_tier2` already does the equivalent
6145+ // substitution for lowercase `self`/`this`; this is the same fix for
6146+ // Rust's capitalized `Self`, applied one branch earlier.
6147+ let dir = std:: env:: temp_dir ( ) . join ( format ! ( "ci_rust_self_colon_{}" , std:: process:: id( ) ) ) ;
6148+ let _ = std:: fs:: remove_dir_all ( & dir) ;
6149+ std:: fs:: create_dir_all ( & dir) . unwrap ( ) ;
6150+
6151+ std:: fs:: write (
6152+ dir. join ( "widget.rs" ) ,
6153+ "struct Widget;\n \
61526154 impl Widget {\n \
61536155 fn new() -> Self {\n Widget\n }\n \n \
61546156 fn make() -> Self {\n Self::new()\n }\n \
61556157 }\n ",
6156- )
6157- . unwrap ( ) ;
6158+ )
6159+ . unwrap ( ) ;
61586160
6159- let mut conn = Connection :: open_in_memory ( ) . unwrap ( ) ;
6160- init_db ( & conn) . unwrap ( ) ;
6161- run_indexing_pipeline ( & mut conn, & dir, dummy_phase ( ) ) . unwrap ( ) ;
6161+ let mut conn = Connection :: open_in_memory ( ) . unwrap ( ) ;
6162+ init_db ( & conn) . unwrap ( ) ;
6163+ run_indexing_pipeline ( & mut conn, & dir, dummy_phase ( ) ) . unwrap ( ) ;
61626164
6163- let edge_count: i64 = conn
6164- . query_row (
6165- "SELECT COUNT(*) FROM call_edges \
6165+ let edge_count: i64 = conn
6166+ . query_row (
6167+ "SELECT COUNT(*) FROM call_edges \
61666168 WHERE from_symbol LIKE '%::Widget::make' AND to_symbol LIKE '%::Widget::new'",
6167- [ ] ,
6168- |r| r. get ( 0 ) ,
6169- )
6170- . unwrap ( ) ;
6171- assert_eq ! (
6172- edge_count, 1 ,
6173- "Self::new() inside impl Widget must produce exactly one call edge \
6169+ [ ] ,
6170+ |r| r. get ( 0 ) ,
6171+ )
6172+ . unwrap ( ) ;
6173+ assert_eq ! (
6174+ edge_count, 1 ,
6175+ "Self::new() inside impl Widget must produce exactly one call edge \
61746176 make -> new, scoped to Widget (not zero, not fanned out to every \
61756177 same-named `new` in the codebase)"
6176- ) ;
6178+ ) ;
61776179
6178- let confidence: String = conn
6179- . query_row (
6180- "SELECT edge_confidence FROM call_edges \
6180+ let confidence: String = conn
6181+ . query_row (
6182+ "SELECT edge_confidence FROM call_edges \
61816183 WHERE from_symbol LIKE '%::Widget::make' AND to_symbol LIKE '%::Widget::new'",
6182- [ ] ,
6183- |r| r. get ( 0 ) ,
6184- )
6185- . unwrap ( ) ;
6186- assert_eq ! (
6187- confidence, "inferred" ,
6188- "Self:: is a type-path receiver (same tier as Type::method()), so \
6184+ [ ] ,
6185+ |r| r. get ( 0 ) ,
6186+ )
6187+ . unwrap ( ) ;
6188+ assert_eq ! (
6189+ confidence, "inferred" ,
6190+ "Self:: is a type-path receiver (same tier as Type::method()), so \
61896191 confidence must be 'inferred', not 'textual'/'ambiguous'/'resolved'"
6190- ) ;
6192+ ) ;
61916193
6192- let _ = std:: fs:: remove_dir_all ( & dir) ;
6193- }
6194+ let _ = std:: fs:: remove_dir_all ( & dir) ;
6195+ }
61946196
6195- #[ test]
6196- fn rust_self_colon_colon_call_inside_a_trait_default_method_resolves_to_the_trait ( ) {
6197- // 2026-08-03 regression test for the walk_calls trait_item fix
6198- // (parser.rs): `trait_item` has no "type" field (only "name"), unlike
6199- // `impl_item` -- `class_name_field: "type"` is shared by both node kinds
6200- // in `lang_constants.rs`, so before this fix `walk_calls`'s child_class
6201- // computation silently got `None` for a trait, and a default method's
6202- // own `Self::sibling()` call fell through to literal target_class "Self"
6203- // (0 call_edges) -- same broken shape as the impl_item `Self::` bug, via
6204- // a different root cause. Verified with a live characterization pass
6205- // before fixing (not assumed): `call_sites` showed
6206- // `target_class=Some("Self")` and `call_edges` was empty.
6207- let dir = std:: env:: temp_dir ( ) . join ( format ! ( "ci_rust_trait_self_{}" , std:: process:: id( ) ) ) ;
6208- let _ = std:: fs:: remove_dir_all ( & dir) ;
6209- std:: fs:: create_dir_all ( & dir) . unwrap ( ) ;
6210-
6211- std:: fs:: write (
6212- dir. join ( "greeter.rs" ) ,
6213- "trait Greeter {\n \
6197+ #[ test]
6198+ fn rust_self_colon_colon_call_inside_a_trait_default_method_resolves_to_the_trait ( ) {
6199+ // 2026-08-03 regression test for the walk_calls trait_item fix
6200+ // (parser.rs): `trait_item` has no "type" field (only "name"), unlike
6201+ // `impl_item` -- `class_name_field: "type"` is shared by both node kinds
6202+ // in `lang_constants.rs`, so before this fix `walk_calls`'s child_class
6203+ // computation silently got `None` for a trait, and a default method's
6204+ // own `Self::sibling()` call fell through to literal target_class "Self"
6205+ // (0 call_edges) -- same broken shape as the impl_item `Self::` bug, via
6206+ // a different root cause. Verified with a live characterization pass
6207+ // before fixing (not assumed): `call_sites` showed
6208+ // `target_class=Some("Self")` and `call_edges` was empty.
6209+ let dir = std:: env:: temp_dir ( ) . join ( format ! ( "ci_rust_trait_self_{}" , std:: process:: id( ) ) ) ;
6210+ let _ = std:: fs:: remove_dir_all ( & dir) ;
6211+ std:: fs:: create_dir_all ( & dir) . unwrap ( ) ;
6212+
6213+ std:: fs:: write (
6214+ dir. join ( "greeter.rs" ) ,
6215+ "trait Greeter {\n \
62146216 fn helper() -> String {\n \" hi\" .to_string()\n }\n \n \
62156217 fn greet() -> String {\n Self::helper()\n }\n \
62166218 }\n ",
6217- )
6218- . unwrap ( ) ;
6219+ )
6220+ . unwrap ( ) ;
62196221
6220- let mut conn = Connection :: open_in_memory ( ) . unwrap ( ) ;
6221- init_db ( & conn) . unwrap ( ) ;
6222- run_indexing_pipeline ( & mut conn, & dir, dummy_phase ( ) ) . unwrap ( ) ;
6222+ let mut conn = Connection :: open_in_memory ( ) . unwrap ( ) ;
6223+ init_db ( & conn) . unwrap ( ) ;
6224+ run_indexing_pipeline ( & mut conn, & dir, dummy_phase ( ) ) . unwrap ( ) ;
62236225
6224- let edge_count: i64 = conn
6225- . query_row (
6226- "SELECT COUNT(*) FROM call_edges \
6226+ let edge_count: i64 = conn
6227+ . query_row (
6228+ "SELECT COUNT(*) FROM call_edges \
62276229 WHERE from_symbol LIKE '%::Greeter::greet' AND to_symbol LIKE '%::Greeter::helper'",
6228- [ ] ,
6229- |r| r. get ( 0 ) ,
6230- )
6231- . unwrap ( ) ;
6232- assert_eq ! (
6233- edge_count, 1 ,
6234- "Self::helper() inside a Greeter trait default method must resolve to \
6230+ [ ] ,
6231+ |r| r. get ( 0 ) ,
6232+ )
6233+ . unwrap ( ) ;
6234+ assert_eq ! (
6235+ edge_count, 1 ,
6236+ "Self::helper() inside a Greeter trait default method must resolve to \
62356237 Greeter's own declared helper() (not zero, not fanned out elsewhere)"
6236- ) ;
6238+ ) ;
62376239
6238- let _ = std:: fs:: remove_dir_all ( & dir) ;
6239- }
6240+ let _ = std:: fs:: remove_dir_all ( & dir) ;
6241+ }
62406242
62416243 /// Regression for the real-world incident this module's return-shape filter
62426244 /// exists for: `caller.rs` calls a bare `as_str()` on an unresolvable
@@ -6553,7 +6555,11 @@ fn rust_self_colon_colon_call_inside_a_trait_default_method_resolves_to_the_trai
65536555 let dir = std:: env:: temp_dir ( ) . join ( format ! ( "ci_idx_dupcallsite_{}" , std:: process:: id( ) ) ) ;
65546556 let _ = std:: fs:: remove_dir_all ( & dir) ;
65556557 std:: fs:: create_dir_all ( & dir) . unwrap ( ) ;
6556- std:: fs:: write ( dir. join ( "a.rs" ) , "fn helper() {}\n fn caller() {\n helper();\n }\n " ) . unwrap ( ) ;
6558+ std:: fs:: write (
6559+ dir. join ( "a.rs" ) ,
6560+ "fn helper() {}\n fn caller() {\n helper();\n }\n " ,
6561+ )
6562+ . unwrap ( ) ;
65576563
65586564 let mut conn = Connection :: open_in_memory ( ) . unwrap ( ) ;
65596565 init_db ( & conn) . unwrap ( ) ;
0 commit comments