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

Generic consts #2424

Open
SoniEx2 opened this issue Apr 28, 2018 · 9 comments
Open

Generic consts #2424

SoniEx2 opened this issue Apr 28, 2018 · 9 comments
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.

Comments

@SoniEx2
Copy link

SoniEx2 commented Apr 28, 2018

Not to be confused with const generics, but I'll use both to describe the idea.

Let's say you have a const initializer and you want it to be different for every type:

const NONE_T_8ARRAY<T>: [Option<T>; 8] = [None; 8];

This is the basic generic const construct. Ofc, if you want length also specified:

const NONE_T_ARRAY<T, const L: usize>: [Option<T>; L] = [None; L];

This creates an array of size L containing only None.

Ofc, you also don't need to use types, consts are fine too:

const SQUARE<const X: usize>: usize = X * X;

But perhaps you want it to be recursive:

const POW<const X: usize, 0>: usize = 1;
const POW<const X: usize, const Y: usize>: usize = X * POW<X, Y-1>;

And you want to calculate Pi with it [1]:

const POW<const X: usize, 0>: usize = 1;
const POW<const X: usize, const Y: usize>: usize = X * POW<X, Y-1>;
const PI<-1>: f64 = 0;
const PI<const N: isize>: f64 = (1.0/POW<16, N as usize> * (4.0/(8*N + 1.0) - 2.0/(8*N + 4.0) - 1.0/(8*N + 5.0) - 1.0/(8*N + 6.0))) + PI<N-1>;

And things of the sort.

Yeah... they'd be nice.

May we have them?

@CryZe
Copy link

CryZe commented Apr 28, 2018

How does this differ from const fn?

@Centril Centril added the T-lang Relevant to the language team, which will review and decide on the RFC. label Apr 28, 2018
@SoniEx2
Copy link
Author

SoniEx2 commented Apr 28, 2018

And if you want to use it in a runtime context, altho the types have to be evaluated at compile-time, you can use use x:

const POW<const X: usize, 0>: usize = 1;
const POW<const X: usize, const Y: usize>: usize = X * POW<X, Y-1>;

fn do_something(x: usize, y: usize) -> usize {
    POW<use x, use y>
}

It's not different from const fn - it replaces const fn. The ability to use like that makes const vs non-const explicit:

fn do_something(x: usize) -> usize {
    POW<use x, 3> // expands/unrolls to x*x*x. this is inherently more flexible than const fn.
}

fn do_something_else(x: usize) -> usize {
    POW<use x, use 3> // recurses at runtime (may be unrolled by LLVM tho)
}

(Altho the idea of use x is controversial so I didn't put it in the main issue body thing or w/e it's called)

@clarfonthey
Copy link
Contributor

I do think that the ability to coerce literals into multiple types without macros would be very useful. Not sure if this is the answer, though.

@alexchandel
Copy link

This doesn't replace the "type level integers" portion of #1038, so there are currently no RFCs for type level integers, right? (beyond the existing ways to hack them in)

@steveklabnik
Copy link
Member

steveklabnik commented Oct 17, 2018 via email

@emanuelpalm
Copy link

I would like to have this in order to be able to return a static array with the same number of arguments as was provided in a static input array, like so:

fn do_something<N>(elements: [isize; N]) -> [usize; N] {
  // Implement, somehow ...
}

Is that something you would be able to do with const fns?

@SoniEx2
Copy link
Author

SoniEx2 commented Apr 13, 2019

@emanuelpalm that's const generics (consts in generics i.e. <const FOO: T>), not generic consts (consts with generics i.e. const FOO<T>)

@emanuelpalm
Copy link

@SoniEx2 Oh. True. I came here via some other issue, and I guess I didn't read the description properly. :P

@zesterer
Copy link

zesterer commented Jun 17, 2019

Here:

const POW<const X: usize, 0>: usize = 1;
const POW<const X: usize, const Y: usize>: usize = X * POW<X, Y-1>;

fn do_something(x: usize, y: usize) -> usize {
    POW<use x, use y>
}

You seem to be coercing a value known only at runtime into a const value. This simply isn't possible since Rust doesn't support that sort of runtime reflection capability once compiled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
T-lang Relevant to the language team, which will review and decide on the RFC.
Projects
None yet
Development

No branches or pull requests

8 participants