You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
For loop range is unusable with types other than usize #17039
pubfnsprite(data: *constSprite, x: u8, y: u8) void {
std.debug.assert(x<=127);
std.debug.assert(y<=127);
for (data, 0..8) |column, sy| {
for (column, 0..8) |color, sx| {
if (x+sx>127ory+sy>127) break;
constsxc: u8=@intCast(sx);
constsyc: u8=@intCast(sy);
if (color!=transparency) pixel(sxc+x, syc+y, color);
}
}
}
where Sprite is [8][8]Color
(Ignore that the function has bugs, that's not really the point 🙂)
Doesn't matter if I use 0.. or 0..8 it still doesn't compile, as the range is seemingly inferred to be usize.
The only way to make it work is to use the two casts as shown in the function above to make the compiler happy.
This is annoying because this range is compile time known, so it should be clear it can fit in a u8.
I would also love to have more control over the index type.
However Andrew mentioned in a related proposal that there would be problems with the compiler implementation.
Oh well. is the problem just inference? Or is it not even possible to have the choice to manually choose what type the range is?
I know that overdoing inference can be exponentially bad, I have written statements in Swift before that just couldn't compile :)
(And I assume the same is true for Rust as it is very similar)
The only workaround I can think of is emulating a C style loop with a while loop, which would honestly be awful.
Either way this feels a bit out of character for a language sold on the level of control it provides.
Is there at least no performance cost when using @intCast?
@intCast works by employing safety-checked illegal behavior.
(Note: The name "undefined behavior" here is remnant C terminology and inaccurate; the langref should IMO be updated in this regard - but see also #2301 .)
The short explanation is that the compiler is told what behavior you expect (the value should fit into the target type), and other behavior is illegal.
In safe build modes (Debug and ReleaseSafe) and blocks with explicit safety, the overhead is that if the assumption turns out wrong, @panic is triggered, which prints a stack trace and aborts the program.
In unsafe build modes (ReleaseFast and ReleaseSmall), the compiler is allowed to rely on the provided assumption (that illegal behavior cannot occur). Usually this is used to optimize the program, i.e. the compiler tries to always improve performance, and should never penalize you for stating such assumptions. (This hasn't really been formalized yet though.)
Technically you could find some performance cost for originally allocating the usize instead of just the u8 on the stack, but since for loops are language primitives and if there's no other dependency on the value before the cast, it should always be quite trivial for the compiler to see the equivalence in optimized build modes (all but Debug).
@IntegratedQuantum hmm that comment was made before @min and @max were adjusted to return a result based on the operands too so i wonder if that bodes well for this getting in after all
changed the title [-]For loop range is unusable with types smaller than usize[/-][+]For loop range is unusable with types other than usize[/+]on Sep 13, 2023
I did find one way to do something similar with comptime, it works for me:
fni32Range(comptimea: i32, comptimeb: i32) [b-a]i32 {
comptime {
varrange=std.mem.zeroes([b-a]i32);
for (range[0..], 0..) |*v, i|v.*=a+@as(i32, i);
returnrange;
}
}
// ...// somewhere in code you do thisinlinefor (comptimei32Range(-1, 2)) |i| {
// I guess "i" is now comptime known and is of type "i32"
}
Hope it helps anyone who stumbles in here searching similar issues like I did.
Activity
IntegratedQuantum commentedon Sep 1, 2023
I would also love to have more control over the index type.
However Andrew mentioned in a related proposal that there would be problems with the compiler implementation.
TeamPuzel commentedon Sep 1, 2023
Oh well. is the problem just inference? Or is it not even possible to have the choice to manually choose what type the range is?
I know that overdoing inference can be exponentially bad, I have written statements in Swift before that just couldn't compile :)
(And I assume the same is true for Rust as it is very similar)
The only workaround I can think of is emulating a C style loop with a
whileloop, which would honestly be awful.Either way this feels a bit out of character for a language sold on the level of control it provides.
TeamPuzel commentedon Sep 1, 2023
Is there at least no performance cost when using
intCast?I assume there must be :/
rohlem commentedon Sep 1, 2023
@intCastworks by employing safety-checked illegal behavior.(Note: The name "undefined behavior" here is remnant C terminology and inaccurate; the langref should IMO be updated in this regard - but see also #2301 .)
The short explanation is that the compiler is told what behavior you expect (the value should fit into the target type), and other behavior is illegal.
In safe build modes (
DebugandReleaseSafe) and blocks with explicit safety, the overhead is that if the assumption turns out wrong,@panicis triggered, which prints a stack trace and aborts the program.In unsafe build modes (
ReleaseFastandReleaseSmall), the compiler is allowed to rely on the provided assumption (that illegal behavior cannot occur). Usually this is used to optimize the program, i.e. the compiler tries to always improve performance, and should never penalize you for stating such assumptions. (This hasn't really been formalized yet though.)Technically you could find some performance cost for originally allocating the
usizeinstead of just theu8on the stack, but sinceforloops are language primitives and if there's no other dependency on the value before the cast, it should always be quite trivial for the compiler to see the equivalence in optimized build modes (all butDebug).nektro commentedon Sep 1, 2023
@IntegratedQuantum hmm that comment was made before
@minand@maxwere adjusted to return a result based on the operands too so i wonder if that bodes well for this getting in after all[-]For loop range is unusable with types smaller than usize[/-][+]For loop range is unusable with types other than usize[/+]betonowy commentedon Mar 7, 2024
I did find one way to do something similar with comptime, it works for me:
Hope it helps anyone who stumbles in here searching similar issues like I did.
andrewrk commentedon Aug 16, 2024
working as designed; duplicate of #14704.
there is a chance you may get your wish with #3806.