Breaking changes
stdlib
- (system) Drop
Process.fork(#17367, thanks @straight-shoota)
Features
lang
- Allow constants with type declarations (#16951, thanks @stakach)
- (macros) Add
StringLiteral#bytesize(#17176, thanks @straight-shoota) - (macros) Add
NumberLiteral#chr(#17169, thanks @straight-shoota) - (macros) Support
CharLiteralinRangeLiteral#each(#17170, thanks @straight-shoota)
stdlib
- Add warning about minimum supported Crystal version in
prelude(#17349, thanks @straight-shoota) - (crypto) Enable OpenSSL Kernel TLS support by default (#17059, thanks @ysbaddaden)
- (crypto) Add
OpenSSL::Cipher#gcm_tagand#gcm_tag=for AEAD ciphers (#17096, thanks @paulocoghi) - (files) Add
IO::Memory#writable?(#17167, thanks @spuun) - (llvm) Support LLVM 23.1 and 24.0 (#17432, thanks @HertzDevil)
- (macros) Add all enum types to
Enum's list of subclasses (#17425, thanks @HertzDevil) - (networking) Add
HTTP::Context#remote_address,#local_address(#17196, thanks @straight-shoota) - (networking) Validate method, version, and host in
HTTP::WebSocketHandler(#17235, thanks @hahwul) - (networking)
HTTP::Client::RequestsupportContent-Encoding: x-gzip(#17263, thanks @straight-shoota) - (networking) Add
HTTP::Headers#merge(#17326, thanks @jgaskins) - (networking) Serialize
IO::Memoryin HTTP body withContent-Lengthheader (#17388, thanks @straight-shoota) - (runtime) Add
GC.syscall(&)(#17150, thanks @ysbaddaden) - (runtime) Add
Thread#waitandThread#wakemethods (#17226, #17243, #17247, #17380, #17419, thanks @ysbaddaden) - (runtime) Add
Crystal::LRUCache(#17284, thanks @ysbaddaden) - (runtime) Add
GC.max_heap_size=(#17346, thanks @straight-shoota) - (runtime) Use epoll event loop on Solaris targets (#17370, thanks @ysbaddaden)
- (runtime) DWARF: build function names table for fast binary search (#17410, #17433, thanks @ysbaddaden)
- (runtime) Enable kqueue event-loop by default on all BSD targets (#17421, thanks @ysbaddaden)
- (runtime) DWARF: build index of
.debug_linesection (#17455, thanks @ysbaddaden) - (runtime) Support
BytesinCrystal::System.printf(%s)(#17463, thanks @ysbaddaden) - (runtime) Support
DW_FORM_addrx<n>andDW_FORM_strx<n>from DWARF 5 (#17445, thanks @ysbaddaden) - (runtime) Add
Fiber::ExecutionContext::Parallel#scale_upto manually scale parallel contexts (#17438, thanks @ysbaddaden) - (runtime) Re-enable pretty backtraces in UNIX segfault handler (#17456, thanks @ysbaddaden)
- (serialization) Add
XML::Node#line_number(#17179, thanks @n-rodriguez) - (system) Include exit code in
Process::Status#description(#17087, thanks @straight-shoota) - (system) Add
File::Info#inspect(#17375, thanks @straight-shoota) - (system) Add
File.exists?(follow_symlinks: true)(#17307, #17600, thanks @straight-shoota, @ysbaddaden) - (system)
File::Info.readable?,.writable?,.executable?follow_symlinks: false(#17391, thanks @straight-shoota) - (text) Add
Char::Reader.new(Bytes)(#17428, thanks @straight-shoota) - (time) Add
Time::Span#to_nanosecondsetc. (#17190, thanks @straight-shoota)
compiler
- (cli) Improve compiler error when writing cross-compile output fails (#17457, thanks @ralsina)
- (parser) Fix parsing suffix form of
ensureafter anExceptionHandler(#17426, #17460, thanks @Sija) - (semantic) Add
Crystal::ALL_FLAGSandUSER_FLAGS(#17392, #17621, thanks @straight-shoota) - (semantic) Fix
method_missingcall location metadata (#17465, thanks @nobodywasishere)
tools
- (docs-generator) Update markd 0.6.0 (#17269, thanks @straight-shoota)
Bugfixes
stdlib
- (cli) Fix bundled short options not consuming a value from the next argument (#17473, thanks @alter)
- (collection) Fix invalid access in
BitArray#[](Int, Int)(#17205, thanks @HertzDevil) - (collection) Fix
Range#stepraise on zero step size (#17225, thanks @straight-shoota) - (collection) Fix
Range#sizeoverflow on max integer value (#17266, thanks @mvanhorn) - (collection) Fix each_repeated_combination iterator raising on an empty collection (#17275, thanks @SAY-5)
- (concurrency)
Sync::RWLock#try_write_lock?skips type protection (#17472, thanks @ysbaddaden) - (files) invalid resize when writing
IO::Memoryto itself (#17241, thanks @ysbaddaden) - (llvm) Add pointer indirection for
__crystal_type_id_to_class_name_map(#17502, thanks @HertzDevil) - (llvm) Fix
LLVM#gepand#inbounds_gepsignatures with multiple indices (#17538, thanks @HertzDevil) - (networking) Reject unrecognized HTTP
Transfer-Encodingheader (#17140, thanks @straight-shoota) - (networking) Reject
HTTP::Client::Responsewith invalidContent-Encoding(#17262, thanks @straight-shoota) - (networking) Fix
HTTP::Request.from_ioparsing empty header name (#17254, thanks @straight-shoota) - (networking) [breaking] Fix
HTTP::Request#body=return value (#17257, thanks @straight-shoota) - (networking) Fix
Content-Encoding: deflate(#17261, thanks @straight-shoota) - (networking) Fix validation in
Request#hostname(#17258, thanks @straight-shoota) - (networking) Fix
HTTP::Request#form_params?to ignore invalid content-type (#17256, thanks @straight-shoota) - (networking) Fix
HTTP.parse_headers_and_bodyto not raise withwithout_zlib(#17272, thanks @straight-shoota) - (networking) Validate
HTTP::Request#method(#17255, thanks @straight-shoota) - (networking) Validate
HTTP::Request#version(#17304, #17374, thanks @straight-shoota, @Sija) - (networking) Fix
HTTP::Request#content_length=return value (#17273, thanks @straight-shoota) - (networking) Validate
HTTP::Request#resource(#17310, thanks @straight-shoota) - (networking) Fix
Socket#sendfilewhencount > file.size(#17286, thanks @straight-shoota) - (networking) Fix
File#sendfileshould not move#pos(#17293, thanks @straight-shoota) - (networking) Fix IPv6 address passed to
OpenSSL::SSL::Socket::Client.newfor OpenSSL 4.0 (#17321, thanks @HertzDevil) - (networking) Fix
HTTP::VALID_TOKEN_CHAR_MAPfor Crystal < 1.16 (#17333, thanks @straight-shoota) - (networking) Fix validate
HTTP::Headersname (#17317, thanks @straight-shoota) - (networking) Close
HTTP::ClientonIO::Errorduring request (#17318, thanks @jgaskins) - (networking) Fix reject invalid HTTP trailer (#17337, thanks @straight-shoota)
- (networking) Validate
HTTP::Request#content_lengthand type asInt64(#17312, thanks @straight-shoota) - (networking) Fix keep
HTTP::Request#content_lengthin sync with#body(#17389, thanks @straight-shoota) - (networking) Fix
WebSocketbuffer corruption with interleaved control frame (#17553, thanks @straight-shoota) - (networking) Fix
WebSocket::Protocol#receiveto validate masked/unmasked state (#17562, #17603, thanks @straight-shoota) - (networking) Fix
WebSocketreject mixed opcode continuation (#17552, thanks @straight-shoota) - (numeric) Fix
BigRational#<=>with an infiniteFloat(#17223, thanks @youdie006) - (numeric) Fix
Int#humanize_bytesto useKiBin IEC format (#17234, thanks @kojix2) - (runtime)
ThreadPool#main_thread_loop(#17194, thanks @ysbaddaden) - (runtime) free dead fiber stack when there's no stack pool (#17229, thanks @ysbaddaden)
- (runtime) support bare threads in crystal/once (#17228, thanks @ysbaddaden)
- (runtime) io_uring event loop hangs on sendfile (#17299, thanks @ysbaddaden)
- (runtime) correctly iterate ELF file sections (#17327, thanks @ysbaddaden)
- (runtime) backtraces on musl-libc when linking with
-static-pie(#17316, thanks @ysbaddaden) - (runtime) abort on out-of-memory instead of segfaulting (#17111, #17345, thanks @carlhoerberg, @straight-shoota)
- (runtime) enqueue thread once into thread pool (#17350, thanks @ysbaddaden)
- (runtime) save stdio closed state on program start (#17378, thanks @ysbaddaden)
- (runtime) rewrite thread pool logic to avoid race conditions (#17400, thanks @ysbaddaden)
- (runtime) don't propagate trace environment variables to sub-processes (#17402, thanks @ysbaddaden)
- (runtime) tracing 128 bit integers (#17403, thanks @ysbaddaden)
- (runtime) kqueue event loop on NetBSD (#17420, thanks @ysbaddaden)
- (runtime) [regression] Fix COFF symbols table being empty on MinGW-w64 (#17442, thanks @HertzDevil)
- (runtime) Fix running on CPUs with
cpu_count > UInt8::MAX(#17437, thanks @willhbr) - (runtime) parallel schedulers may deadlock each other (#17491, thanks @ysbaddaden)
- (runtime) crystal/once must cleanup when an exception is raised (#17546, thanks @ysbaddaden)
- (runtime) auto-scaling of multiple execution contexts (#17514, thanks @ysbaddaden)
- (runtime) Distinguish kqueue registration errors from kevent errors (#17599, thanks @ysbaddaden)
- (serialization) Fix CSV error line numbers with CRLF input (#17381, thanks @cuishuang)
- (serialization) Fix CSV builder to escape CR characters (#17548, thanks @ysbaddaden)
- (system) [regression] Fix missing NULL terminator for
execvevargs (#17184, thanks @sdogruyol) - (system) Fix
Process.newto close pipes on error (#17297, thanks @straight-shoota) - (system) [breaking] Add
IO::FileDescriptor#exit_on_broken_pipe(#17335, thanks @straight-shoota) - (system) Skip inaccessible candidates for
Process.find_executable(#17409, thanks @mvanhorn) - (system) Fix
FileUtils.mv(Enumerable)swallowing errors (#17407, thanks @LaskaIDK) - (system) Ignore all
File::ErrorinProcess.find_executable(#17542, thanks @jochenseeber) - (text) Fix
String#gsubwhenRegexpattern matches empty string and advances (#17204, thanks @HertzDevil) - (text) Fix
URI#resolvefor path without/(#17213, thanks @straight-shoota) - (text) Handle consecutive whitespace in
String#titleize(#17206, thanks @HertzDevil) - (text) Fix
String#each_line(remove_empty: true)with many empty lines (#17242, thanks @straight-shoota) - (text) Fix
Char::Reader#pos=to raise on negative position (#17382, thanks @straight-shoota) - (text) Fix
Char::Reader#current_char_widthto be zero at end (#17405, thanks @straight-shoota) - (text) Fix
String#compare(case_insensitive: true)to order invalid byte sequences (#17314, thanks @straight-shoota) - (text) Fix
Char::Reader.newto raise on an invalid position (#17416, thanks @youdie006) - (text) Fix
PCRE2#jit_compileto accept nomemory error for implicit fallback (#17559, thanks @straight-shoota) - (time) Fix local timezone location name for Android (#17248, thanks @HertzDevil)
- (time) Fix
Time::Location.load?for Android (#17249, thanks @HertzDevil)
compiler
- Fix vswhere ignoring ARM64-only MSVC installations (#17395, thanks @HertzDevil)
- (codegen) Codegen doesn't materialize an unused yield block value in debug builds, pt. 2 (#17130, thanks @nobodywasishere)
- (codegen) Unify LLVM types used for
ReferenceStorage(#17397, thanks @HertzDevil) - (codegen) Do not access owner type in dispatch if it is not passed at runtime (#17424, thanks @HertzDevil)
- (codegen) cross-compile crashes when combined with emit llvm-bc or obj (#17510, thanks @ysbaddaden)
- (codegen) Fix memory leak in mixed union assignments (#17518, thanks @ysbaddaden)
- (codegen) Fix SysV ABI classification of word containing
Float32followed by integer (#17572, thanks @HertzDevil) - (codegen) Respect ABI info when explicitly returning inside top-level funs (#17616, thanks @HertzDevil)
- (debugger) Fix lldb-dap crash on Windows when loading Crystal formatters (#17448, thanks @magynhard)
- (interpreter) Fix interpreter dispatch on a virtual struct narrowed from a union (#17450, thanks @jochenseeber)
- (parser) Fix parse
OP_SLASHafter block (#17159, thanks @straight-shoota) - (parser) Fix suffix
ExceptionHandler#locationin an assignment (#17365, thanks @Sija) - (parser) Fix global calls shadowed by local variables (#17558, thanks @grepsedawk)
- (semantic) Fix instance variable initializer using a class variable assignment (#17148, thanks @nobodywasishere)
- (semantic) Fix bug allowing
selfin private top-level method (#17149, thanks @nobodywasishere) - (semantic) Fix dynamic class declaration macro error (#17274, thanks @nobodywasishere)
- (semantic) Backfill included type to existing instantiations (#17094, thanks @straight-shoota)
- (semantic) Fix ICE when module with ivar is included in a type that can't have them (#17386, thanks @bcardiff)
- (semantic) Disallow
instance_sizeofandinstance_alignofonVoidorNoReturn(#17453, thanks @HertzDevil)
tools
- (formatter) Fix formatter for setter assignment with parenthesized values (#17083, thanks @mamantoha)
- (formatter) formatter unescapes fresh variables (#17517, thanks @ysbaddaden)
Chores
lang
- [deprecation] Deprecate uppercase instance and class variables (#17160, thanks @nobodywasishere)
stdlib
- (llvm) [deprecation] Deprecate
LLVM::Type#sizeand#alignment(#17494, #17533, thanks @HertzDevil) - (networking) [deprecation] Deprecate
HTTP::Request#local_addressand#remote_address(#17260, thanks @straight-shoota)
compiler
- (codegen) Drop
Compiler#fork_codegen(#16417, thanks @straight-shoota)
other
- Fix deprecation warnings in samples (#17342, thanks @HertzDevil)
Performance
stdlib
- (networking) Optimize
HTTP.header_name(#14503, thanks @jgaskins) - (runtime) Keep decoded backtrace lines into LRU cache (#17285, thanks @ysbaddaden)
- (text) Optimize
String#byte_index(Int)(#17303, thanks @HertzDevil) - (text) Optimize
String#gsub(String)and#scan(String)(#17305, thanks @HertzDevil)
Refactor
stdlib
- (collection) Optimize buffer size in
Enum.parse?withStringLiteral#bytesize(#17193, thanks @straight-shoota) - (networking) Refactor
Socket::IPAddressinterface index conversion (#17250, thanks @HertzDevil) - (networking) Refactor
RequestProcessor#processto receive a single IO (#17461, thanks @straight-shoota) - (numeric) Use unchecked arithmetic in compiler-rt ports (#17180, thanks @HertzDevil)
- (numeric) Use native
UInt128in Dragonbox (#16262, thanks @HertzDevil) - (numeric) Format
IntMINandMAXconstants as hex numbers (#17352, thanks @straight-shoota) - (numeric) Use 128-bit literals (#5545, thanks @Sija)
- (runtime) Execution contexts directly enqueue fibers during event loop runs (#17158, thanks @ysbaddaden)
- (runtime) Add
Runnables#lazy_grab?to skip the mutex on quick dequeue (#17151, thanks @ysbaddaden) - (runtime) Refactor file lock (#17105, thanks @ysbaddaden)
- (runtime) Refactor
Exception::CallStack.decode_backtrace_frame(#17282, thanks @ysbaddaden) - (runtime) DWARF: scan sections instead of building large tables (#17283, thanks @ysbaddaden)
- (text) Refactor
Char::Reader#next_charand ivar initialization (#17383, thanks @straight-shoota) - (time) Change
Time.zeroto create new instance instead of returningZERO(#17216, thanks @straight-shoota) - (time) Replace
Time::Span::ZEROwith.zero(#17217, thanks @straight-shoota) - (time) Use
Time::Span#to_secondsetc. (#17259, thanks @straight-shoota)
compiler
- Refactor
Program#define_crystal_constants(#17268, thanks @straight-shoota) - (codegen) Remove
Crystal::LLVMBuilderHelper#llvm_sizeand friends (#17452, thanks @HertzDevil) - (semantic) Refactor
RangeLiteral#each(#17195, thanks @straight-shoota) - (semantic) Refactor
#interpret_to_range(#17227, thanks @straight-shoota)
other
- Remove unnecessary requires (#17306, thanks @straight-shoota)
- Do not use relative requires for the standard library (#17320, thanks @HertzDevil)
Documentation
stdlib
- (collection) Fix doc example for
Hash#put(#17459, thanks @spuun) - (concurrency) Clarify docs for
Channelbuffered channel close and drain semantics (#17423, thanks @renich) - (numeric) Fix typo in doc comment for
Int(#17238, thanks @swsch) - (runtime) Undocument internal
GCmethods (#17451, thanks @ysbaddaden) - (serialization) Mention
#to_pretty_jsoninJSONdocumentation (#17131, thanks @LaskaIDK) - (specs) Fix summary line of
Spec::Expectations#bedocs (#17556, thanks @SatvikMishra08) - (system) Document error behaviour for
Dir.mkdirand.mkdir_p(#17240, thanks @LaskaIDK)
compiler
other
Specs
stdlib
- (networking) Reorganize
HTTP::Requestspec (#17166, thanks @straight-shoota) - (networking) Add more specs for
HTTP::Request(#17218, thanks @straight-shoota) - (networking) Assert return value of
Socket#sendfile(#17292, thanks @straight-shoota) - (networking) Fix: link-local zone interface fails with ENXIO on Solaris targets (#17371, thanks @ysbaddaden)
- (networking) Fix
getaddrinfowithAF_UNSPECfailing withEAI_ADDRFAMILYon FreeBSD (#17358, thanks @ysbaddaden) - (networking) Fix: loopback interface may not be the first interface (#17359, thanks @ysbaddaden)
- (networking) Fix: disable dual stack specs on FreeBSD and DragonFly (#17411, thanks @ysbaddaden)
- (networking) Add spec for explicit decompressing HTTP request body [follow-up #17476] (#17531, thanks @straight-shoota)
- (numeric) Add specs for
Big*types compaing against float infinity (#17224, thanks @straight-shoota) - (runtime) Relax threshold for
sleepspec with libevent (#17232, thanks @straight-shoota) - (system) Add
process-utilsfor testing process execution (#17047, thanks @straight-shoota) - (system) Always ignore
%PROCESSOR_ARCHITECTURE%when runningProcessspecs on MSVC (#17362, thanks @HertzDevil) - (system) Add spec for
FileUtils.ln_sfreplacing a dangling symlink (#17289, thanks @SAY-5) - (text) Improve specs for
Char::Reader(#17354, thanks @straight-shoota) - (text) Add regression spec for multibyte
String#splitseparator (#17338, thanks @wangyusheng1985)
compiler
- Refactor
new_programspec helper to concat program flags (#17356, thanks @straight-shoota) - (parser) Remove obsolete
FIXMEs for array literal parsing (#17347, thanks @straight-shoota)
Infrastructure
- Update previous Crystal release 1.21.0 (#17137, thanks @straight-shoota)
- Makefile: Add
buildandmanpagestargets (#17142, thanks @straight-shoota) - Makefile: Remove
alltarget from help (alias forcrystal) (#17157, thanks @straight-shoota) - Update
devenv.lock(#17147, #17210, #17245, #17253, #17290, #17330, #17379, #17415, #17181, #17143, thanks @crysbot) - Enable FIXME rules in
rumdl.tomlconfiguration (#17171, thanks @straight-shoota) - Update distribution-scripts (#17178, thanks @straight-shoota)
- Update
crystalversion inshard.yml(#17351, thanks @straight-shoota) bin/crystal: Avoid symlinks inCRYSTAL_PATH(#17355, thanks @straight-shoota)- Fix
update-changelog.shfor patch releases (#17479, thanks @straight-shoota) - Merge
release/1.21@1.21.1intomaster(#17526, thanks @straight-shoota) - devenv: Remove actionlint because it's broken (#17527, thanks @straight-shoota)
- renovate: Add custom config for updating shards repo checkout ([#17547], thanks @straight-shoota)
- Support ARM64 for the MSVC-based toolchain's GUI installer (#17398, thanks @HertzDevil)
- (ci) Fix Inno Setup download URL (#17135, thanks @straight-shoota)
- (ci) Update GH Actions (#17185, #17336, #17427, #17458, #17146, #17512, thanks @renovate)
- (ci) Update cachix/install-nix-action action to v31.11.1 (#17252, thanks @renovate)
- (ci) Upgrade runner to
windows-11-vs2026-arm(#17267, thanks @straight-shoota) - (ci) Limit
forward-compatibilityto last 8 releases (#17332, thanks @straight-shoota) - (ci) Fix allow unsafe PR checkout in
backportworkflow (#17340, thanks @straight-shoota) - (ci) Switch
uses:in GHA workflows to self-repository syntax (#17513, thanks @straight-shoota) - (ci) run std specs on FreeBSD 14 (#17361, thanks @ysbaddaden)
- (ci) Run smoke tests on changes that affect codegen (#17545, thanks @straight-shoota)
- (ci) Use newer GitHub Action to set up MSVC developer command prompt (#17396, thanks @HertzDevil)
- (ci) Update MSVC CI library versions (#17301, thanks @HertzDevil)
- (ci) Use explicit development branch version number for LLVM CI (#17497, thanks @HertzDevil)
- (ci) Drop
macos-14runner on GitHub CI (#17532, thanks @HertzDevil) - (ci) Bootstrap ARM64 MSVC-based Crystal compiler (#17154, thanks @HertzDevil)
- (ci) Use clang-cl to build OpenSSL for ARM64 MSVC CI (#17251, thanks @HertzDevil)
- (ci) Build stage-2 compiler on ARM64 MSVC CI (#17363, thanks @HertzDevil)
- (ci) Use Cygwin to build libffi for MSVC CI (#17163, thanks @HertzDevil)
- (ci) Split MSVC CI third-party libraries onto own workflow (#17287, thanks @HertzDevil)
- (ci) Set up NASM manually on MSVC CI (#17429, thanks @HertzDevil)