Skip to content

Commit aaf8db5

Browse files
committed
fix(recursive_callees): insert visited outside calls_in_body
$ cargo r -- --json=false tests/standard_proof_simple.rs [top_level] fn FnDef(DefId { id: 1, name: "top_level" })() -> () { let mut _0: (); let _1: (); bb0: { _1 = m::func1() -> [return: bb1, unwind continue]; } bb1: { return; } } [m::func1] fn FnDef(DefId { id: 2, name: "m::func1" })() -> () { let mut _0: (); let _1: &str; let mut _2: &str; debug _a => _1; bb0: { StorageLive(_1); StorageLive(_2); _2 = ""; _1 = core::str::<impl str>::trim(move _2) -> [return: bb1, unwind continue]; } bb1: { StorageDead(_2); StorageDead(_1); return; } } [core::str::<impl str>::trim] fn FnDef(DefId { id: 3, name: "core::str::<impl str>::trim" })(_1: &str) -> &str { let mut _0: &str; debug self => _1; bb0: { _0 = core::str::<impl str>::trim_matches::<{closure@core::str::<impl str>::trim::{closure#0}}>(_1, ZeroSized: {closure@core::str::<impl str>::trim::{closure#0}}) -> [return: bb1, unwind unreachable]; } bb1: { return; } } [core::str::<impl str>::trim_matches] fn FnDef(DefId { id: 4, name: "core::str::<impl str>::trim_matches" })(_1: &str, _2: P) -> &str { let mut _0: &str; let mut _3: usize; let mut _4: usize; let mut _5: <P as std::str::pattern::Pattern>::Searcher<'_>; let mut _6: std::option::Option<(usize, usize)>; let mut _7: &mut <P as std::str::pattern::Pattern>::Searcher<'_>; let mut _8: isize; let _9: usize; let _10: usize; let mut _11: std::option::Option<(usize, usize)>; let mut _12: &mut <P as std::str::pattern::Pattern>::Searcher<'_>; let mut _13: isize; let _14: usize; let mut _15: std::ops::Range<usize>; let mut _16: usize; let mut _17: usize; debug self => _1; debug pat => _2; debug i => _3; debug j => _4; debug matcher => _5; debug a => _9; debug b => _10; debug b => _14; bb0: { StorageLive(_3); _3 = 0_usize; StorageLive(_4); _4 = 0_usize; StorageLive(_5); _5 = <P as std::str::pattern::Pattern>::into_searcher(move _2, _1) -> [return: bb1, unwind unreachable]; } bb1: { StorageLive(_6); StorageLive(_7); _7 = &mut _5; _6 = <<P as std::str::pattern::Pattern>::Searcher<'_> as std::str::pattern::Searcher<'_>>::next_reject(move _7) -> [return: bb2, unwind unreachable]; } bb2: { StorageDead(_7); _8 = discriminant(_6); switchInt(move _8) -> [1: bb3, 0: bb4, otherwise: bb12]; } bb3: { _9 = (((_6 as variant#1).0: (usize, usize)).0: usize); _10 = (((_6 as variant#1).0: (usize, usize)).1: usize); _3 = _9; _4 = _10; StorageDead(_6); goto -> bb5; } bb4: { StorageDead(_6); goto -> bb5; } bb5: { StorageLive(_11); StorageLive(_12); _12 = &mut _5; _11 = <<P as std::str::pattern::Pattern>::Searcher<'_> as std::str::pattern::ReverseSearcher<'_>>::next_reject_back(move _12) -> [return: bb6, unwind unreachable]; } bb6: { StorageDead(_12); _13 = discriminant(_11); switchInt(move _13) -> [1: bb7, 0: bb8, otherwise: bb12]; } bb7: { _14 = (((_11 as variant#1).0: (usize, usize)).1: usize); _4 = _14; StorageDead(_11); goto -> bb9; } bb8: { StorageDead(_11); goto -> bb9; } bb9: { StorageLive(_15); StorageLive(_16); _16 = _3; StorageLive(_17); _17 = _4; _15 = Range(move _16, move _17); StorageDead(_17); StorageDead(_16); _0 = core::str::<impl str>::get_unchecked::<std::ops::Range<usize>>(_1, move _15) -> [return: bb10, unwind unreachable]; } bb10: { StorageDead(_15); drop(_5) -> [return: bb11, unwind unreachable]; } bb11: { StorageDead(_5); StorageDead(_4); StorageDead(_3); return; } bb12: { unreachable; } } [core::str::<impl str>::get_unchecked] fn FnDef(DefId { id: 10, name: "core::str::<impl str>::get_unchecked" })(_1: &str, _2: I) -> &<I as std::slice::SliceIndex<str>>::Output { let mut _0: &<I as std::slice::SliceIndex<str>>::Output; let _3: *const <I as std::slice::SliceIndex<str>>::Output; let mut _4: *const str; debug self => _1; debug i => _2; bb0: { StorageLive(_3); StorageLive(_4); _4 = &raw const (*_1); _3 = <I as std::slice::SliceIndex<str>>::get_unchecked(move _2, move _4) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_4); _0 = &(*_3); StorageDead(_3); return; } } [std::slice::SliceIndex::get_unchecked] [std::str::pattern::ReverseSearcher::next_reject_back] fn FnDef(DefId { id: 9, name: "std::str::pattern::ReverseSearcher::next_reject_back" })(_1: &mut Self) -> std::option::Option<(usize, usize)> { let mut _0: std::option::Option<(usize, usize)>; let mut _2: std::str::pattern::SearchStep; let mut _3: isize; let _4: usize; let _5: usize; let mut _6: (usize, usize); debug self => _1; debug a => _4; debug b => _5; bb0: { goto -> bb1; } bb1: { StorageLive(_2); _2 = <Self as std::str::pattern::ReverseSearcher<'_>>::next_back(_1) -> [return: bb2, unwind unreachable]; } bb2: { _3 = discriminant(_2); switchInt(move _3) -> [1: bb4, 2: bb3, 0: bb5, otherwise: bb7]; } bb3: { _0 = std::option::Option::None; goto -> bb6; } bb4: { _4 = ((_2 as variant#1).0: usize); _5 = ((_2 as variant#1).1: usize); StorageLive(_6); _6 = (_4, _5); _0 = std::option::Option::Some(move _6); StorageDead(_6); goto -> bb6; } bb5: { StorageDead(_2); goto -> bb1; } bb6: { StorageDead(_2); return; } bb7: { unreachable; } } [std::str::pattern::ReverseSearcher::next_back] [std::str::pattern::Searcher::next_reject] fn FnDef(DefId { id: 8, name: "std::str::pattern::Searcher::next_reject" })(_1: &mut Self) -> std::option::Option<(usize, usize)> { let mut _0: std::option::Option<(usize, usize)>; let mut _2: std::str::pattern::SearchStep; let mut _3: isize; let _4: usize; let _5: usize; let mut _6: (usize, usize); debug self => _1; debug a => _4; debug b => _5; bb0: { goto -> bb1; } bb1: { StorageLive(_2); _2 = <Self as std::str::pattern::Searcher<'_>>::next(_1) -> [return: bb2, unwind unreachable]; } bb2: { _3 = discriminant(_2); switchInt(move _3) -> [1: bb4, 2: bb3, 0: bb5, otherwise: bb7]; } bb3: { _0 = std::option::Option::None; goto -> bb6; } bb4: { _4 = ((_2 as variant#1).0: usize); _5 = ((_2 as variant#1).1: usize); StorageLive(_6); _6 = (_4, _5); _0 = std::option::Option::Some(move _6); StorageDead(_6); goto -> bb6; } bb5: { StorageDead(_2); goto -> bb1; } bb6: { StorageDead(_2); return; } bb7: { unreachable; } } [std::str::pattern::Searcher::next] [std::str::pattern::Pattern::into_searcher] [m::func1] fn FnDef(DefId { id: 2, name: "m::func1" })() -> () { let mut _0: (); let _1: &str; let mut _2: &str; debug _a => _1; bb0: { StorageLive(_1); StorageLive(_2); _2 = ""; _1 = core::str::<impl str>::trim(move _2) -> [return: bb1, unwind continue]; } bb1: { StorageDead(_2); StorageDead(_1); return; } } [core::str::<impl str>::trim] fn FnDef(DefId { id: 3, name: "core::str::<impl str>::trim" })(_1: &str) -> &str { let mut _0: &str; debug self => _1; bb0: { _0 = core::str::<impl str>::trim_matches::<{closure@core::str::<impl str>::trim::{closure#0}}>(_1, ZeroSized: {closure@core::str::<impl str>::trim::{closure#0}}) -> [return: bb1, unwind unreachable]; } bb1: { return; } } [core::str::<impl str>::trim_matches] fn FnDef(DefId { id: 4, name: "core::str::<impl str>::trim_matches" })(_1: &str, _2: P) -> &str { let mut _0: &str; let mut _3: usize; let mut _4: usize; let mut _5: <P as std::str::pattern::Pattern>::Searcher<'_>; let mut _6: std::option::Option<(usize, usize)>; let mut _7: &mut <P as std::str::pattern::Pattern>::Searcher<'_>; let mut _8: isize; let _9: usize; let _10: usize; let mut _11: std::option::Option<(usize, usize)>; let mut _12: &mut <P as std::str::pattern::Pattern>::Searcher<'_>; let mut _13: isize; let _14: usize; let mut _15: std::ops::Range<usize>; let mut _16: usize; let mut _17: usize; debug self => _1; debug pat => _2; debug i => _3; debug j => _4; debug matcher => _5; debug a => _9; debug b => _10; debug b => _14; bb0: { StorageLive(_3); _3 = 0_usize; StorageLive(_4); _4 = 0_usize; StorageLive(_5); _5 = <P as std::str::pattern::Pattern>::into_searcher(move _2, _1) -> [return: bb1, unwind unreachable]; } bb1: { StorageLive(_6); StorageLive(_7); _7 = &mut _5; _6 = <<P as std::str::pattern::Pattern>::Searcher<'_> as std::str::pattern::Searcher<'_>>::next_reject(move _7) -> [return: bb2, unwind unreachable]; } bb2: { StorageDead(_7); _8 = discriminant(_6); switchInt(move _8) -> [1: bb3, 0: bb4, otherwise: bb12]; } bb3: { _9 = (((_6 as variant#1).0: (usize, usize)).0: usize); _10 = (((_6 as variant#1).0: (usize, usize)).1: usize); _3 = _9; _4 = _10; StorageDead(_6); goto -> bb5; } bb4: { StorageDead(_6); goto -> bb5; } bb5: { StorageLive(_11); StorageLive(_12); _12 = &mut _5; _11 = <<P as std::str::pattern::Pattern>::Searcher<'_> as std::str::pattern::ReverseSearcher<'_>>::next_reject_back(move _12) -> [return: bb6, unwind unreachable]; } bb6: { StorageDead(_12); _13 = discriminant(_11); switchInt(move _13) -> [1: bb7, 0: bb8, otherwise: bb12]; } bb7: { _14 = (((_11 as variant#1).0: (usize, usize)).1: usize); _4 = _14; StorageDead(_11); goto -> bb9; } bb8: { StorageDead(_11); goto -> bb9; } bb9: { StorageLive(_15); StorageLive(_16); _16 = _3; StorageLive(_17); _17 = _4; _15 = Range(move _16, move _17); StorageDead(_17); StorageDead(_16); _0 = core::str::<impl str>::get_unchecked::<std::ops::Range<usize>>(_1, move _15) -> [return: bb10, unwind unreachable]; } bb10: { StorageDead(_15); drop(_5) -> [return: bb11, unwind unreachable]; } bb11: { StorageDead(_5); StorageDead(_4); StorageDead(_3); return; } bb12: { unreachable; } } [core::str::<impl str>::get_unchecked] fn FnDef(DefId { id: 10, name: "core::str::<impl str>::get_unchecked" })(_1: &str, _2: I) -> &<I as std::slice::SliceIndex<str>>::Output { let mut _0: &<I as std::slice::SliceIndex<str>>::Output; let _3: *const <I as std::slice::SliceIndex<str>>::Output; let mut _4: *const str; debug self => _1; debug i => _2; bb0: { StorageLive(_3); StorageLive(_4); _4 = &raw const (*_1); _3 = <I as std::slice::SliceIndex<str>>::get_unchecked(move _2, move _4) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_4); _0 = &(*_3); StorageDead(_3); return; } } [std::slice::SliceIndex::get_unchecked] [std::str::pattern::ReverseSearcher::next_reject_back] fn FnDef(DefId { id: 9, name: "std::str::pattern::ReverseSearcher::next_reject_back" })(_1: &mut Self) -> std::option::Option<(usize, usize)> { let mut _0: std::option::Option<(usize, usize)>; let mut _2: std::str::pattern::SearchStep; let mut _3: isize; let _4: usize; let _5: usize; let mut _6: (usize, usize); debug self => _1; debug a => _4; debug b => _5; bb0: { goto -> bb1; } bb1: { StorageLive(_2); _2 = <Self as std::str::pattern::ReverseSearcher<'_>>::next_back(_1) -> [return: bb2, unwind unreachable]; } bb2: { _3 = discriminant(_2); switchInt(move _3) -> [1: bb4, 2: bb3, 0: bb5, otherwise: bb7]; } bb3: { _0 = std::option::Option::None; goto -> bb6; } bb4: { _4 = ((_2 as variant#1).0: usize); _5 = ((_2 as variant#1).1: usize); StorageLive(_6); _6 = (_4, _5); _0 = std::option::Option::Some(move _6); StorageDead(_6); goto -> bb6; } bb5: { StorageDead(_2); goto -> bb1; } bb6: { StorageDead(_2); return; } bb7: { unreachable; } } [std::str::pattern::ReverseSearcher::next_back] [std::str::pattern::Searcher::next_reject] fn FnDef(DefId { id: 8, name: "std::str::pattern::Searcher::next_reject" })(_1: &mut Self) -> std::option::Option<(usize, usize)> { let mut _0: std::option::Option<(usize, usize)>; let mut _2: std::str::pattern::SearchStep; let mut _3: isize; let _4: usize; let _5: usize; let mut _6: (usize, usize); debug self => _1; debug a => _4; debug b => _5; bb0: { goto -> bb1; } bb1: { StorageLive(_2); _2 = <Self as std::str::pattern::Searcher<'_>>::next(_1) -> [return: bb2, unwind unreachable]; } bb2: { _3 = discriminant(_2); switchInt(move _3) -> [1: bb4, 2: bb3, 0: bb5, otherwise: bb7]; } bb3: { _0 = std::option::Option::None; goto -> bb6; } bb4: { _4 = ((_2 as variant#1).0: usize); _5 = ((_2 as variant#1).1: usize); StorageLive(_6); _6 = (_4, _5); _0 = std::option::Option::Some(move _6); StorageDead(_6); goto -> bb6; } bb5: { StorageDead(_2); goto -> bb1; } bb6: { StorageDead(_2); return; } bb7: { unreachable; } } [std::str::pattern::Searcher::next] [std::str::pattern::Pattern::into_searcher] [core::str::<impl str>::trim] fn FnDef(DefId { id: 3, name: "core::str::<impl str>::trim" })(_1: &str) -> &str { let mut _0: &str; debug self => _1; bb0: { _0 = core::str::<impl str>::trim_matches::<{closure@core::str::<impl str>::trim::{closure#0}}>(_1, ZeroSized: {closure@core::str::<impl str>::trim::{closure#0}}) -> [return: bb1, unwind unreachable]; } bb1: { return; } } [core::str::<impl str>::trim_matches] fn FnDef(DefId { id: 4, name: "core::str::<impl str>::trim_matches" })(_1: &str, _2: P) -> &str { let mut _0: &str; let mut _3: usize; let mut _4: usize; let mut _5: <P as std::str::pattern::Pattern>::Searcher<'_>; let mut _6: std::option::Option<(usize, usize)>; let mut _7: &mut <P as std::str::pattern::Pattern>::Searcher<'_>; let mut _8: isize; let _9: usize; let _10: usize; let mut _11: std::option::Option<(usize, usize)>; let mut _12: &mut <P as std::str::pattern::Pattern>::Searcher<'_>; let mut _13: isize; let _14: usize; let mut _15: std::ops::Range<usize>; let mut _16: usize; let mut _17: usize; debug self => _1; debug pat => _2; debug i => _3; debug j => _4; debug matcher => _5; debug a => _9; debug b => _10; debug b => _14; bb0: { StorageLive(_3); _3 = 0_usize; StorageLive(_4); _4 = 0_usize; StorageLive(_5); _5 = <P as std::str::pattern::Pattern>::into_searcher(move _2, _1) -> [return: bb1, unwind unreachable]; } bb1: { StorageLive(_6); StorageLive(_7); _7 = &mut _5; _6 = <<P as std::str::pattern::Pattern>::Searcher<'_> as std::str::pattern::Searcher<'_>>::next_reject(move _7) -> [return: bb2, unwind unreachable]; } bb2: { StorageDead(_7); _8 = discriminant(_6); switchInt(move _8) -> [1: bb3, 0: bb4, otherwise: bb12]; } bb3: { _9 = (((_6 as variant#1).0: (usize, usize)).0: usize); _10 = (((_6 as variant#1).0: (usize, usize)).1: usize); _3 = _9; _4 = _10; StorageDead(_6); goto -> bb5; } bb4: { StorageDead(_6); goto -> bb5; } bb5: { StorageLive(_11); StorageLive(_12); _12 = &mut _5; _11 = <<P as std::str::pattern::Pattern>::Searcher<'_> as std::str::pattern::ReverseSearcher<'_>>::next_reject_back(move _12) -> [return: bb6, unwind unreachable]; } bb6: { StorageDead(_12); _13 = discriminant(_11); switchInt(move _13) -> [1: bb7, 0: bb8, otherwise: bb12]; } bb7: { _14 = (((_11 as variant#1).0: (usize, usize)).1: usize); _4 = _14; StorageDead(_11); goto -> bb9; } bb8: { StorageDead(_11); goto -> bb9; } bb9: { StorageLive(_15); StorageLive(_16); _16 = _3; StorageLive(_17); _17 = _4; _15 = Range(move _16, move _17); StorageDead(_17); StorageDead(_16); _0 = core::str::<impl str>::get_unchecked::<std::ops::Range<usize>>(_1, move _15) -> [return: bb10, unwind unreachable]; } bb10: { StorageDead(_15); drop(_5) -> [return: bb11, unwind unreachable]; } bb11: { StorageDead(_5); StorageDead(_4); StorageDead(_3); return; } bb12: { unreachable; } } [core::str::<impl str>::get_unchecked] fn FnDef(DefId { id: 10, name: "core::str::<impl str>::get_unchecked" })(_1: &str, _2: I) -> &<I as std::slice::SliceIndex<str>>::Output { let mut _0: &<I as std::slice::SliceIndex<str>>::Output; let _3: *const <I as std::slice::SliceIndex<str>>::Output; let mut _4: *const str; debug self => _1; debug i => _2; bb0: { StorageLive(_3); StorageLive(_4); _4 = &raw const (*_1); _3 = <I as std::slice::SliceIndex<str>>::get_unchecked(move _2, move _4) -> [return: bb1, unwind unreachable]; } bb1: { StorageDead(_4); _0 = &(*_3); StorageDead(_3); return; } } [std::slice::SliceIndex::get_unchecked] [std::str::pattern::ReverseSearcher::next_reject_back] fn FnDef(DefId { id: 9, name: "std::str::pattern::ReverseSearcher::next_reject_back" })(_1: &mut Self) -> std::option::Option<(usize, usize)> { let mut _0: std::option::Option<(usize, usize)>; let mut _2: std::str::pattern::SearchStep; let mut _3: isize; let _4: usize; let _5: usize; let mut _6: (usize, usize); debug self => _1; debug a => _4; debug b => _5; bb0: { goto -> bb1; } bb1: { StorageLive(_2); _2 = <Self as std::str::pattern::ReverseSearcher<'_>>::next_back(_1) -> [return: bb2, unwind unreachable]; } bb2: { _3 = discriminant(_2); switchInt(move _3) -> [1: bb4, 2: bb3, 0: bb5, otherwise: bb7]; } bb3: { _0 = std::option::Option::None; goto -> bb6; } bb4: { _4 = ((_2 as variant#1).0: usize); _5 = ((_2 as variant#1).1: usize); StorageLive(_6); _6 = (_4, _5); _0 = std::option::Option::Some(move _6); StorageDead(_6); goto -> bb6; } bb5: { StorageDead(_2); goto -> bb1; } bb6: { StorageDead(_2); return; } bb7: { unreachable; } } [std::str::pattern::ReverseSearcher::next_back] [std::str::pattern::Searcher::next_reject] fn FnDef(DefId { id: 8, name: "std::str::pattern::Searcher::next_reject" })(_1: &mut Self) -> std::option::Option<(usize, usize)> { let mut _0: std::option::Option<(usize, usize)>; let mut _2: std::str::pattern::SearchStep; let mut _3: isize; let _4: usize; let _5: usize; let mut _6: (usize, usize); debug self => _1; debug a => _4; debug b => _5; bb0: { goto -> bb1; } bb1: { StorageLive(_2); _2 = <Self as std::str::pattern::Searcher<'_>>::next(_1) -> [return: bb2, unwind unreachable]; } bb2: { _3 = discriminant(_2); switchInt(move _3) -> [1: bb4, 2: bb3, 0: bb5, otherwise: bb7]; } bb3: { _0 = std::option::Option::None; goto -> bb6; } bb4: { _4 = ((_2 as variant#1).0: usize); _5 = ((_2 as variant#1).1: usize); StorageLive(_6); _6 = (_4, _5); _0 = std::option::Option::Some(move _6); StorageDead(_6); goto -> bb6; } bb5: { StorageDead(_2); goto -> bb1; } bb6: { StorageDead(_2); return; } bb7: { unreachable; } } [std::str::pattern::Searcher::next] [std::str::pattern::Pattern::into_searcher] ⏎
1 parent 9ce2186 commit aaf8db5

File tree

3 files changed

+44
-27
lines changed

3 files changed

+44
-27
lines changed

src/functions/callees.rs

Lines changed: 16 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,62 +1,55 @@
11
use super::ty_to_fndef;
22
use indexmap::IndexSet;
3-
use stable_mir::{mir::*, ty::FnDef};
3+
use stable_mir::{CrateDef, mir::*, ty::FnDef};
44

5-
pub fn calls_in_body(body: &Body, visited: &mut IndexSet<FnDef>) -> Vec<FnDef> {
5+
pub fn calls_in_body(body: &Body) -> Vec<FnDef> {
66
let locals = body.locals();
77
let mut direct = Vec::new();
88
for basic_block in &body.blocks {
9-
terminator_to_fn_def(&basic_block.terminator, locals, visited, &mut direct);
9+
terminator_to_fn_def(&basic_block.terminator, locals, &mut direct);
1010
}
1111
// all direct calls in a body
1212
direct
1313
}
1414

1515
/// Extract fn call from the terminator.
16-
fn terminator_to_fn_def(
17-
terminator: &Terminator,
18-
locals: &[LocalDecl],
19-
visited: &mut IndexSet<FnDef>,
20-
direct: &mut Vec<FnDef>,
21-
) {
16+
fn terminator_to_fn_def(terminator: &Terminator, locals: &[LocalDecl], direct: &mut Vec<FnDef>) {
2217
let TerminatorKind::Call { func, args, .. } = &terminator.kind else { return };
2318

24-
push_fn_def(func, visited, locals, direct);
19+
push_fn_def(func, locals, direct);
2520

2621
// FIXME: Will there be a FnDef in an arg in MIR? Probably no?
2722
// Anyway, need find a test for this. But now assume yes.
2823
// Maybe a function pointer or raw pointer cast to fn pointer suit?
2924
for arg in args {
30-
push_fn_def(arg, visited, locals, direct);
25+
push_fn_def(arg, locals, direct);
3126
}
3227

3328
// Will there ever be a FnDef in destination? Skip destination for now.
3429
}
3530

3631
/// Push a FnDef Operand if any.
37-
fn push_fn_def(
38-
func: &Operand,
39-
visited: &mut IndexSet<FnDef>,
40-
locals: &[LocalDecl],
41-
direct: &mut Vec<FnDef>,
42-
) {
32+
fn push_fn_def(func: &Operand, locals: &[LocalDecl], direct: &mut Vec<FnDef>) {
4333
let ty = func.ty(locals).expect("malformed operand or incompatible locals list");
4434
if let Some(fn_def) = ty_to_fndef(ty) {
4535
direct.push(fn_def);
46-
visited.insert(fn_def);
4736
}
4837
}
4938

5039
/// Recursively retrieve calls for a call.
5140
pub fn recursive_callees(fn_def: FnDef, visited: &mut IndexSet<FnDef>) {
41+
// print!("[{}] ", fn_def.name());
42+
5243
let Some(body) = fn_def.body() else { return };
53-
let mut buf = Vec::with_capacity(1024);
54-
body.dump(&mut buf, &format!("{fn_def:?}")).unwrap();
55-
println!("{}", String::from_utf8(buf).unwrap());
56-
let mut direct = calls_in_body(&body, visited);
44+
45+
// let mut buf = Vec::with_capacity(1024);
46+
// body.dump(&mut buf, &format!("{fn_def:?}")).unwrap();
47+
// println!("{}", String::from_utf8(buf).unwrap());
48+
49+
let mut direct = calls_in_body(&body);
5750
while let Some(call) = direct.pop() {
5851
// the call hasn't been reached, traverse
59-
if !visited.contains(&call) {
52+
if visited.insert(call) {
6053
recursive_callees(call, visited);
6154
}
6255
}

src/functions/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ impl Function {
4040

4141
let mut callees = IndexSet::new();
4242
// retrieve direct calls
43-
callees::calls_in_body(&body, &mut callees);
43+
callees.extend(callees::calls_in_body(&body));
4444
// recursive calls
4545
let direct_calls: Vec<_> = callees.iter().copied().collect();
4646
for call in direct_calls {

tests/snapshots.rs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,16 @@ fn standard_proof() {
4444
"func": "fn recursive_callees() {\n crate::top_level();\n }",
4545
"callees": [
4646
"FnDef(DefId { id: 3, name: \"top_level\" })",
47-
"FnDef(DefId { id: 4, name: \"m::func1\" })"
47+
"FnDef(DefId { id: 4, name: \"m::func1\" })",
48+
"FnDef(DefId { id: 8, name: \"core::str::<impl str>::trim\" })",
49+
"FnDef(DefId { id: 9, name: \"core::str::<impl str>::trim_matches\" })",
50+
"FnDef(DefId { id: 15, name: \"core::str::<impl str>::get_unchecked\" })",
51+
"FnDef(DefId { id: 16, name: \"std::slice::SliceIndex::get_unchecked\" })",
52+
"FnDef(DefId { id: 14, name: \"std::str::pattern::ReverseSearcher::next_reject_back\" })",
53+
"FnDef(DefId { id: 18, name: \"std::str::pattern::ReverseSearcher::next_back\" })",
54+
"FnDef(DefId { id: 13, name: \"std::str::pattern::Searcher::next_reject\" })",
55+
"FnDef(DefId { id: 19, name: \"std::str::pattern::Searcher::next\" })",
56+
"FnDef(DefId { id: 12, name: \"std::str::pattern::Pattern::into_searcher\" })"
4857
]
4958
},
5059
{
@@ -53,7 +62,15 @@ fn standard_proof() {
5362
"func": "pub fn top_level() {\n m::func1();\n}",
5463
"callees": [
5564
"FnDef(DefId { id: 4, name: \"m::func1\" })",
56-
"FnDef(DefId { id: 8, name: \"core::str::<impl str>::trim\" })"
65+
"FnDef(DefId { id: 8, name: \"core::str::<impl str>::trim\" })",
66+
"FnDef(DefId { id: 9, name: \"core::str::<impl str>::trim_matches\" })",
67+
"FnDef(DefId { id: 15, name: \"core::str::<impl str>::get_unchecked\" })",
68+
"FnDef(DefId { id: 16, name: \"std::slice::SliceIndex::get_unchecked\" })",
69+
"FnDef(DefId { id: 14, name: \"std::str::pattern::ReverseSearcher::next_reject_back\" })",
70+
"FnDef(DefId { id: 18, name: \"std::str::pattern::ReverseSearcher::next_back\" })",
71+
"FnDef(DefId { id: 13, name: \"std::str::pattern::Searcher::next_reject\" })",
72+
"FnDef(DefId { id: 19, name: \"std::str::pattern::Searcher::next\" })",
73+
"FnDef(DefId { id: 12, name: \"std::str::pattern::Pattern::into_searcher\" })"
5774
]
5875
},
5976
{
@@ -62,7 +79,14 @@ fn standard_proof() {
6279
"func": "pub fn func1() {\n let _a = \"\".trim();\n }",
6380
"callees": [
6481
"FnDef(DefId { id: 8, name: \"core::str::<impl str>::trim\" })",
65-
"FnDef(DefId { id: 9, name: \"core::str::<impl str>::trim_matches\" })"
82+
"FnDef(DefId { id: 9, name: \"core::str::<impl str>::trim_matches\" })",
83+
"FnDef(DefId { id: 15, name: \"core::str::<impl str>::get_unchecked\" })",
84+
"FnDef(DefId { id: 16, name: \"std::slice::SliceIndex::get_unchecked\" })",
85+
"FnDef(DefId { id: 14, name: \"std::str::pattern::ReverseSearcher::next_reject_back\" })",
86+
"FnDef(DefId { id: 18, name: \"std::str::pattern::ReverseSearcher::next_back\" })",
87+
"FnDef(DefId { id: 13, name: \"std::str::pattern::Searcher::next_reject\" })",
88+
"FnDef(DefId { id: 19, name: \"std::str::pattern::Searcher::next\" })",
89+
"FnDef(DefId { id: 12, name: \"std::str::pattern::Pattern::into_searcher\" })"
6690
]
6791
}
6892
]"##]].assert_eq(&stdout);

0 commit comments

Comments
 (0)