From: "larskanis (Lars Kanis) via ruby-core" Date: 2026-10-17T13:54:29+00:00 Subject: [ruby-core:127159] [Ruby Feature#22400] Use rb_long_t for lengths so that String and Array can exceed 2GiB on mswin Issue #22400 has been updated by larskanis (Lars Kanis). Both MSWIN and MINGW intentionally use the same ABI. They only have a different toolset. So I don't think we should introduce a ABI difference on the ruby C interface for them. Likewise there's no good reason to handle MINGW and MSWIN differently because of compatibility, IMHO. The same source gems are used for MSWIN and for MINGW. So they need to be changed regarding `rb_len_t` in order to be compatible to MSWIN anyway. I think this is manageable for the time frame until Ruby-4.2 comes out, so that they are compatible to 64 bit `rb_len_t` on both MSWIN and MINGW then. There are currently more binary gems available for MINGW than for MSWIN. But it doesn't matter, since already released binaries are bound to the Ruby ABI 3.3, 3.4, 4.0, etc. and Ruby-4.1/4.2 need new binaries anyway. I understand that the ruby core developers prefer MSWIN and that testing on MINGW is cumbersome for you and slows down development. So I'm fine with checking the MSWIN related changes and port them to MINGW where necessary. You could give me a hint to do so, if there's some need. Anyway it's great that the Windows port receives some attention recently and I really appreciate all the efforts! ---------------------------------------- Feature #22400: Use rb_long_t for lengths so that String and Array can exceed 2GiB on mswin https://bugs.ruby-lang.org/issues/22400#change-119565 * Author: hsbt (Hiroshi SHIBATA) * Status: Open ---------------------------------------- On x64-mswin64, `long` is 32 bits while pointers are 64 bits. String, Array and MatchData keep their lengths in `long`, so none of them can reach 2GiB. ```ruby "a" * 2**31 # RangeError: bignum too big to convert into 'long' File.open(path, "rb") { it.read(2**31) } # RangeError Array.new(2**31) # RangeError ``` I propose giving these lengths and indices a type of their own, `rb_long_t`, in two steps. The first step is https://github.com/ruby/ruby/pull/18862. It defines `typedef long rb_long_t` everywhere and uses it for the lengths and indices of RString, RArray and RMatch, the C API that carries them, and the core, adding `LONGT2NUM`, `NUM2LONGT` and `PRIdLONGT`. A static assert keeps it `long`, so nothing changes, and `NUM2LONG` and `FIX2LONG` still return `long`. The second step makes `rb_long_t` 64 bits on mswin, as `rb_off_t` already does for `off_t` there. mingw keeps `long`, and Fixnum (#14378) stays as is. This breaks extensions that pass a `long *` to an out-parameter such as `rb_range_beg_len`, because Ruby then writes 8 bytes into a 4-byte variable. `-we4133` makes that a compile error, and I will send fixes to the gems it hits: nokogiri, google-protobuf, nokolexbor, string_view, readline-ext and iconv. An extension supporting older Ruby can `typedef long rb_long_t` when `RB_LONGT_MAX` is undefined. No existing type fits. `ssize_t` and `intptr_t` are `int` on ILP32 and would change `long *` parameters there. `SIGNED_VALUE` is already 64 bits on mswin, so it could not land as a no-op first. To catch new code that adds a plain `long` for a length, I would like a CI job that builds with `rb_long_t` set to `long long` on Linux, where `%ld` and `long *` mismatches fail. First, do you agree with this direction and with carrying it out? If so, is `rb_long_t` a good name? And since few C extensions are distributed for mswin, I think we could make the second step in 4.1 as well, without a transition period. What do you think? -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/