Rust: type_name intrinsic returns fully qualified pathes

Created on 29 Jun 2016  路  11Comments  路  Source: rust-lang/rust

The type_name intrinsic name implies that the function should only return the name of type, however it returns a fully qualified path of the type.

Try this:

#![feature(core_intrinsics)]

use std::intrinsics::type_name;

fn main(){ 
    let vec: Option<Vec<bool>> = Some(vec![]);
    println!("{}", unsafe { type_name::<Option<Vec<bool>>>() });
}

Expected Option<Vec<bool>>, got std::option::Option<std::vec::Vec<bool>>.

C-feature-request T-compiler

Most helpful comment

So ideally the intrinsic would eventually return data about the type in a structured way. Could be something as simple as struct Ty { name: &str, path: &str, generic_args: &[Ty], lifetimes: &[&str], ... }. I鈥檓 pretty sure this is written down somewhere else already, but I can鈥檛 remember where.

A Display impl for this type could then be used to retrieve the original fully qualified form.

All 11 comments

I feel like this isn't a bad thing. Fully qualified paths seem somewhat more useful. @nagisa Is there a specific reason other than the name that you wanted non-qualified paths?

IMHO at this point the issue should serve as an "tracking" issue for type_name intrinsic redesign, which it badly needs.

As for specific reasons, we used this intrinsic like this in the compiler to automatically derive the name of MIR passes and, obviously, nobody wants to see the crate name prefix in those. We had to hack it with some quick'n'dirty string manipulation.

Could you provide a list of things that would be preferable over the existing type_name output, in the original issue description? That would help make this bug more helpful to those visiting it, so that others may be able to help out and make this happen or people visiting for triage could diagnose whether this has happened.

So ideally the intrinsic would eventually return data about the type in a structured way. Could be something as simple as struct Ty { name: &str, path: &str, generic_args: &[Ty], lifetimes: &[&str], ... }. I鈥檓 pretty sure this is written down somewhere else already, but I can鈥檛 remember where.

A Display impl for this type could then be used to retrieve the original fully qualified form.

@nagisa I'm poking some at this.

I don't see any existing intrinsic in libcore/intrinsics.rs that returns anything other than a boolean, number, given generic, pointer (to given generic), or 2-tuple of the above. Is it possible for an intrinsic to return more complicated information?

Putting down some of the information I dug around for so I can find it again:

So what I'd imagine is that we had a bunch of intrinsics for the individual bits (of which many exist already in some form) and then there'd be a wrapper struct, maybe in std::any, that calls the individual intrinsics and exposes a safe, but unstable, API. Then we could iterate further on that.

I don't think we should try to make an intrinsic return a struct, though I do believe it to be possible, since that seems unlikely to be a good approach; it makes it hard to interpret what the fields are to outside users'.

Unless I missed something, the only current intrinsics that return type information are type_id and type_name.

It's a little wasteful, but given just the fully-qualified version, a consumer could use syn to break it up into parts if needed.

That's true. Or even just split("::") would probably work. @nagisa might have comments as to if that's sufficient or not... I'd lean towards no.

This issue is about specifically redesigning the intrinsic. The intrinsic would be best off implemented as something that returns a tuple with all components, I think. The safe-wrapper would then put the data into fields of some named structure. It is true, that there aren't many intrinsics that would be as complicated as the structured type_name would end up being, so the implementation likely won鈥檛 be too easy.

Parsing strings is certainly not something we want to end up doing, because it is both inefficient and locks us into keeping the format of the string stable (not necessarily something we want). Besides, since this is an intrinsic, we can make it possible to implement Display/Debug, super efficiently (with a single write_str() call).

split("::")

As far as I can tell, this won't work if your type has generic parameters, because those also have a fqpn and you will get a very wrong result...

However, this works:

use regex::Regex;

let re = Regex::new( r"\w+::" ).unwrap();

let s = re.replace_all( name, "" );

Not sure if syn would be faster.

Was this page helpful?
0 / 5 - 0 ratings