Skip to content
GitHub Repository Forum RSS-Newsfeed

Crystal 1.14.0 is released!

Johannes Müller

We are announcing a new Crystal release with several new features and bug fixes.

Pre-built packages are available on GitHub Releases and our official distribution channels. See crystal-lang.org/install for installation instructions.

Stats

This release includes 134 changes since 1.13.3 by 13 contributors. We thank all the contributors for all the effort put into improving the language! ❤️

Advances in multi-threading support

The project to improve multi-threading support with the help of 84codes is still ongoing. This release doesn’t include any big changes. There are a couple of smaller concurrency improvements, though.

We expect to roll out a major performance upgrade to the event loop for the 1.15 development cycle. See New Event Loop (UNIX): call for reviews & tests for a heads up.

The upcoming execution contexts API from RFC 2 is available as a standalone shard for testing: ysbaddaden/execution_context.

Changes

Below we list the most remarkable changes in the language, compiler and stdlib. For more details, visit the full changelog.

Breaking

⚠️ Slice#[start, count] now accepts a negative index for start, like similar methods already do. This would break existing code that depends on the current behaviour that a negative start index raises IndexError (#14778).

⚠️ Finalizers for Socket and IO::FileDescriptor do no longer flush. We realized that flushing is too heavy for a finalizer, as it might involve the event loop and even memory allocations which must be strictly avoided in a finalizer. Be sure to always flush before letting a stream go out of scope, ideally with an explicit #close (#14882).

⚠️ XML::Error.errors had been deprecated since 1.7.0, but continued to work. This unconditioned availability causes a serious memory leak, which cannot be fixed without disabling XML::Error.errors. In order to make this obvious, calling the method causes a compile time error now. (#14936).

⚠️ Hash::Entry has been removed from public API docs. It was never intended to be a public type. (#14881).

Thanks @ysbaddaden, @straight-shoota and @Blacksmoke16

Language features

Allow ^ in constant numeric expressions (#14951). This operator was oddly missing even though | and & were already supported.

Thanks @HertzDevil

HashLiteral and NamedTupleLiteral respond to #has_key?, just like their regular counterparts Hash and NamedTuple (#14890).

Thanks @kamil-gwozdz

Standard library

The WaitGroup concurrency primitive gains some convenience methods, WaitGroup.wait and WaitGroup#spawn (#14837).

require "wait_group"
WaitGroup.wait do |wg|
  10.times do
    wg.spawn do
      sleep 5.seconds
    end
  end
end

Thanks @jgaskins

There are two new methods for working with slices: Slice#same? checks if two slices point to the same memory (#14728). And Pointer::Appender#to_slice (#14874) makes it easy to create a slice containing the items from an appender.

Thanks @straight-shoota

A minor fix turning an eager class getter into a lazy one avoids linking libpcre for programs that do not use Regex (#14891).

Thanks @kojix2

Windows

Windows support is making good progress.

The interpreter runs on Windows (#14964). There is still a limitation: networking does not work due to #12495.

And the compiler can now target ARM64 Windows, i.e. aarch64-windows-msvc. It’s not 100% polished, but looking pretty well. Read #14911 for details on how to test it out. Currently we still need to cross-compile because the compiler itself does not run on ARM64 Windows yet.

Starting with this release, DNS requests resolve asynchronously on Windows (#14979). It’s actually the first platform to support that.

There are also a number of improvements regarding non-blocking IO:

  • Support non-blocking File#read and #write (#14940), File#read_at (#14958), Process.run standard streams (#14941), IO::FileDescriptor#flock_* (#14943).
  • Emulate non-blocking STDIN console (#14947).
  • Open non-blocking regular files as overlapped (#14921).

And we add implementations of System::User (#14933) and System::Group on Windows (#14945).

Thanks @HertzDevil

URI::Params

URI::Params::Serializable is a new serialization API which works similar to the JSON and YAML variants, but for the URI query parameters format (#14684).

require "uri/params/serializable"

record Applicant,
  first_name : String
  last_name : String
  qualities : Array(String) do
  include URI::Params::Serializable
end

applicant = Applicant.from_www_form "first_name=John&last_name=Doe&qualities=kind&qualities=smart"
applicant # => Applicant(@first_name="John", @last_name="Doe", @qualities=["kind", "smart"])
applicant.to_www_form # => "first_name=John&last_name=Doe&qualities=kind&qualities=smart"

Thanks @Blacksmoke16

In a related matter, URI is now applicable as a key in JSON objects via URI.from_json_object_key? (#14834).

Thanks @nobodywasishere

Compiler tools

The compiler binary can now execute external programs as subcommands: crystal foo tries to run crystal-foo if foo is not an internal command. This allows us to split the compiler binary into separate executables which helps improve iteration speed (#14953).

Thanks @bcardiff

Performance

This release includes some minor performance improvements, particularly in the compiler (#14748, #14992, #15002).

Thanks @ysbaddaden, @HertzDevil, @ggiraldez

Dependency Updates

  • LibCrypto bindings now support LibreSSL 3.5+ (#14872).
  • Support for Unicode 16.0.0 (#14997).
  • Support for LLVM 19.1 (#14842)

Thanks @straight-shoota, @HertzDevil

Deprecations

Pointer.new(Int) was deprecated in favour of Pointer.new(UInt64) (#14875). Deprecation warnings for argument type that autocast to UInt64 can be ignored or disabled by explicitly casting to UInt64.

Thanks @straight-shoota

We updated a couple of APIs that receive a time span argument. Benchmark.ips (#14805) and ::sleep (#14962) now explicitly require Time::Span. The overloads with Number are deprecated. You can convert bare numbers with Int#seconds to use the valid overload.

Thanks @HertzDevil


Thanks

We have been able to do all of this thanks to the continued support of 84codes and every other sponsor. To maintain and increase the development pace, donations and sponsorships are essential. OpenCollective is available for that.

Reach out to crystal@manas.tech if you’d like to become a direct sponsor or find other ways to support Crystal. We thank you in advance!

Contribute