How to identify a specific library function call in the mir

Hello,
I would like to identify a specific library function call in mir. In specific, I want to identify the <std::ops::Range<usize> as iter::range::RangeIteratorImpl>::spec_next(). I thought I could get this function's def_id, and then use tcx.def_path_str to get the function name.
This is the code piece I used.

if let Some(Terminator{kind: TerminatorKind::Call { func, .. }, ..}) = &bbData.terminator {
   if let Operand::Constant(box constant) = func { 
      if let ConstantKind::Val(_, ty) = constant.literal {
         if let ty::FnDef(did, _) = &ty.kind() {
            if tcx.def_path_str(*did).contains("spec_next") {
               debug!("true");
            }
         }
      }
   }
}

But it turn out to be:

error: internal compiler error: no warnings or errors encountered even though `delayed_good_path_bugs` issued

error: internal compiler error: trimmed_def_paths constructed but no error emitted; use `DelayDm` for lints or `with_no_trimmed_paths` for debugging

I wonder what's wrong with this code. And how can I identify the lib function properly.

Why are you trying to do this?

The answer depends on the goal. (As well as things like whether this is something you're trying to hack locally or something you want to upstream.)

I found that, bound checks in ‘for’ loop are not optimized out. And it’s probably because usage of iterator makes it hard to analysis range. I’m trying to implement a mir pass to identify this pattern and try to eliminate some bound checks. For now, it’s just a toy for me to explore rustc.

If it's one of the LangItem in rustc_hir::lang_items - Rust (a bunch of iterator-related things already are because they're used in the desugar) then you can get them via https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/context/struct.TyCtxt.html#method.require_lang_item. Or you can see something's from a for loop via https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/hygiene/enum.DesugaringKind.html#variant.ForLoop.

If that doesn't do what you need, the most expedient way for a local experiment is to use Diagnostic items - Rust Compiler Development Guide.

(Also, consider rewriting your function slightly to help out LLVM. It often can optimize out indexing just fine, with a bit of help, like in Why can't rustc optimize out bounds checks in this code? - #3 by scottmcm. What's the code you're using that's not optimizing currently? Odds are that anything that you successfully can optimize in MIR is something that LLVM can already do without too many contortions -- MIR is much less amenable to optimizations than LLVM-IR's SSA.)

Thanks for your advice, I'm not sure I'm doing it right.

I checked the LangItem, but it's not in there. The one I'm try to find is DefId(2:6672 ~ core[5f83]::iter::range::RangeIteratorImpl::spec_next). But I didn't find something like this. (LangItem::IntoIterIntoIter and LangItem::IteratorNext have different DefIDs)

And I tried to use get_diagnostic_name to get the diagnostic name, but it returns None. I guess it means it's not a Diagnostic items.

Any suggestions?

I'm using the bubble sort.

pub fn bubble_sort<T: Ord>(arr: &mut [T]) {
    for i in 0..arr.len() {
        for j in 0..arr.len() - 1 - i {
            if arr[j] > arr[j + 1] {
                arr.swap(j, j + 1);
            }
        }
    }
}

If changing for loop to while loop, the bound checks can be indeed optimized out. I guess it's because of the usage of iterator when translating for loop. So I'm trying to implement a mir pass to help with this situation. ( I'm new to rust, and I'm still struggling to work on Rustc. I hope I'm doing it right. )

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.