Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tracking issue for any::type_name_of_val #66359

Closed
1 task
lcnr opened this issue Nov 13, 2019 · 17 comments
Closed
1 task

Tracking issue for any::type_name_of_val #66359

lcnr opened this issue Nov 13, 2019 · 17 comments
Labels
B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.

Comments

@lcnr
Copy link
Contributor

lcnr commented Nov 13, 2019

#65961 added the function core::any::type_name_of_val.

Unresolved issues:

  • type_name_of_val(&val) is quite verbose, type_name_of(&val) might be better, even if align_of, align_of_val and size_of and size_of_val already exist.
@Centril Centril added T-libs-api Relevant to the library API team, which will review and decide on the PR/issue. B-unstable Blocker: Implemented in the nightly compiler and unstable. requires-nightly This issue requires a nightly compiler in some way. labels Nov 13, 2019
@Dylan-DPC-zz

This comment has been minimized.

@Globidev
Copy link

It might be worth considering adding a note about the usage of dyn Traits with that function.

core::mem::size_of_val will actually inspect a DST's metadata to return an appropriate value for the size but core::any::type_name_of_val cannot do the same since AFAIK vtables include size and alignment information, but no type name.

Some users might get confused as to why type_name_of_val(&some_dyn_foo) returns "dyn Foo" and not the actual type name of the unsized type

Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue Jan 18, 2020
Centril added a commit to Centril/rust that referenced this issue Jan 18, 2020
@JohnTitor JohnTitor added the C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. label Feb 28, 2020
@lcnr
Copy link
Contributor Author

lcnr commented Mar 14, 2020

used in a question on reddit

@KodrAus KodrAus added Libs-Small Libs issues that are considered "small" or self-contained Libs-Tracked Libs issues that are tracked on the team's project board. labels Jul 29, 2020
@Fishrock123
Copy link
Contributor

Would something like type_name_dynamic() be acceptable? Right now I am literally just copying rustc's existing impl into my code, haha.

@lcnr
Copy link
Contributor Author

lcnr commented Oct 8, 2020

One big issue of type_name_of_val is that it does not look into trait objects, so for example

#![feature(type_name_of_val)]

fn main() {
    let x: u32 = 3;
    let y: &dyn Send = &x;
    println!("{}", std::any::type_name_of_val(y)); // prints something like 'dyn Send'
}

I think dynamic quite strongly implies that it does look into trait objects so I don't feel like this name would be a good fit here

@Fishrock123
Copy link
Contributor

Perhaps type_name_of_generic()?

Or are we saying that this should be changed to get type name form dynamic objects at runtime?

@lcnr
Copy link
Contributor Author

lcnr commented Oct 13, 2020

getting the type name at runtime isn't really possible without having a non zero cost even for programs never using type_name_of_val

type_name_of_generic is even more verbose than type_name_of_val so I personally do not prefer it. Don't really care about this though

@Fishrock123
Copy link
Contributor

Perhaps type_name_of, and then in a theoretical future type_name_of_val could do the dynamic thing.

@mehcode
Copy link
Contributor

mehcode commented May 9, 2022

Just tried to use this for what it says on the tin. It wasn't able to work for my situation. I'm trying to print the type name of a partially-moved struct.

type_name_of_val(&expr);
error[E0382]: borrow of partially moved value: `expr`

Does this need to be compiler magic to let this work?

@Globidev
Copy link

@mehcode
This is indeed a general issue with partially moved values: you cannot create a reference to one
&expr would always be invalid and yield that error, regardless of the surrounding context.
it would also probably lead to more confusion if we were to somehow allow this to work in this particular case

@danielhenrymantilla
Copy link
Contributor

@mehcode you can write the following helper to let you query the type name of an unusable binding:

macro_rules! type_name_of {( $e:expr $(,)? ) => ({
    let it = [];
    #[allow(unreachable_code)] {
        if false {
            loop {} // disables borrowck and dropck
            (&mut { it })[0] = &$e; // nudges type inference
        }
    }
    $crate::__helper__(it)
})} pub(in crate) use type_name_of;

#[doc(hidden)] pub
fn __helper__<T> (_: [&T; 0])
  -> &'static str
{
    ::core::any::type_name::<T>()
}

With it, the following snippet compiles and runs fine:

let it = (vec![()], 42);
drop(it.0);
dbg!(type_name_of!(it));

@tgross35
Copy link
Contributor

tgross35 commented Sep 14, 2023

Is the only blocker here naming? It seems like type_name_of_val and type_name_of are the two possibilities. std::mem::{align_of_val, size_of_val} do use of_val, but their base names also already have _of so there is already a difference (this base function is type_name not type_name_of).

