# Changelog 1.20

## [1.20.3] (2026-07-02)

[1.20.3]: https://github.com/crystal-lang/crystal/releases/1.20.3

### Bugfixes

#### stdlib

- _(serialization)_ **[security]** add `max_nesting` to `YAML::PullParser` ([#17107], thanks @ysbaddaden)
- _(serialization)_ **[security]** add alias vs anchor ratio check to `YAML::PullParser` ([#17109], thanks @ysbaddaden)

[#17107]: https://github.com/crystal-lang/crystal/pull/17107
[#17109]: https://github.com/crystal-lang/crystal/pull/17109

### Refactor

#### stdlib

- _(serialization)_ `YAML::PullParser`: memoize anchor name ([#17108], thanks @ysbaddaden)

[#17108]: https://github.com/crystal-lang/crystal/pull/17108

## [1.20.2] (2026-05-15)

[1.20.2]: https://github.com/crystal-lang/crystal/releases/1.20.2

### Bugfixes

#### stdlib

- _(concurrency)_ **[regression]** Simplify `Sync::Mutex#synchronize` proc type constraints ([#16904], [#16937], thanks @ysbaddaden)
- _(runtime)_ `Range#sample` eventually loses randomness ([#16909], thanks @ysbaddaden)

[#16904]: https://github.com/crystal-lang/crystal/pull/16904
[#16909]: https://github.com/crystal-lang/crystal/pull/16909
[#16937]: https://github.com/crystal-lang/crystal/pull/16937

### Infrastructure

- Changelog for 1.20.2 ([#16945], thanks @straight-shoota)

[#16945]: https://github.com/crystal-lang/crystal/pull/16945

## [1.20.1] (2026-04-29)

[1.20.1]: https://github.com/crystal-lang/crystal/releases/1.20.1

### Bugfixes

#### stdlib

- _(crypto)_ Fix issues in OpenSSL Kernel TLS ([#16888], thanks @ysbaddaden)
- _(crypto)_ OpenSSL Kernel TLS support should be opt-in ([#16897], thanks @ysbaddaden)
- _(networking)_ **[regression]** Add `HTTP::Headers#to_json` and `#to_yaml` ([#16890], thanks @straight-shoota)
- _(runtime)_ **[regression]** `Range#sample` eventually loses randomness ([#16853], thanks @ysbaddaden)
- _(runtime)_ don't parse debug sections from bare threads ([#16877], thanks @ysbaddaden)

[#16853]: https://github.com/crystal-lang/crystal/pull/16853
[#16877]: https://github.com/crystal-lang/crystal/pull/16877
[#16888]: https://github.com/crystal-lang/crystal/pull/16888
[#16890]: https://github.com/crystal-lang/crystal/pull/16890
[#16897]: https://github.com/crystal-lang/crystal/pull/16897

#### compiler

- _(parser)_ **[regression]** Fix lexing macro delimiter state inside literals ([#16892], thanks @straight-shoota)

[#16892]: https://github.com/crystal-lang/crystal/pull/16892

#### tools

- _(formatter)_ **[regression]** Revert "Refactor `Formatter` code for simplification" ([#16885], thanks @straight-shoota)

[#16885]: https://github.com/crystal-lang/crystal/pull/16885

### Refactor

#### stdlib

- _(runtime)_ Refactor `Exception::CallStack` for better boundaries ([#16896], thanks @straight-shoota)

[#16896]: https://github.com/crystal-lang/crystal/pull/16896

### Infrastructure

- Changelog for 1.20.1 ([#16898], thanks @straight-shoota)

[#16898]: https://github.com/crystal-lang/crystal/pull/16898

## [1.20.0] (2026-04-16)

[1.20.0]: https://github.com/crystal-lang/crystal/releases/1.20.0

### Security

#### stdlib

- _(networking)_ Fix `HTTP::Server` is no longer vulnerable to request smuggling ([GHSA-wqh5-7w63-pm68])

[GHSA-wqh5-7w63-pm68]: https://github.com/crystal-lang/crystal/security/advisories/GHSA-wqh5-7w63-pm68

### Features

#### lang

- _(macros)_ Add `#select` and `#reject` to `HashLiteral` and `NamedTupleLiteral` ([#16558], thanks @Blacksmoke16)
- _(macros)_ Refine error message for unsupported named arguments in macros ([#16576], thanks @hahwul)

[#16558]: https://github.com/crystal-lang/crystal/pull/16558
[#16576]: https://github.com/crystal-lang/crystal/pull/16576

#### stdlib

- _(cli)_ Add short option bundling for `OptionParser` ([#16770], thanks @Qard)
- _(crypto)_ Add Kernel TLS support to custom `OpenSSL::BIO` ([#16646], thanks @ysbaddaden)
- _(files)_ Add `IO#read_greedy` ([#16535], thanks @BlobCodes)
- _(files)_ Add `FileUtils#rm_f` ([#12832], thanks @zw963)
- _(files)_ Add `IO::PrefixSuffixBuffer` for capturing truncated streams ([#16774], thanks @straight-shoota)
- _(llvm)_ Support LLVM 22.1 and 23.0 ([#16631], thanks @HertzDevil)
- _(networking)_ Add `Sec-WebSocket-Protocol` checks to `HTTP::WebSocket::Protocol` ([#16600], [#16671], thanks @antondalgren, @straight-shoota)
- _(networking)_ Add support for `Sec-WebSocket-Protocol` to `HTTP::WebSocketHandler` ([#16574], thanks @antondalgren)
- _(networking)_ Add `HTTP::Response#content_type` and `#content_length` as convenient accessors ([#16712], thanks @CTC97)
- _(networking)_ Detect `OAuth` error in payload ([#16634], [#16828], thanks @jgaskins, @Sija)
- _(runtime)_ Add `Fiber::ExecutionContext::ThreadPool` ([#15885], [#16750], thanks @ysbaddaden)
- _(runtime)_ Add `Pointer#align_up` and `#align_down` ([#16585], thanks @BlobCodes)
- _(runtime)_ Detach execution context scheduler from running thread during blocking syscall ([#15871], [#16679], thanks @ysbaddaden)
- _(runtime)_ Forward API docs for properties in `record` macro ([#16172], [#16834], thanks @Vici37, @ysbaddaden)
- _(runtime)_ Add `Crystal::Lock` ([#16768], thanks @ysbaddaden)
- _(runtime)_ Add io_uring event loop (linux) ([#16264], thanks @ysbaddaden)
- _(system)_ Use `FdLock` on all targets ([#16569], thanks @ysbaddaden)
- _(system)_ Add `Process.new` with `args` instead of `command, args` ([#16681], thanks @straight-shoota)
- _(system)_ Add `Process.run(args)` without `command` ([#16739], thanks @straight-shoota)
- _(system)_ Add `Process.run?` ([#16738], thanks @straight-shoota)
- _(system)_ Add `Process.capture` ([#16773], thanks @straight-shoota)
- _(text)_ Add `StringScanner#scan`, `#check`, and `#skip` overloads for `Int` ([#16557], thanks @jneen)
- _(text)_ Add `StringScanner#peek_behind` ([#16593], thanks @jneen)
- _(text)_ Add convenience methods to `StringScanner` ([#16595], thanks @jneen)
- _(text)_ Improve cursor window format in `StringScanner#inspect` ([#16594], thanks @jneen)

[#12832]: https://github.com/crystal-lang/crystal/pull/12832
[#15871]: https://github.com/crystal-lang/crystal/pull/15871
[#15885]: https://github.com/crystal-lang/crystal/pull/15885
[#16172]: https://github.com/crystal-lang/crystal/pull/16172
[#16264]: https://github.com/crystal-lang/crystal/pull/16264
[#16535]: https://github.com/crystal-lang/crystal/pull/16535
[#16557]: https://github.com/crystal-lang/crystal/pull/16557
[#16569]: https://github.com/crystal-lang/crystal/pull/16569
[#16574]: https://github.com/crystal-lang/crystal/pull/16574
[#16585]: https://github.com/crystal-lang/crystal/pull/16585
[#16593]: https://github.com/crystal-lang/crystal/pull/16593
[#16594]: https://github.com/crystal-lang/crystal/pull/16594
[#16595]: https://github.com/crystal-lang/crystal/pull/16595
[#16600]: https://github.com/crystal-lang/crystal/pull/16600
[#16631]: https://github.com/crystal-lang/crystal/pull/16631
[#16634]: https://github.com/crystal-lang/crystal/pull/16634
[#16646]: https://github.com/crystal-lang/crystal/pull/16646
[#16671]: https://github.com/crystal-lang/crystal/pull/16671
[#16679]: https://github.com/crystal-lang/crystal/pull/16679
[#16681]: https://github.com/crystal-lang/crystal/pull/16681
[#16712]: https://github.com/crystal-lang/crystal/pull/16712
[#16738]: https://github.com/crystal-lang/crystal/pull/16738
[#16739]: https://github.com/crystal-lang/crystal/pull/16739
[#16750]: https://github.com/crystal-lang/crystal/pull/16750
[#16768]: https://github.com/crystal-lang/crystal/pull/16768
[#16770]: https://github.com/crystal-lang/crystal/pull/16770
[#16773]: https://github.com/crystal-lang/crystal/pull/16773
[#16774]: https://github.com/crystal-lang/crystal/pull/16774
[#16828]: https://github.com/crystal-lang/crystal/pull/16828
[#16834]: https://github.com/crystal-lang/crystal/pull/16834

#### compiler

- _(cli)_ Prefer modern linker (`mold` or `lld`) ([#16696], thanks @straight-shoota)
- _(codegen)_ Add `@[TargetFeature]` annotation ([#16717], [#16835], thanks @stakach, @ysbaddaden)
- _(parser)_ Parse `ProcNotation` with empty arg parenthesis: `() ->` ([#16741], thanks @straight-shoota)

[#16696]: https://github.com/crystal-lang/crystal/pull/16696
[#16717]: https://github.com/crystal-lang/crystal/pull/16717
[#16741]: https://github.com/crystal-lang/crystal/pull/16741
[#16835]: https://github.com/crystal-lang/crystal/pull/16835

#### tools

- _(docs-generator)_ Add `--base-path` for `crystal docs` ([#16091], thanks @matiasgarciaisaia)

[#16091]: https://github.com/crystal-lang/crystal/pull/16091

### Bugfixes

#### stdlib

- _(compress)_ Fix decode gzip MTIME as `UInt32` ([#16730], thanks @kojix2)
- _(crypto)_ **[breaking]** OpenSSL sockets shouldn't flush on read ([#16650], thanks @ysbaddaden)
- _(crypto)_ Fix typo in digest.cr ([#16808], thanks @kojix2)
- _(files)_ Fix MIME.parse_media_type invalid character check ([#16793], thanks @cuiweixie)
- _(networking)_ **[regression]** Fix `HTTP::Headers#merge!` to not wrap key ([#16624], thanks @straight-shoota)
- _(networking)_ Fix `forward_missing_to` in `HTTP::Headers` ([#16637], thanks @straight-shoota)
- _(networking)_ Fix `Socket::IPAddress` IPv4 address in IPv6 with zone identifier ([#16813], thanks @straight-shoota)
- _(numeric)_ Fix `Indexable#range_to_index_and_count` with unsigned integers ([#16597], thanks @jneen)
- _(numeric)_ **[regression]** Fix `Float32#abs` to return `Float32` ([#16655], thanks @straight-shoota)
- _(numeric)_ Fix signedness in GMP FFI bindings ([#16799], thanks @kojix2)
- _(runtime)_ Rename filename to path in WASI `EventLoop#open` ([#16636], thanks @kojix2)
- _(runtime)_ `Thread.sleep` is invalid when duration >= 1 minute ([#16629], thanks @ysbaddaden)
- _(runtime)_ Fix typos in ELF reader ([#16668], thanks @kojix2)
- _(runtime)_ don't terminate thread on Windows/IOCP ([#16680], thanks @ysbaddaden)
- _(runtime)_ `Sync::ConditionVariable` can hang forever ([#16677], thanks @ysbaddaden)
- _(runtime)_ Fix `Pointer#to_s` with lib typedefs ([#16687], thanks @straight-shoota)
- _(runtime)_ Fix race condition in `Process#wait` on Windows ([#16766], thanks @ysbaddaden)
- _(serialization)_ call `xmlFree` for string pointer from `xmlNodeGetContent` ([#16688], thanks @toddsundsted)
- _(serialization)_ Fix sequence_end_event_initialize return type ([#16803], thanks @kojix2)
- _(system)_ Fix `Dir.glob` matching wildcard with dot directory ([#16604], thanks @straight-shoota)
- _(system)_ Lenient `Fiber.current` access on segfault handler ([#16612], thanks @bcardiff)
- _(system)_ **[breaking]** Fix `Process#wait` to not close `@input` before waiting ([#16620], [#16638], thanks @straight-shoota, @ysbaddaden)
- _(system)_ Fix `System.cpu_count` returns `Int32` ([#16648], thanks @straight-shoota)
- _(system)_ Fix `Process.new(args)` etc. support `Enumerable(String)` args ([#16784], thanks @straight-shoota)
- _(text)_ Fix `String#scan` zero-width matches with multibyte characters ([#16684], thanks @error256)
- _(text)_ Fix PCRE2 FFI type declarations ([#16804], thanks @kojix2)
- _(text)_ Fix blink_fast reset code ([#16806], thanks @kojix2)

[#16597]: https://github.com/crystal-lang/crystal/pull/16597
[#16604]: https://github.com/crystal-lang/crystal/pull/16604
[#16612]: https://github.com/crystal-lang/crystal/pull/16612
[#16620]: https://github.com/crystal-lang/crystal/pull/16620
[#16624]: https://github.com/crystal-lang/crystal/pull/16624
[#16629]: https://github.com/crystal-lang/crystal/pull/16629
[#16636]: https://github.com/crystal-lang/crystal/pull/16636
[#16637]: https://github.com/crystal-lang/crystal/pull/16637
[#16638]: https://github.com/crystal-lang/crystal/pull/16638
[#16648]: https://github.com/crystal-lang/crystal/pull/16648
[#16650]: https://github.com/crystal-lang/crystal/pull/16650
[#16655]: https://github.com/crystal-lang/crystal/pull/16655
[#16668]: https://github.com/crystal-lang/crystal/pull/16668
[#16677]: https://github.com/crystal-lang/crystal/pull/16677
[#16680]: https://github.com/crystal-lang/crystal/pull/16680
[#16684]: https://github.com/crystal-lang/crystal/pull/16684
[#16687]: https://github.com/crystal-lang/crystal/pull/16687
[#16688]: https://github.com/crystal-lang/crystal/pull/16688
[#16730]: https://github.com/crystal-lang/crystal/pull/16730
[#16766]: https://github.com/crystal-lang/crystal/pull/16766
[#16784]: https://github.com/crystal-lang/crystal/pull/16784
[#16793]: https://github.com/crystal-lang/crystal/pull/16793
[#16799]: https://github.com/crystal-lang/crystal/pull/16799
[#16803]: https://github.com/crystal-lang/crystal/pull/16803
[#16804]: https://github.com/crystal-lang/crystal/pull/16804
[#16806]: https://github.com/crystal-lang/crystal/pull/16806
[#16808]: https://github.com/crystal-lang/crystal/pull/16808
[#16813]: https://github.com/crystal-lang/crystal/pull/16813

#### compiler

- _(codegen)_ Emit `unreachable` for inlined `NoReturn` returns ([#16690], thanks @kojix2)
- _(codegen)_ Fix alignment for fields in packed structs for x86_64 ABI ([#16667], thanks @kojix2)
- _(codegen)_ Fix `declare_fun` attribute copy ([#16708], thanks @kojix2)
- _(parser)_ **[breaking]** Ensure that heredoc lexing allows only valid identifiers ([#16548], thanks @Sija)
- _(parser)_ **[regression]** Fix lexing percent literals with `|` delimiter in macro context ([#16672], [#16716], thanks @toddsundsted, @straight-shoota)
- _(parser)_ Escape quotes in the filename within the location pragmas ([#16549], thanks @Sija)
- _(semantic)_ Fix constant lookup in ivar initializer blocks ([#16678], thanks @nobodywasishere)
- _(semantic)_ Fix ICE on alias generic instance namespace lookup ([#16700], thanks @nobodywasishere)
- _(semantic)_ Fix tuple splat validation ([#16787], thanks @kojix2)
- _(semantic)_ Add arithmetic error reporting for MathInterpreter ([#16809], thanks @kojix2)

[#16548]: https://github.com/crystal-lang/crystal/pull/16548
[#16549]: https://github.com/crystal-lang/crystal/pull/16549
[#16667]: https://github.com/crystal-lang/crystal/pull/16667
[#16672]: https://github.com/crystal-lang/crystal/pull/16672
[#16678]: https://github.com/crystal-lang/crystal/pull/16678
[#16690]: https://github.com/crystal-lang/crystal/pull/16690
[#16700]: https://github.com/crystal-lang/crystal/pull/16700
[#16708]: https://github.com/crystal-lang/crystal/pull/16708
[#16716]: https://github.com/crystal-lang/crystal/pull/16716
[#16787]: https://github.com/crystal-lang/crystal/pull/16787
[#16809]: https://github.com/crystal-lang/crystal/pull/16809

#### tools

- _(formatter)_ Fix formatter `ProcNotation` with parens around argument type ([#16753], thanks @straight-shoota)
- _(formatter)_ Fix track line increment when formatting macro literal only ([#16761], thanks @straight-shoota)
- _(formatter)_ Fix formatter indent and newlines between expression items ([#16769], thanks @straight-shoota)
- _(formatter)_ Fix formatter increment `@line` only on write ([#16762], thanks @straight-shoota)

[#16753]: https://github.com/crystal-lang/crystal/pull/16753
[#16761]: https://github.com/crystal-lang/crystal/pull/16761
[#16762]: https://github.com/crystal-lang/crystal/pull/16762
[#16769]: https://github.com/crystal-lang/crystal/pull/16769

### Chores

#### stdlib

- _(system)_ Add `@[Experimental]` annotation to new Process API ([#16816], thanks @straight-shoota)

[#16816]: https://github.com/crystal-lang/crystal/pull/16816

### Performance

#### stdlib

- _(time)_ Improve performance of `System::Time.monotonic` on Windows ([#16555], thanks @straight-shoota)

[#16555]: https://github.com/crystal-lang/crystal/pull/16555

### Refactor

#### stdlib

- _(crypto)_ dust off `OpenSSL::BIO` ([#16640], thanks @ysbaddaden)
- _(crypto)_ Refactor initialization of custom OpenSSL BIO ([#16651], thanks @ysbaddaden)
- _(numeric)_ **[experimental]** Use `Slice.literal` for `fast_float` when supported, part 2 ([#16261], thanks @HertzDevil)
- _(runtime)_ **[deprecation]** Soft deprecate `Mutex` in favor to `Sync::Mutex` ([#16737], [#16759], [#16802], thanks @ysbaddaden)
- _(runtime)_ Protect `Crystal::System::Env` with `Sync::RWLock` (UNIX) ([#16591], thanks @ysbaddaden)
- _(runtime)_ Refactor `System::Process.make_env_block` into `System::Env` (win32) ([#16605], thanks @ysbaddaden)
- _(runtime)_ Use `System.wstr_literal` for env names on Win32 ([#16669], thanks @kojix2)
- _(runtime)_ Add adaptive scaling to `ExecutionContext::Parallel` ([#16719], thanks @ysbaddaden)
- _(runtime)_ Handle events in `EventLoop::IOCP` instead of `System::IOCP` ([#16765], thanks @ysbaddaden)
- _(runtime)_ Add internal state to `Fiber::ExecutionContext::Parallel::Scheduler` ([#16732], thanks @ysbaddaden)
- _(runtime)_ Replace `Mutex` use cases with `Sync::Mutex` ([#16783], thanks @ysbaddaden)
- _(specs)_ Prefer `with_env` helper over mutating `ENV` in specs ([#16608], thanks @ysbaddaden)
- _(specs)_ Remove unnecessary `shell: true` from `Process.run` calls ([#16781], thanks @ysbaddaden)
- _(system)_ Avoid deprecated `Pointer.new(Int)` in `dlfcn` ([#16691], thanks @kojix2)
- _(system)_ Refactor code duplication in `Process.new` overloads ([#16782], thanks @straight-shoota)

[#16261]: https://github.com/crystal-lang/crystal/pull/16261
[#16591]: https://github.com/crystal-lang/crystal/pull/16591
[#16605]: https://github.com/crystal-lang/crystal/pull/16605
[#16608]: https://github.com/crystal-lang/crystal/pull/16608
[#16640]: https://github.com/crystal-lang/crystal/pull/16640
[#16651]: https://github.com/crystal-lang/crystal/pull/16651
[#16669]: https://github.com/crystal-lang/crystal/pull/16669
[#16691]: https://github.com/crystal-lang/crystal/pull/16691
[#16719]: https://github.com/crystal-lang/crystal/pull/16719
[#16732]: https://github.com/crystal-lang/crystal/pull/16732
[#16737]: https://github.com/crystal-lang/crystal/pull/16737
[#16759]: https://github.com/crystal-lang/crystal/pull/16759
[#16765]: https://github.com/crystal-lang/crystal/pull/16765
[#16781]: https://github.com/crystal-lang/crystal/pull/16781
[#16782]: https://github.com/crystal-lang/crystal/pull/16782
[#16783]: https://github.com/crystal-lang/crystal/pull/16783
[#16802]: https://github.com/crystal-lang/crystal/pull/16802

#### compiler

- _(parser)_ Refactor parsing interpolation ([#16693], thanks @straight-shoota)
- _(parser)_ Standardize `DelimiterState#open_count` to initialize with `0` ([#16771], thanks @straight-shoota)

[#16693]: https://github.com/crystal-lang/crystal/pull/16693
[#16771]: https://github.com/crystal-lang/crystal/pull/16771

#### tools

- _(formatter)_ Extract helper methods for formatter string interpolation ([#16720], [#16747], thanks @straight-shoota)
- _(formatter)_ Refactor `Formatter` code for simplification ([#16745], thanks @straight-shoota)

[#16720]: https://github.com/crystal-lang/crystal/pull/16720
[#16745]: https://github.com/crystal-lang/crystal/pull/16745
[#16747]: https://github.com/crystal-lang/crystal/pull/16747

### Documentation

#### stdlib

- _(llvm)_ Fix typo ([#16694], thanks @straight-shoota)
- _(runtime)_ Add Safety section to `ENV` documentation ([#16592], [#16599], thanks @ysbaddaden)
- _(runtime)_ Fix: `thread_local` macro exposes `Thread` class in stdlib docs ([#16714], thanks @ysbaddaden)
- _(runtime)_ Improve docs for `Fiber::ExecutionContext` ([#16602], thanks @ysbaddaden)
- _(runtime)_ Remove invalid `Pointer.new` constructor from API docs ([#16734], thanks @ysbaddaden)
- _(runtime)_ Document that reentrant read lock can deadlock ([#16833], thanks @ysbaddaden)
- _(system)_ Improve documentation for `Process.run` & co ([#16618], thanks @straight-shoota)

[#16592]: https://github.com/crystal-lang/crystal/pull/16592
[#16599]: https://github.com/crystal-lang/crystal/pull/16599
[#16602]: https://github.com/crystal-lang/crystal/pull/16602
[#16618]: https://github.com/crystal-lang/crystal/pull/16618
[#16694]: https://github.com/crystal-lang/crystal/pull/16694
[#16714]: https://github.com/crystal-lang/crystal/pull/16714
[#16734]: https://github.com/crystal-lang/crystal/pull/16734
[#16833]: https://github.com/crystal-lang/crystal/pull/16833

### Specs

#### stdlib

- _(concurrency)_ Fix: modernize channel specs to avoid parallelism issues ([#16704], thanks @ysbaddaden)
- _(runtime)_ Fix: increase timeout of execution context stress test helper ([#16639], thanks @ysbaddaden)
- _(runtime)_ Fix: `Fiber#resumable?` spec must run in concurrent context ([#16731], thanks @ysbaddaden)
- _(system)_ Add specs for `Process.run(shell: true)` with `PATH` ([#16617], thanks @straight-shoota)

[#16617]: https://github.com/crystal-lang/crystal/pull/16617
[#16639]: https://github.com/crystal-lang/crystal/pull/16639
[#16704]: https://github.com/crystal-lang/crystal/pull/16704
[#16731]: https://github.com/crystal-lang/crystal/pull/16731

#### compiler

- Add `Crystal::Config.path=` for spec helper ([#16613], thanks @straight-shoota)
- _(codegen)_ Rename duplicated "between 64 and 128 bits" case ([#16683], thanks @kojix2)
- _(codegen)_ Add "compile" spec helper ([#16735], thanks @ysbaddaden)
- _(parser)_ Add parser specs for escaping in delimited literals ([#16703], [#16709], thanks @straight-shoota)
- _(parser)_ Refactor `assert_syntax_error` to use `expect_raises` ([#16711], thanks @straight-shoota)
- _(parser)_ Enhance parser specs for escaping delimiters [follow-up #16703] ([#16721], thanks @straight-shoota)
- _(parser)_ Add formatter specs for `ProcNotation` ([#16742], thanks @straight-shoota)
- _(parser)_ Add `spec/syntax_spec.cr` ([#16749], thanks @straight-shoota)
- _(parser)_ Add specs for parsing `MacroVar` syntax inside literals ([#16778], thanks @straight-shoota)
- _(semantic)_ Fix typo in `Link` annotation spec ([#16710], thanks @kojix2)

[#16613]: https://github.com/crystal-lang/crystal/pull/16613
[#16683]: https://github.com/crystal-lang/crystal/pull/16683
[#16703]: https://github.com/crystal-lang/crystal/pull/16703
[#16709]: https://github.com/crystal-lang/crystal/pull/16709
[#16710]: https://github.com/crystal-lang/crystal/pull/16710
[#16711]: https://github.com/crystal-lang/crystal/pull/16711
[#16721]: https://github.com/crystal-lang/crystal/pull/16721
[#16735]: https://github.com/crystal-lang/crystal/pull/16735
[#16742]: https://github.com/crystal-lang/crystal/pull/16742
[#16749]: https://github.com/crystal-lang/crystal/pull/16749
[#16778]: https://github.com/crystal-lang/crystal/pull/16778

#### tools

- _(formatter)_ Improve formatter spec helper to show trailing whitespace ([#16760], thanks @straight-shoota)

[#16760]: https://github.com/crystal-lang/crystal/pull/16760

### Infrastructure

- Changelog for 1.20.0 ([#16751], thanks @straight-shoota)
- Update previous Crystal release 1.19.0 ([#16572], thanks @ysbaddaden)
- Update `devenv.lock` ([#16426], [#16588], [#16658], [#16673], [#16775], [#16586], [#16623], thanks @github-actions)
- Update previous Crystal release 1.19.1 ([#16598], thanks @ysbaddaden)
- Drop `ENV.[]=` in `generate_windows_zone_names` ([#16606], thanks @straight-shoota)
- Update devenv 2.0 ([#16705], thanks @straight-shoota)
- Add changelogs for older releases ([#16698], [#16791], thanks @straight-shoota)
- Disable buggy ameba rule `Lint/SpecFocus` ([#16740], thanks @straight-shoota)
- scripts/github-changelog.cr: Group PRs with same name ([#16788], thanks @straight-shoota)
- scripts/github-changelog.cr: Sort link ref labels by PR number ([#16789], thanks @straight-shoota)
- scripts/update-changelog.sh: Fix escape output of final command ([#16790], thanks @straight-shoota)
- _(ci)_ Adjust triggers for `update-devenv` workflow ([#16587], thanks @straight-shoota)
- _(ci)_ Update GH Actions ([#16546], [#16619], [#16660], [#16702], [#16786], [#16654], [#16800], thanks @renovate)
- _(ci)_ Refactor Linux CI workflows ([#16615], thanks @ysbaddaden)
- _(ci)_ Fix lint workflow to use `prek` instead of `pre-commit` ([#16653], thanks @straight-shoota)
- _(ci)_ Add `fail-fast: false` to all matrix strategies ([#16656], thanks @straight-shoota)
- _(ci)_ Drop separate lint workflows for actionlint and shellcheck ([#16663], thanks @straight-shoota)
- _(ci)_ Run `lint` workflow on all files when `devenv.lock` was changed ([#16682], thanks @straight-shoota)
- _(ci)_ Pin `nixpkgs` in `lint` workflow ([#16706], thanks @straight-shoota)
- _(ci)_ Update cachix/install-nix-action digest to 1ca7d21 ([#16727], thanks @renovate)
- _(ci)_ Test stdlib with execution contexts on Windows and macOS ([#16701], thanks @ysbaddaden)

[#16426]: https://github.com/crystal-lang/crystal/pull/16426
[#16546]: https://github.com/crystal-lang/crystal/pull/16546
[#16572]: https://github.com/crystal-lang/crystal/pull/16572
[#16586]: https://github.com/crystal-lang/crystal/pull/16586
[#16587]: https://github.com/crystal-lang/crystal/pull/16587
[#16588]: https://github.com/crystal-lang/crystal/pull/16588
[#16598]: https://github.com/crystal-lang/crystal/pull/16598
[#16606]: https://github.com/crystal-lang/crystal/pull/16606
[#16615]: https://github.com/crystal-lang/crystal/pull/16615
[#16619]: https://github.com/crystal-lang/crystal/pull/16619
[#16623]: https://github.com/crystal-lang/crystal/pull/16623
[#16653]: https://github.com/crystal-lang/crystal/pull/16653
[#16654]: https://github.com/crystal-lang/crystal/pull/16654
[#16656]: https://github.com/crystal-lang/crystal/pull/16656
[#16658]: https://github.com/crystal-lang/crystal/pull/16658
[#16660]: https://github.com/crystal-lang/crystal/pull/16660
[#16663]: https://github.com/crystal-lang/crystal/pull/16663
[#16673]: https://github.com/crystal-lang/crystal/pull/16673
[#16682]: https://github.com/crystal-lang/crystal/pull/16682
[#16698]: https://github.com/crystal-lang/crystal/pull/16698
[#16701]: https://github.com/crystal-lang/crystal/pull/16701
[#16702]: https://github.com/crystal-lang/crystal/pull/16702
[#16705]: https://github.com/crystal-lang/crystal/pull/16705
[#16706]: https://github.com/crystal-lang/crystal/pull/16706
[#16727]: https://github.com/crystal-lang/crystal/pull/16727
[#16740]: https://github.com/crystal-lang/crystal/pull/16740
[#16751]: https://github.com/crystal-lang/crystal/pull/16751
[#16775]: https://github.com/crystal-lang/crystal/pull/16775
[#16786]: https://github.com/crystal-lang/crystal/pull/16786
[#16788]: https://github.com/crystal-lang/crystal/pull/16788
[#16789]: https://github.com/crystal-lang/crystal/pull/16789
[#16790]: https://github.com/crystal-lang/crystal/pull/16790
[#16791]: https://github.com/crystal-lang/crystal/pull/16791
[#16800]: https://github.com/crystal-lang/crystal/pull/16800
