Breaking changes
stdlib
- (runtime) Release: Execution Contexts (#17100, #17104, thanks @ysbaddaden)
- (text) Disable automatic fallback to legacy
PCRE(#16924, thanks @straight-shoota)
Features
lang
- Add
%Wpercent string array literals with interpolation (#16919, thanks @straight-shoota) - (macros) Add
TypeNode#all_methodsthat includes the type's ancestor's methods (#16902, thanks @Blacksmoke16)
stdlib
- (cli) Align long-only options in OptionParser help (#16914, thanks @kojix2)
- (collection) Make
Channel(T)anIterator(T)(#16916, thanks @jgaskins) - (crypto) Add support for OpenSSL 4.0 (#16839, thanks @straight-shoota)
- (crypto) Support OpenSSL 4.x DLLs on Windows MSVC (#17116, thanks @HertzDevil)
- (networking) [experimental] Add
Socket#sendfile(andCrystal::EventLoop::Socket#sendfile) (#16665, #17133, thanks @ysbaddaden, @straight-shoota) - (networking) Add
HTTP::WebSocket#receiveas a synchronous call (#16689, thanks @jgaskins) - (runtime) Add
Crystal::EventLoop::FileDescriptor#pread(#17068, thanks @ysbaddaden) - (runtime) Add
without_mainflag (#17074, thanks @kojix2) - (runtime) OpenBSD: use kqueue event loop by default (#17123, thanks @ysbaddaden)
- (serialization) Support nested
rootproperties inJSON::Field(#17016, thanks @tcoatswo) - (serialization) Add
URI::Params::Field(ignore:),ignore_serialize,ignore_deserialize(#17029, thanks @trypsynth) - (specs) Allow chaining
#should,#should_notexpectations (#17020, thanks @straight-shoota) - (system) Expose
Path#kind(#16917, thanks @Sija) - (system) Add splat overloads for
Process.capture,.runand.new(#16975, thanks @straight-shoota) - (system) Add
Process::Status.[]constructor (#17003, thanks @straight-shoota) - (text) Add
String#present?(#16930, thanks @Sija) - (text) Add
UUID.v6and.v8generators (#17010, thanks @trypsynth)
compiler
- (cli) Classify compiler exit reasons (#17028, thanks @straight-shoota)
- (debugger) Improve proc debug metadata (#16830, thanks @skuznetsov)
- (debugger) Emit debug metadata for constants and class vars (#16831, thanks @skuznetsov)
- (debugger) Improve LLDB collection formatters (#16832, thanks @skuznetsov)
- (parser) Add
ASTNode#inspect(#16699, thanks @straight-shoota) - (parser) Parse
MacroVarwith empty expressions:%var{}(#16772, thanks @straight-shoota) - (semantic) Split branches on
when Bar, Baz(#17072, thanks @straight-shoota)
tools
- (docs-generator) Improve wording in warning about doc generator without LibXML2 (#16926, thanks @kojix2)
Bugfixes
stdlib
- (cli) Fix summary wrapping condition in OptionParser (#16915, thanks @kojix2)
- (cli) Avoid
Process.execon Windows and explicitly spawn subprocess (#17049, thanks @straight-shoota) - (collection) Fix
Iterator#compact_mapwithEmptyIterator(#16928, thanks @straight-shoota) - (collection) Fix
Iterator#compact_mapwith non-nilable compactor proc (#16927, thanks @straight-shoota) - (concurrency) Fix swapped atomic orderings in
Sync::MUfast paths (#17063, thanks @stevegeek) - (llvm) Fix use line 0 for unknown debug location (#17013, thanks @straight-shoota)
- (networking) Fix
HTTP::Request.form_params?to recognizeContent-Typeandcharset(#16934, #16971, thanks @swsch, @straight-shoota) - (networking) Fix
HTTP::Clientto retry for connection recovery only (#16981, thanks @straight-shoota) - (networking) Disable transport read-ahead for Kernel TLS sockets (#17053, thanks @jage)
- (runtime)
Fiber::ExecutionContext::Monitorcompat with old Crystal releases (#17007, thanks @ysbaddaden) - (runtime)
EventLoop::IoUring#openmusn't setO_NONBLOCKwhen blocking (#17035, thanks @ysbaddaden) - (runtime) underperforming unlock conditions in
Sync::MU(#17070, thanks @ysbaddaden) - (runtime)
fdlock#try_close?must release ref after yielding to the block (#17089, thanks @ysbaddaden) - (runtime)
Fiber::ExecutionContext.current?(#17092, thanks @ysbaddaden) - (runtime) Refactor Win32 iocp evloop (#17101, thanks @ysbaddaden)
- (serialization) memory leak in
XML::Node#each_namespace(#17038, thanks @ysbaddaden) - (system) skip Windows registry MIME entries with an invalid Content Type (#17106, thanks @SAY-5)
- (text) Fix
IO::Encoder#writewhen operating on long strings (#16797, thanks @jgaskins)
compiler
- (cli) Remedy short-flag conflict for
crystal spec -p(#17062, thanks @straight-shoota) - (codegen) Fix codegen treating distinct lib
typealiases as the same type (#16961, thanks @stakach) - (interpreter) Add interpreter
upcast_distinctforPointertoPointer(#16962, thanks @stakach) - (interpreter:repl) Fix auto-indentation in the REPL when typing classes. (#16910, thanks @I3oris)
- (interpreter:repl) Fix interpreter multidispatch cache collision (#16958, thanks @stakach)
- (parser) Fix lexing
MacroVarsyntax in literal (#16779, thanks @straight-shoota) - (parser) Fix parsing macro var without exps followed by macro expression (#16879, thanks @straight-shoota)
- (parser) Fix parse parenthesized expression in block arg assignment (#16894, thanks @straight-shoota)
- (parser) Do not merge nested
ExpressionandExceptionHandler(#16852, thanks @straight-shoota) - (parser) Fix parser silently ignoring
&(...),&[...],&{...}in assignment (#16960, thanks @stakach) - (parser) Fix parser allow
/and//immediately afterself,nil,true,false(#16942, thanks @stakach) - (parser) Fix short block setter call end location (#17039, thanks @Sija)
- (semantic) Fix freeze type of variable declared with
out(#16870, thanks @straight-shoota) - (semantic) Fix
lookup_matches_in_typeto reject partial matches (#16867, thanks @straight-shoota) - (semantic) Fix location of double splat named tuple typenode entry locations (#16889, thanks @Blacksmoke16)
- (semantic) Fix
sizeof,offsetofas generic type argument in inferred ivar type (#16811, thanks @kojix2) - (semantic) Fix macro argument errors for path receiver calls (#16923, thanks @kojix2)
- (semantic) Detect uninitialized ancestor ivars through macro_def initializers (#16959, thanks @stakach)
- (semantic) Preserve
nil_if_read?across while cond filters (#16963, thanks @stakach) - (semantic) Keep wider subclass observer when call owner narrows (#16947) (#16990, thanks @stakach)
- (semantic) Symmetric
common_descendentfor two generic class types (#10831) (#16999, thanks @stakach)
tools
- (formatter) Fix format empty
thenwith trailing comment (#16878, thanks @straight-shoota) - (formatter) Fix formatting whitespace in ternary
ifwith trailing comments (#16880, thanks @straight-shoota) - (formatter) Fix formatter on empty string literal continuation (#16817, thanks @straight-shoota)
- (formatter) Fix format annotations of splat parameter (#16987, thanks @straight-shoota)
- (formatter) Fix formatter strip empty lines in heredoc (#17034, thanks @straight-shoota)
Chores
stdlib
- (cli) [deprecation] Deprecate
Colorize.on_tty_only!(#16859, thanks @straight-shoota) - (concurrency) [deprecation] Deprecate
spawn(same_thread:)(#17097, thanks @ysbaddaden) - (files) [deprecation] Rename parameter to
writableinIO::Memory.new(#16858, #16883, thanks @straight-shoota) - (system) [deprecation] Hide platform-specific
Process::Statusconstructor (#16997, thanks @straight-shoota)
Performance
stdlib
- (collection) Preallocate correct size for hash in
Hash.zip(#17054, thanks @carlhoerberg)
Refactor
stdlib
- (cli) Split error helper for compiler CLI into independent methods (#16984, thanks @straight-shoota)
- (cli) Refactor compiler code to raise
CompilerErrorinstead ofabort(#16995, thanks @straight-shoota) - (concurrency) simplify read console (windows) (#17098, thanks @ysbaddaden)
- (concurrency)
Process#waiton Windows (#17099, thanks @ysbaddaden) - (networking) Refactor bubbling exceptions from user code in
HTTP::Client#exec(&)(#16969, thanks @straight-shoota) - (runtime) Internalize
IO::EventedintoCrystal::EventLoop::Wasi(#17030, thanks @ysbaddaden) - (runtime) Fix: thread safety of the libevent event loop (#17031, thanks @ysbaddaden)
- (runtime) Drop unused
IO::EventedandCrystal::ThreadLocalValue(#17032, thanks @ysbaddaden) - (runtime) Consolidate
#overlapped_connectand#overlapped_acceptintoEventLoop::IOCP(#17090, thanks @ysbaddaden) - (runtime) OpenBSD now supports EVFILT_USER (#17121, thanks @ysbaddaden)
- (system) Refactor
Dir::Globberto a struct with instance methods (#16899, thanks @straight-shoota) - (system) Refactor internal
Processconstructor to receiveCrystal::System::Process(#16933, thanks @straight-shoota) - (system) dont parse but mmap ELF, Mach-O, PE files and some DWARF sections (#16939, #17134, thanks @ysbaddaden)
compiler
- Replace backticks with
Process.capture(#17012, #17122, thanks @straight-shoota, @ysbaddaden) - (codegen) Set
optsizeandminsizefun attributes for the-Osand-Ozoptimization modes (#16983, thanks @ysbaddaden) - (parser) Parse parens in type grammar into
Union#parens(#16744, #16908, thanks @straight-shoota) - (parser) Refactor whitespace branch in
Lexer#next_macro_token[follow-up #16771] (#16776, thanks @straight-shoota) - (parser) Refactor formatter, remove internal
delimited_pair(advance)(#17023, thanks @straight-shoota)
tools
- (formatter) [breaking] Standardize parsing of symbol and string array literals (#16748, thanks @straight-shoota)
- (formatter) Drop
format_binaryparameteralternative(#16912, thanks @straight-shoota)
other
- Fix violations reported by ameba 1.7 (#17021, thanks @straight-shoota)
Documentation
stdlib
- (cli) Add missing_option to OptionParser example (#17112, thanks @LaskaIDK)
- (macros) Improve docs for
::delegate(#16854, thanks @straight-shoota) - (text) Document null-termination on
String#to_unsafe(#16869, thanks @mvanhorn) - (text) Document
Stringis not inheritable (#17000, thanks @LaskaIDK)
other
- Fix typo
writablein documentation (#16848, thanks @straight-shoota) - Format asciidoc (#16992, thanks @straight-shoota)
- rumdl: Fix MD077: Continuation line over-indented (#17085, thanks @straight-shoota)
Specs
stdlib
- (cli) Refactor
run_gitspec helper to useProcess.capture_result?(#17079, thanks @straight-shoota) - (collection) Add specs for
Iterator.empty(#17014, thanks @straight-shoota) - (concurrency) Fix: Crystal 1.0.0 is confused by file private types (#17067, thanks @ysbaddaden)
- (networking) Extract spec helpers
close_connectionandclient_forfor HTTP client specs (#16968, thanks @straight-shoota) - (text) Add specs for range accessor with open ended exclusive range (#16849, thanks @straight-shoota)
compiler
- (cli) Add
compiler-clitest suite (#17033, thanks @straight-shoota) - (debugger) Fix
lldb-checkexpectations in debug tests for compatibility with modern LLDB (#16860, thanks @straight-shoota)
other
- Remove unnecessary
not_nil!in spec suite (#16865, thanks @straight-shoota) - Replace
not_nil!withshould_not(be_nil)in spec suite (#16906, thanks @straight-shoota)
Infrastructure
- Changelog for 1.21.0 (#17095, thanks @straight-shoota)
- Update previous Crystal release 1.20.0 (#16844, thanks @ysbaddaden)
- Update previous Crystal release 1.20.1 (#16901, thanks @straight-shoota)
- Merge
release/1.19@1.19.2intomaster(#16905, thanks @straight-shoota) - Merge
release/1.20@1.20.1intomaster(#16900, thanks @straight-shoota) - Update
devenv.lock(#16819, #16935, #17006, #17075, #17084, thanks @github-actions, @crysbot) - Update changelog script (#16946, thanks @straight-shoota)
- Extract
CRYSTAL_BOOTSTRAP_VERSIONinbin/ci(#16966, thanks @straight-shoota) - Update previous Crystal release 1.20.2 (#16954, thanks @straight-shoota)
- Makefile: Split
installtarget into subcomponents (#16980, thanks @straight-shoota) - Update
release-updatescript (#16977, thanks @straight-shoota) - Makefile: Build manpages for
installtarget (#16991, thanks @straight-shoota) - Apply
shfmt(#17015, thanks @straight-shoota) - Apply
mbakeformatter forMakefile(#17024, thanks @straight-shoota) - infra: devenv input for
git-hooksfollowsnixpkgs(#17064, thanks @straight-shoota) - Replace
markdownlintwithrumdl(#17069, thanks @straight-shoota) - Replace
.markdownlint.yamlwithrumdl.toml(#17078, thanks @straight-shoota) - (ci) Fix
-Devloop=io_uringflag in Linux CI (#16843, thanks @straight-shoota) - (ci) Use PAT from GHA environments for
backportjob (#16864, thanks @straight-shoota) - (ci) Use AWS credentials from GHA environments for
deploy_api_docsjob (#16863, thanks @straight-shoota) - (ci) Update GH Actions (#16836, #16944, #17011, #17042, [#17117], thanks @renovate)
- (ci) Use Crysbot token in
update-devenvworkflow to trigger CI (#16938, thanks @straight-shoota) - (ci) Fix tags for nightly docker images (#16973, thanks @straight-shoota)
- (ci) Drop separate
aarch64workflow (#16965, thanks @straight-shoota) - (ci) Update crate-ci/typos action to v1.46.2 (#16986, thanks @renovate)
- (ci) Update
macos-15runners tomacos-26(#17022, thanks @straight-shoota) - (ci) Upgrade library dependencies for Windows CI (#17025, thanks @straight-shoota)
- (ci) Upgrade windows runners to VS 2026 (#17043, thanks @straight-shoota)
- (ci) Upgrade nixpkgs 26.05 in
Lintworkflow (#17066, thanks @straight-shoota) - (ci) Update previous Crystal release 1.20.3 (#17114, thanks @ysbaddaden)