RFC: Allow type inference for const or static by PixelDust22 · Pull Request #3546 · rust-lang/rfcs (original) (raw)

Ok, now I want to use that array in my downstream code. I need to know its exact length, because my API requires an array of specific size. Am I supposed to manually count the array size each time?

For the original author, writing the array size is trivial. Just write 0, and the compiler will complain that it doesn't match the actual size 4. Write it down, done. It's a trivial annoyance, and it doesn't matter much unless you change the lengths of your arrays frequently (in which case its a semver break anyway, so it should be made explicit and done deliberately, rather than the compiler silently swallowing the breaking change).

You're trading a trivial ease-of-writing change into an issue for each one of your downstream consumers.

FTR, I personally think the array issue is persuasive. If I've got a local static that contains a list of upwards of a thousand values (say, syscall addresses in a kernel), I'm not going to want to scroll up a thousand+ lines of code to also update the length of the array.
And to answer the "use a slice" point before it's made again, slap #[no_mangle] on the array, and store the .len() in a different (also #[no_mangle]) static. Or pass it in via a sym and const operand to global_asm!(). Slices can't be accessed directly via FFI or assembly. The syscall point is I think very important here, because here's what a syscall wrapper might be:

static SYSCALLS: _ = [/build syscall array/]

global_asm!( ".globl __syscall_dest_lstar", "__syscall_dest_lstar:" "cmp eax, {SYSCALL_LIMIT}", "jae 2f", "mov rax, qword ptr [{SYSCALLS}+rip]", "cmp rax, rax", "jz 2f", "swapgs", "push rcx", "push rsp", "mov rsp, gs:[0]", "mov rcx, r10", "call rax", "pop rsp", "pop rcx", "swapgs", "sysret", "2:", "mov eax, {ERROR_UNSUPPORTED_KERNEL_FUNCTION}", "sysret", ERROR_UNSUPPORTED_KERNEL_FUNCTION = const errors::UNSUPPORTED_KERNEL_FUNCTION, SYSCALLS = sym SYSCALLS, SYSCALL_LIMIT = const SYSCALLS.len() );

It's fairly simple - check if the syscall number (in eax/rax) is below the syscall limit, if ts not, then return UNSUPPORTED_KERNEL_FUNCTION, otherwise load the address of the syscall, check it for being null, and then convert from syscall convention to Sys-V convention (and do a stack switch), call the function, switch back to syscall, and sysret. Of course, it's simple because SYSCALLS is an array, not a slice.