I don't think that there is much we would want to do for arbitrary &dyn without adding some amount of bloat to trait objects. This seems better as a helper trait:

trait AnyNamed {
    fn name(&self) -> &'static str {
        std::any::type_name::<Self>()
    }
}

impl<T: ?Sized> AnyNamed for T {}

fn type_name_dyn(val: &dyn AnyNamed) {
    println!("{}", val.name());
}

fn main() {
    type_name_dyn(&"abcd".to_owned()); // alloc::string::String
    type_name_dyn(&100u8); // u8
    type_name_dyn(&10.0f32); // f32
}

Or, if you only need a few types you can just check if your &dyn Any matches one

macro_rules! dyn_impl {
    ($val:ident, $($ty:ty),*) => { $(
        if $val.is::<$ty>() {
            stringify!($ty)
        } else )* {
            "unknown"
    }}
}

fn type_name_dyn(val: &dyn std::any::Any) {
    let name = dyn_impl!(val, String, u8, f32);
    println!("{name}");
}

fn main() {
    type_name_dyn(&"abcd".to_owned()); // String
    type_name_dyn(&100u8); // u8
    type_name_dyn(&10.0f32); // f32
    type_name_dyn(&"abcd"); // unknown
}

tgross35 added a commit to tgross35/rust that referenced this issue Nov 24, 2023
Make the following API stable:

    // in core::any
    pub fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str

Const stability is not added because this relies on `type_name` which is also
not const. That has a blocking issue.

Fixes rust-lang#66359
@tgross35
Copy link
Contributor

I created a stabilization PR at #118234

@dtolnay dtolnay removed requires-nightly This issue requires a nightly compiler in some way. Libs-Tracked Libs issues that are tracked on the team's project board. Libs-Small Libs issues that are considered "small" or self-contained labels Nov 25, 2023
@dtolnay
Copy link
Member

dtolnay commented Nov 25, 2023

@rust-lang/libs-api:
@rfcbot fcp merge

https://doc.rust-lang.org/nightly/core/any/fn.type_name_of_val.html

Context: this function is intended to be useful when you have a value whose type cannot be named in Rust code, so directly calling type_name::<T>() is not straightforward. Examples: function objects, or impl Trait values.

fn main() {
    println!("{}", type_name_of_val(&main));  // "playground::main"
    f(false);
}

fn f(asdf: impl Display) {
    println!("{}", type_name_of_val(&asdf));  // "bool"
}

Stabilizing type_name_of_val does not add any expressiveness, since it is a trivial wrapper that is easy to implement yourself. We would only be adding convenience. People needing type_name_of_val today wouldn't be desperate to get this stabilized in core, since they would just be writing their own:

fn type_name_of_val<T: ?Sized>(_: &T) -> &'static str {
    type_name::<T>()
}

Notes from @tgross35 in #118234 (comment):

Naming: type_name_of and type_name_of_val seem like the only mentioned options. Differences in opinion here come from std::mem::{size_of, align_of, size_of_val, align_of_val}. This PR leaves the name as type_name_of_val, but I can change if desired since it is pretty verbose.

What this displays for &dyn: I don't think that having type_name_of_val function resolve those is worth the headache it would be, see #66359 (comment) for some workarounds. I also amended the docs wording to leave it open-ended, in case we have means to change that behavior in the future.

Const stability is not added because this relies on type_name which is also not const. That has a blocking issue #97156.

@rfcbot
Copy link

rfcbot commented Nov 25, 2023

Team member @dtolnay has proposed to merge this. The next step is review by the rest of the tagged team members:

No concerns currently listed.

Once a majority of reviewers approve (and at most 2 approvals are outstanding), this will enter its final comment period. If you spot a major issue that hasn't been raised at any point in this process, please speak up!

See this document for info about what commands tagged team members can give me.

@rfcbot rfcbot added proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. labels Nov 25, 2023
tgross35 added a commit to tgross35/rust that referenced this issue Nov 25, 2023
Make the following API stable:

    // in core::any
    pub fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str

Const stability is not added because this relies on `type_name` which is also
not const. That has a blocking issue.

Fixes rust-lang#66359
@rfcbot rfcbot added final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. and removed proposed-final-comment-period Proposed to merge/close by relevant subteam, see T-<team> label. Will enter FCP once signed off. labels Dec 5, 2023
@rfcbot
Copy link

rfcbot commented Dec 5, 2023

🔔 This is now entering its final comment period, as per the review above. 🔔

