fn find_blocks_calling_self<'tcx>(
    tcx: TyCtxt<'tcx>,
    body: &Body<'tcx>,
    def_id: DefId,
) -> BitSet<BasicBlock> {
    let param_env = tcx.param_env(def_id);

    // If this is trait/impl method, extract the trait's substs.
    let trait_substs_count = match tcx.opt_associated_item(def_id) {
        Some(AssocItem { container: AssocItemContainer::TraitContainer(trait_def_id), .. }) => {
            tcx.generics_of(trait_def_id).count()
        }
        _ => 0,
    };
    let trait_substs = &InternalSubsts::identity_for_item(tcx, def_id)[..trait_substs_count];

    let mut self_calls = BitSet::new_empty(body.basic_blocks().len());

    for (bb, data) in body.basic_blocks().iter_enumerated() {
        if let TerminatorKind::Call { func, .. } = &data.terminator().kind {
            let func_ty = func.ty(body, tcx);

            if let ty::FnDef(fn_def_id, substs) = func_ty.kind {
                let (call_fn_id, call_substs) =
                    if let Some(instance) = Instance::resolve(tcx, param_env, fn_def_id, substs) {
                        (instance.def_id(), instance.substs)
                    } else {
                        (fn_def_id, substs)
                    };

                // FIXME(#57965): Make this work across function boundaries

                // If this is a trait fn, the substs on the trait have to match, or we might be
                // calling into an entirely different method (for example, a call from the default
                // method in the trait to `<A as Trait<B>>::method`, where `A` and/or `B` are
                // specific types).
                let is_self_call =
                    call_fn_id == def_id && &call_substs[..trait_substs.len()] == trait_substs;

                if is_self_call {
                    self_calls.insert(bb);
                }
            }
        }
    }

    self_calls
}
/// Finds blocks with `Call` terminators that would end up calling back into the same method.
Finds blocks with `Call` terminators that would end up calling back into the same method.
Finds blocks with ` Call ` terminators that would end up calling back into the same method .
fn find_blocks_calling_self<'tcx>(
    tcx: TyCtxt<'tcx>,
    body: &Body<'tcx>,
    def_id: DefId,
) -> BitSet<BasicBlock> {
    let param_env = tcx.param_env(def_id);
    // If this is trait/impl method, extract the trait's substs.
    let trait_substs_count = match tcx.opt_associated_item(def_id) {
        Some(AssocItem { container: AssocItemContainer::TraitContainer(trait_def_id), .. }) => {
            tcx.generics_of(trait_def_id).count()
        }
        _ => 0,
    };
    let trait_substs = &InternalSubsts::identity_for_item(tcx, def_id)[..trait_substs_count];
    let mut self_calls = BitSet::new_empty(body.basic_blocks().len());
    for (bb, data) in body.basic_blocks().iter_enumerated() {
        if let TerminatorKind::Call { func, .. } = &data.terminator().kind {
            let func_ty = func.ty(body, tcx);
            if let ty::FnDef(fn_def_id, substs) = func_ty.kind {
                let (call_fn_id, call_substs) =
                    if let Some(instance) = Instance::resolve(tcx, param_env, fn_def_id, substs) {
                        (instance.def_id(), instance.substs)
                    } else {
                        (fn_def_id, substs)
                    };
                // FIXME(#57965): Make this work across function boundaries
                // If this is a trait fn, the substs on the trait have to match, or we might be
                // calling into an entirely different method (for example, a call from the default
                // method in the trait to `<A as Trait<B>>::method`, where `A` and/or `B` are
                // specific types).
                let is_self_call =
                    call_fn_id == def_id && &call_substs[..trait_substs.len()] == trait_substs;
                if is_self_call {
                    self_calls.insert(bb);
                }
            }
        }
    }
    self_calls
}
fn find_blocks_calling_self < ' tcx > ( tcx : TyCtxt < ' tcx > , body : & Body < ' tcx > , def_id : DefId , ) -> BitSet < BasicBlock > { let param_env = tcx . param_env ( def_id ) ; // If this is trait/impl method, extract the trait's substs. let trait_substs_count = match tcx . opt_associated_item ( def_id ) { Some ( AssocItem { container : AssocItemContainer :: TraitContainer ( trait_def_id ) , .. } ) => { tcx . generics_of ( trait_def_id ) . count ( ) } _ => 0 , } ; let trait_substs = & InternalSubsts :: identity_for_item ( tcx , def_id ) [ .. trait_substs_count ] ; let mut self_calls = BitSet :: new_empty ( body . basic_blocks ( ) . len ( ) ) ; for ( bb , data ) in body . basic_blocks ( ) . iter_enumerated ( ) { if let TerminatorKind :: Call { func , .. } = & data . terminator ( ) . kind { let func_ty = func . ty ( body , tcx ) ; if let ty :: FnDef ( fn_def_id , substs ) = func_ty . kind { let ( call_fn_id , call_substs ) = if let Some ( instance ) = Instance :: resolve ( tcx , param_env , fn_def_id , substs ) { ( instance . def_id ( ) , instance . substs ) } else { ( fn_def_id , substs ) } ; // FIXME(#57965): Make this work across function boundaries // If this is a trait fn, the substs on the trait have to match, or we might be // calling into an entirely different method (for example, a call from the default // method in the trait to `<A as Trait<B>>::method`, where `A` and/or `B` are // specific types). let is_self_call = call_fn_id == def_id && & call_substs [ .. trait_substs . len ( ) ] == trait_substs ; if is_self_call { self_calls . insert ( bb ) ; } } } } self_calls }
Finds blocks with `Call` terminators that would end up calling back into the same method.
Finds blocks with ` Call ` terminators that would end up calling back into the same method .
tcx
TyCtxt<'tcx>
body
&Body<'tcx>
def_id
DefId
tcx
TyCtxt<'tcx>
body
&Body<'tcx>
def_id
DefId