glfw: should use u32/i32/etc everywhere instead of usize/isize #114
Labels
No labels
CI
all
basisu
blog
bug
build
contributor-friendly
core
correctness
deferred
dev
direct3d-headers
docs
driver-os-issue
duplicate
dxcompiler
editor
examples
experiment
feature-idea
feedback
flac
freetype
gamemode
gkurve
glfw
gpu
gpu-dawn
harfbuzz
help welcome
in-progress
infrastructure
invalid
libmach
linux-audio-headers
long-term
mach
mach.gfx
mach.math
mach.physics
mach.testing
model3d
needs-triage
object
opengl-headers
opus
os/linux
os/macos
os/wasm
os/windows
package-manager
priority
proposal
proposal-accepted
question
roadmap
slipped
stability
sysaudio
sysgpu
sysjs
validating-fix
vulkan-zig-generated
wayland-headers
website
wontfix
wrench
www
x11-headers
xcode-frameworks
zig-update
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
hexops/mach#114
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Currently it produces an
isizewidthandheight, which matches the GLFWinttype. But presumably a framebuffer is always positive and there's not a good reason to use signed integers?I've tried investigating, to find any obvious instances where it could be set to a negative value, but it appears to be a pretty barren topic, and there's nothing that stands out in the GLFW source involved with the callback.
It may not be a bad idea to switch to an unsigned type; if anything breaks, then it's something that can be addressed directly, and thus improved.
Though, now thinking about it, I think perhaps switching over to a smaller, fixed integer type, like
u32would be a better for the codebase, being that on 32 bit platforms,c_intis 4 bytes, andusizeis 8 bytes, meaning if someone built on a 64 bit platform, they could theoretically make runtime-incompatible software for 32 bit platforms. Yes, an edge case, but as stated in zig zen "Edge cases matter".+1 on u32. There are already framebuffers 8k wide, so we can imagine a u16 overflowing within a few years. usize and isize are POINTER sized types, not, say window sized types. The C++ std goes a bit awry with size_t which is meant for measuring memory, using it when no pointer measuring is involved. No need to follow in those footsteps ;)
@InKryption
I want to make sure I understand this. Are you saying that you believe the current c_int -> usize casts would be invalid on a 32-bit platform (I did not believe so, I'd like to learn/understand why if so) or are you saying that this being usize could lead to someone else making a mistake in their code? Or something else entirely?
switching to u32/i32 where appropriate sounds good to me, there are quite a few places where I've used
usizeandisizeas general purpose integers of an unknown size (e.g. to substitutec_intandc_uint) so we will need to vet each one.@slimsag
Sorry, should have been more clear: I believe there is no issue here, in this particular instance, but it got me thinking about the usage of
usize/isizein the codebase, e.g. in window creation, width and height could theoretically overflow, since it's a downcast fromusizetoc_int(if memory serves me right). Erego, even if there is no issue here, the same change should still be applied here for consistency's sake.And @meshula also makes a pretty compelling argument.
Makes sense, and sounds good to me!
Bit more info: Specs_guy says
var u : usize = something; var i : u64 = @intCast(u64, something)is "free" in terms of processor cycles, butvar u : usize = something; var i : u32 = @intCast(u32, something)is undefined on a 64 bit machine.@meshula I'm not sure what exactly you mean because the type of
somethingin both of your examples is not clear. I think that you are trying to say@intCast(u32, something)wheresomethingis a value greater than a u32 can contain is UB? If so, yeah, that makes sense - this is also why Zig has@truncate(u32, something)if you want to explicitly take e.g. the lower 32 bits of a 64-bitusizeWhat was not clear to me before this discussion was whether or not
usize/isizeare appropriate types for a general integer of no specific size, akin to how C and Go haveintanduint. And actually, I thought I had seen Andrew Kelley publicly state somewhere thatusizeandisizewere the correct type in this case, but after a few hours of searching I couldn't find it anymore and reading all docs/issues seems to indicate that indeed, it's not, one should use best-effort guesses in such situations (e.g. u32 for framebuffer width/height.) I think my background in using Go/C confused me here, so that's how we ended up withusizeandisizeeverywhere.Sorry about the unclearness, @InKryption had mentioned "theoretically runtime incompatible interfaces" on 32 bit machines, which sent me down a path of double checking if there was any UB around usize/isize.
The intent of the note was to be adding another supporting argument for u32/i32 interfaces, not explaining zig basics, of which I am definitely not a source of ground truth ;)
somethingwas also unclear; just a placeholder meaning "it doesn't matter what value this is", and Spec_guy also mentioned that @truncate removes the UB, which I neglected to report :)Ahh okay, got it, thanks! Just wanted to make sure I wasn't missing something more subtle in your message :) Appreciate the clarification
I would just like to add: I think it's often more sane to use
std.math.clampthan@truncate, because if you downcast a very big integer with only high bits set, it will turn into a very small or value 0 integer.