@rfcbot rfcbot added finished-final-comment-period The final comment period is finished for this PR / Issue. to-announce Announce this issue on triage meeting and removed final-comment-period In the final comment period and will be merged soon unless new substantive objections are raised. labels Dec 15, 2023
@rfcbot
Copy link

rfcbot commented Dec 15, 2023

The final comment period, with a disposition to merge, as per the review above, is now complete.

As the automated representative of the governance process, I would like to thank the author for their work and everyone else who contributed.

This will be merged soon.

matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Dec 15, 2023
…lnay

Stabilize `type_name_of_val`

Make the following API stable:

```rust
// in core::any
pub fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str
```

This is a convenience method to get the type name of a value, as opposed to `type_name` that takes a type as a generic.

Const stability is not added because this relies on `type_name` which is also not const. That has a blocking issue rust-lang#97156.

Wording was also changed to direct most of the details to `type_name` so we don't have as much duplicated documentation.

Fixes tracking issue rust-lang#66359.

There were two main concerns in the tracking issue:

1. Naming: `type_name_of` and `type_name_of_val` seem like the only mentioned options. Differences in opinion here come from `std::mem::{size_of, align_of, size_of_val, align_of_val}`. This PR leaves the name as `type_name_of_val`, but I can change if desired since it is pretty verbose.
2. What this displays for `&dyn`: I don't think that having `type_name_of_val` function resolve those is worth the headache it would be, see rust-lang#66359 (comment) for some workarounds. I also amended the docs wording to leave it open-ended, in case we have means to change that behavior in the future.

`@rustbot` label -T-libs +T-libs-api +needs-fcp
r? libs-api
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this issue Dec 15, 2023
…lnay

Stabilize `type_name_of_val`

Make the following API stable:

```rust
// in core::any
pub fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str
```

This is a convenience method to get the type name of a value, as opposed to `type_name` that takes a type as a generic.

Const stability is not added because this relies on `type_name` which is also not const. That has a blocking issue rust-lang#97156.

Wording was also changed to direct most of the details to `type_name` so we don't have as much duplicated documentation.

Fixes tracking issue rust-lang#66359.

There were two main concerns in the tracking issue:

1. Naming: `type_name_of` and `type_name_of_val` seem like the only mentioned options. Differences in opinion here come from `std::mem::{size_of, align_of, size_of_val, align_of_val}`. This PR leaves the name as `type_name_of_val`, but I can change if desired since it is pretty verbose.
2. What this displays for `&dyn`: I don't think that having `type_name_of_val` function resolve those is worth the headache it would be, see rust-lang#66359 (comment) for some workarounds. I also amended the docs wording to leave it open-ended, in case we have means to change that behavior in the future.

``@rustbot`` label -T-libs +T-libs-api +needs-fcp
r? libs-api
@bors bors closed this as completed in b225aab Dec 15, 2023
rust-timer added a commit to rust-lang-ci/rust that referenced this issue Dec 15, 2023
Rollup merge of rust-lang#118234 - tgross35:type_name_of_value, r=dtolnay

Stabilize `type_name_of_val`

Make the following API stable:

```rust
// in core::any
pub fn type_name_of_val<T: ?Sized>(_val: &T) -> &'static str
```

This is a convenience method to get the type name of a value, as opposed to `type_name` that takes a type as a generic.

Const stability is not added because this relies on `type_name` which is also not const. That has a blocking issue rust-lang#97156.

Wording was also changed to direct most of the details to `type_name` so we don't have as much duplicated documentation.

Fixes tracking issue rust-lang#66359.

There were two main concerns in the tracking issue:

1. Naming: `type_name_of` and `type_name_of_val` seem like the only mentioned options. Differences in opinion here come from `std::mem::{size_of, align_of, size_of_val, align_of_val}`. This PR leaves the name as `type_name_of_val`, but I can change if desired since it is pretty verbose.
2. What this displays for `&dyn`: I don't think that having `type_name_of_val` function resolve those is worth the headache it would be, see rust-lang#66359 (comment) for some workarounds. I also amended the docs wording to leave it open-ended, in case we have means to change that behavior in the future.

``@rustbot`` label -T-libs +T-libs-api +needs-fcp
r? libs-api
@apiraino apiraino removed the to-announce Announce this issue on triage meeting label Dec 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B-unstable Blocker: Implemented in the nightly compiler and unstable. C-tracking-issue Category: A tracking issue for an RFC or an unstable feature. disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. finished-final-comment-period The final comment period is finished for this PR / Issue. T-libs-api Relevant to the library API team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests