Skip to content

Function path is stripped of root for local crateΒ #109

@zjp-CN

Description

@zjp-CN

Problem

The .name() API doc indicates returned path is absolute, however, it's not true because for local functions ("local" means that the crate is being compiled), the fn name doesn't include crate root.

Retrieve the instance name for diagnostic messages.
This will return the specialized name, e.g., std::vec::Vec::new.
src: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_public/mir/mono/struct.Instance.html#method.name

(local ) [test    ] a                              - (instance) a // NOT test::a πŸ’₯
(local ) [test    ] b                              - (instance) b // NOT test::b πŸ’₯
(extern) [std     ] std::rt::__rust_abort          - (instance) std::rt::__rust_abort
(extern) [std     ] std::rt::handle_rt_panic       - (instance) Item requires monomorphization
(extern) [core    ] core::contracts::build_check_ensures - (instance) Item requires monomorphization
(extern) [core    ] core::f128::<impl f128>::is_nan - (instance) core::f128::<impl f128>::is_nan

That brings a problem when libcore is compiled directly with smir to get names like
num::nonzero::<impl convert::From<num::nonzero::NonZero<u64>> for u64>::from,
in which num and convert are submodules in core rather than external crates.

You may argue that the path is for diagnostics, thus slimmed local item names are fine, but it'd be good for smir to make a good uniform path in a less surprising manner. This can be even quite troublesome for quering because fn names from local and external crates need to be carefully handled.

I think the ideal solution may have a dedicated (typed) ItemPath API. The above fn path invloves module path, trait path, and struct path. cc #68

Maybe the current only choice is resorting to internal DefPath.

Reproduce

Details

$ cat test.rs
pub fn a() {}
fn b() {}

$ export LD_LIBRARY_PATH=$(rustc --print sysroot)/lib
$ ./target/debug/smir-fn-name --crate-type=lib test.rs
// smir-fn-name/src/main.rs
#![feature(rustc_private)]

extern crate rustc_driver;
extern crate rustc_interface;
extern crate rustc_middle;
extern crate rustc_public;

use rustc_public::{mir::mono::Instance, ty::FnDef, CrateDef, CrateItem};

fn main() {
    let args: Vec<_> = std::env::args().collect();
    _ = rustc_public::run!(&args, || {
        analyze();
        ControlFlow::<(), ()>::Break(())
    });
}

fn analyze() {
    let local_crate = rustc_public::local_crate();
    let crate_name = &*local_crate.name;
    for f in local_crate.fn_defs() {
        let inst_name = name_from_instance(&f);
        println!(
            "(local ) [{crate_name:8}] {:30} - (instance) {inst_name}",
            f.name()
        );
    }

    for extern_krate in rustc_public::external_crates() {
        let root = &*extern_krate.name;
        for f in extern_krate.fn_defs().iter().take(2) {
            let inst_name = name_from_instance(f);
            println!(
                "(extern) [{root:8}] {:30} - (instance) {inst_name}",
                f.name()
            );
        }
    }
}

fn name_from_instance(f: &FnDef) -> String {
    Instance::try_from(CrateItem(f.def_id()))
        .map(|inst| inst.name())
        .unwrap_or_else(|err| err.to_string())
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions