authors/bcardiff.jpg Brian J. Cardiff 23 Sep 2019

Crystal 0.31.0 released!

Crystal 0.31.0 has been released!

This release comes with multi-threading preview, changes in numbers, performance improvements and as usual fixes and improvements in across the std-lib.

There are 191 commits since 0.30.1 by 23 contributors.

Let’s review some highlights in this release. But don’t miss the rest of the release changelog which has a lot of valuable information.

Language changes

There is a new, and cleaner, way to declare type restrictions for non-captured blocks in a method.

A nameless parameter & can now appear at the end of the list. It can optionally have type restrictions that will be used by the compiler and by the doc tool.

def foo(x, y, & : Int32 -> Int32)

There is no need to rewrite your current code base, but it’s a feature that will improve a bit the understanding to the reader. Especially if you used &block : T -> S, but didn’t mention block in the method body. Read more at #8117.


Since Crystal 0.29 the compiler is able to emit warnings. This feature is now opt-out, since the default is changed to --warnings=all. This will help you identify usages of deprecated methods and other language constructs as they appear. Read more at #8171.

LLVM 8.0 is used in the Linux official packages. Read more at #8155.

Standard library


One of the most awaited features landed between the previous release and this one, behind the -Dpreview_mt flag: Multithreading. Even after merging #8112 there were a couple of iterations to fix corner cases and stabilize the runtime.

Don’t miss its dedicated blog post where you can find out how to use it, the main API changes and its current limitations.


There were a couple of changes in the numeric part of the std-lib announced a long time ago that finally made its way in this release.

Overflows are handled by default. Int32::MAX + 1 will no longer wrap around. In case you need non-overflow operation you can use Int32::MAX &+ 1. Same with - and *. In some architectures LLVM requires the compiler-rt library. We ported what was needed so there is no external dependency. If the new default behavior is blocking you, use -Ddisable_overflow to keep the same semantics as in 0.30 or -Dskip_crystal_compiler_rt to not include out compiler-rt port and link against another build of it. The disable_overflow flag is temporal and it will go away. Read more at #8170.

The / will represent always the arithmetic division. This also means its result will be a float (of some kind). The expression a.sum / a.size will return the average, whatever numeric type is used in a. If you want the integer division that preserves the type of the left-hand side operarand use //. Read more at #8120.


The major changes in the collections are related to performance. Array and Hash were in the eye of these changes #8017, #8042, #8048, #8087, #8116. There seems to always be room for improvement (take 1).


There is a breaking-change regarding XML, yet the main API has not changed. Read more at #8134

A probably more impactful change is that JSON and YAML deserialization can now handle NamedTuple with nilable fields. Read more at #8109.

And there was some missing setting in YAML to emit unicode. Read more at #8132.


Optimizations were not only present in collections. Follow the path and you will find improvements in Path#join and Dir.glob. #8078, #8082, #8081. There seems to always be room for improvement (take 2).


The HTTP::Server::Response#respond_with_error is deprecated in favor of #respond_with_status that will also handle the final state of the connection and default status description. Read more at #6988.

The built-in HTTP server will respond in a more controlled way to requests with long URIs or large header fields. The default limit of 1MB can be configured. The response will be 414 Request-URI too long and 431 Request Header Fields Too Large respectively. This logic is implemented in HTTP::Request.from_io. Read more at #8013.

Other deprecations

The Markdown module is no longer exposed in the std-lib. It’s still used internally and there is an ongoing discussion regarding a future official markdown package. For now, the best replacement is icyleaf/markd. Read more at #8115 and #4613.

You should drop the ! from OptionParser#parse!. Read more at #8041.

Crystal-db 0.7.0

A new release of crystal-lang/crystal-db is also available. Updates to drivers and frameworks were sent to use the new release.

Some concurrency issues that might cause a peak in the number of connections created were fixed. This is also an important update for multi-threading contexts. Read more at crystal-db#109.

There is also a breaking-change required to avoid an ambiguity for drivers that support columns with Array values. db.query("SELECT ...", [1,2]) now means a single argument: [1, 2], and db.query("SELECT ...", args: [1, 2]) means that two arguments are passed to the query.


Given a describe, context or it in a spec, you can now add a focus: true. When you do that, only the things that are marked with focus: true will run.

Also, if a line that ended someplace outside the it but inside a describe is specified, the whole describe will run.

This new behavior leads to a breaking change in case you shared local variables within it blocks. Read more at #8125.

Doc generator

Writing documentation for a type hierarchy got a bit better. The content of a previous def or ancestor is automatically inherited (with a nice note stating so) or it can be explicitly placed within new docs using an :inherit: placeholder. Read more at #6989.

Next steps

Please update your Crystal and report any issues. We will keep moving forward and start the development focusing on 0.32.

It will also be helpful if your shards are run against Crystal nightly releases. Either Docker or Snap are the current channels to get them easily. This will help reduce the friction of a release while checking if the ecosystem is in good shape.

We have been able to do all of this thanks to the continued support of 84codes, and every other sponsor. It is extremely important for us to sustain the support through donations, so that we can maintain this development pace. OpenCollective and Bountysource are two available channels for that. Reach out to if you’d like to become a direct sponsor or find other ways to support Crystal. We thank you in advance!