-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
First-class compile time type manipulation #3669
Comments
Here are the ideas I had for how we could go about implementing this feature by feature. First, we could start by introducing const myXs: [i32] = [1, 2, 5]
// Standard const fn (all variables and parameters const)
const fn my_const_fn(xs: [i32], y: i32) -> i32 {
let sum: i32 = 0;
for x in xs {
sum += x;
}
return sum + y
}
// `my_const_fn(myXs, y)` not allowed unless y is const
// `my_const_fn(myXs, 6)` becomes `return (1 + 2 + 5) + 6 == 14` after compile time evaluation
// Non-const fn with const parameters
fn my_non_const_fn(const xs: [i32], y: i32) -> i32 {
// Can use const parameters within const blocks
return const {
let mut sum: i32 = 0;
for x in xs {
sum += x;
}
sum
} + y
}
// `my_non_const_fn(myXs, y)` is valid with non-const `y` and becomes `return (1 + 2 + 5) + y`
// `my_non_const_fn(myXs, 6)` becomes `return (1 + 2 + 5) + 6 == 14`, same as above The next step would involve allowing the generation of runtime code within compile time contexts. This allows one to put runtime code within an inline const block: fn runtime_in_const(const xs: [i32], ys: [i32]) -> i32 {
const {
for (i, x) in xs.enumerate() {
runtime {
if x > ys[i] {
return x;
}
}
}
}
return 0;
}
// runtime_in_const([1, 2], ys) would generate the following specialized function at runtime:
fn runtime_in_const_specialized(ys: [i32]) -> i32 {
if 1 > ys[0] {
return 1;
}
if 2 > ys[1] {
return 2;
}
return 0;
} The final step would be to reify types so they can be queried and manipulated in const contexts, and then provide a way to call a const fns on generic arguments to produce new type arguments. I'm still figuring out how this might look, but should start to resemble Zig. |
This comment was marked as off-topic.
This comment was marked as off-topic.
This would be closer to what we have (except const generics only takes integers, // Non-const fn with const parameters
fn my_non_const_fn<const XS: &'static [i32]>(y: i32) -> i32 {
let mut sum = 0;
let mut index = 0;
while index < XS.len() {
sum += XS[index];
index += 1;
}
sum + y
} |
Zig supports
comptime
, which is a keyword that allows for the evaluation of arbitrary expressions and entire functions at compile time. It is also used in Zig's implementation of generics, so that types can be manipulated at compile time to generate code. In particular, Zig supports the following compile time features:Rust has a few existing features that address compile-time code evaluation:
These are a few of the goals that could be addressed with compile-time code evaluation and type manipulation:
I have some ideas for how this could be implemented, but ultimately I wanted to build a path towards variadic generics through compile-time code evaluation and generation. There are many features we would need to expand on first before we could work on many of the features listed above, mostly around making const and generics more powerful in Rust. And we would need a way to manipulate types in const fns and return them to be used as generic arguments.
What are the community's thoughts about this as a future direction for Rust?
The text was updated successfully, but these errors were encountered: