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

No way to get compile-time info from the type of local. #88531

Open
m-ou-se opened this issue Aug 31, 2021 · 6 comments
Open

No way to get compile-time info from the type of local. #88531

m-ou-se opened this issue Aug 31, 2021 · 6 comments
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.

Comments

@m-ou-se
Copy link
Member

m-ou-se commented Aug 31, 2021

const fn bla<T>(_: &T) -> usize { type_name::<T>().len() }

fn z(_: &'static [usize]) {}

fn f() {
    let x = read_integer_or_whatever();
    z(&[bla(&x)]); // This line is expanded from a macro, e.g. something like `format_args!()`
}

This doesn't work. There's no way to express here that the value of x is entirely irrelevant, and that bla only cares about the type of the argument.

If we had a magic PhantomData::of(x) that would work in const contexts regardless of whether x itself is const, we could do things like this:

impl<T> PhantomData<T> {
    #[lang = "magic"]
    const fn of(_: &T) -> Self { Self }
}

const fn bla<T>(_: PhantomData<T>) -> usize { type_name::<T>().len() }

fn z(_: &'static [usize]) {}

fn f() {
    let x = read_integer_or_whatever();
    z(&[bla(PhantomData::of(&x))]);
}
@m-ou-se m-ou-se added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. C-feature-request Category: A feature request, i.e: not implemented / a PR. labels Aug 31, 2021
@m-ou-se
Copy link
Member Author

m-ou-se commented Aug 31, 2021

cc @oli-obk @eddyb

@m-ou-se
Copy link
Member Author

m-ou-se commented Aug 31, 2021

The more 'obvious' alternative is typeof:

const fn bla<T>() -> usize { type_name::<T>().len() }

fn z(_: &'static [usize]) {}

fn f() {
    let x = read_integer_or_whatever();
    z(&[bla::<typeof(x)>()]);
}

But I've been told that typeof does not and will probably never work on locals like that.

@SkiFire13
Copy link
Contributor

SkiFire13 commented Aug 31, 2021

You can kind of emulate typeof with type_alias_impl_trait, in particular this compiles on nightly:

#![feature(const_type_name)]
#![feature(type_alias_impl_trait)]

use core::any::type_name;

fn read_integer_or_whatever() -> i32 { todo!() }

const fn bla<T>() -> usize { type_name::<T>().len() }

fn z(_: &'static [usize]) {}

fn f() {
    let x = read_integer_or_whatever();
    
    // Here's where the magic happens:
    type TypeOfX = impl Sized;
    if false {
        let _def_use = move || -> TypeOfX { x };
        loop {}
    }

    // Note that `z(&[bla::<i32>()])` also doesn't work because
    // calls to const fns are not static promoted
    const B: usize = bla::<TypeOfX>();
    z(&[B]);
}

@oli-obk
Copy link
Contributor

oli-obk commented Aug 31, 2021

unknown

@rodrimati1992
Copy link
Contributor

As far as I know, there's no equivalent of this with TAIT:

let foo = 0i32;
let bar: typeof foo = 100;
[foo, bar];

@kanashimia
Copy link

So apparently with trait solver next globally #107374 -Znext-solver=globally you can ACTUALLY implement typeof:

#![feature(type_alias_impl_trait)]
#![allow(unused)]
struct Foo {
    x: u32,
    y: u32,
}

fn main() {
    let x = Foo { x: 1, y: 2 };
    
    type TypeOfX = impl Sized;
    
    if false {
        let _def_use = move || -> TypeOfX { x }; 
        loop {}
    }
    
    let c = TypeOfX { x: 1, y: 2 };
}

Image

TypeOfX is not an opaque type anymore.

And I think this is a feature, not a bug.
So you can actually emulate inferred type names _ { x: 1, y: 2 } like that for example.

Found this based on this doc: https://hackmd.io/@impl-trait-everywhere/S1lO4jy86

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-feature-request Category: A feature request, i.e: not implemented / a PR. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants