---
title: Crystal 0.34.0 released!
version: 0.34.0
summary: Crystal has a new development release.
thumbnail: +
author: bcardiff
comment_href: https://disqus.com/home/discussion/crystal-lang/crystal_0340_released/
---


[Crystal 0.34.0](https://github.com/crystal-lang/crystal/releases/tag/0.34.0) has been released!

Get excited because this release comes with some of the final touches to the language before 1.0: a better exception hierarchy to replace Errno, a new logging module, cleanups and fixes aiming for a better, more stable release, one that should make us all proud.

There are [183 commits since 0.33.0](https://github.com/crystal-lang/crystal/compare/0.33.0...0.34.0) by 26 contributors.

Let’s get right into some of the highlights in this release. But don't miss out on the rest of the [release changelog](https://github.com/crystal-lang/crystal/releases/tag/0.34.0) which has a lot of valuable information.

## Language changes

### Exhaustive Case

From now on a `case` expression will no longer have an implicit `else nil`. This is useful to enable an exhaustive check across the `when` branches within the `case`. If you are doing `case exp` over a union or an enum value, and you are missing a `when` to cover some type or value, the compiler will let you know. Unless you have an `else` at the end of the `case`.

Note: In this version, when the `case` does not cover all the possibilities, a warning is generated, and the `else nil` is implicitly added. In the next version it will produce a compile-time error and the implicit `else nil` will be gone.

The following snippet complains about the missing `when Char`

```crystal
a = 1 || 'x' || "foo"
case a
when Int32
  # ...
when String
  # ...
end
```

And the following snippet complains about the missing `when West`

```crystal
enum Direction
  North; South; East; West
end

d = Direction::North
case d
when .north?, .south?
  # ...
when .east?
  # ...
end
```

The only case that will still have an implicit `else nil` is when there is no expression and only a list of `when` statements. This construction is equivalent to multiple `if`/`elseif` where there is an implicit `else nil` also.

```crystal
x = 1
y = 2
case
when x.even?  # if x.even?
  # ...
when y >= 10  # elsif y >= 0
  # ...
end           # end
```

Read more at [#8424](https://github.com/crystal-lang/crystal/pull/8424).

### Procs subtyping

While dealing with `Procs` and callbacks it is common to not use the return value. In Crystal, that usually means returning `nil`. In regular methods you can specify the return type `: Nil` to ignore the value of the last expression.

The counterpart in `Procs` is harder because there usually is no type annotation for the return type.

For ease of use, we make it that any `Proc(T)` should be able to be used as a `Proc(Nil)`. That is, ignoring the return value in runtime. So, for those that like formality, `Proc(T) < Proc(Nil)` is a valid subtyping rule now.

There was a previous attempt to achieve something similar, but in this version, a better handling of that affair was implemented. Read more at [#8970](https://github.com/crystal-lang/crystal/pull/8970).

## Compiler

The `disable_overflow` compiler flag is dropped. This means that the usual arithmetic operators will always have the overflow check. Use `&+` and others to skip overflow checks. Read more at [#8772](https://github.com/crystal-lang/crystal/pull/8772).

The `CRYSTAL_OPTS` environment variable can now be used to inject compiler options and flags implicitly. This is useful, for example, when the compiler is used in `post_install` steps of shards and you want to enforce `--error-on-warnings`. Read more at [#8900](https://github.com/crystal-lang/crystal/pull/8900).

LLVM 10 has just been released and we added support for it. Read more at [#8940](https://github.com/crystal-lang/crystal/pull/8940).

The codegen for Windows has been improved to work without `--single-module`. Read more at [#8978](https://github.com/crystal-lang/crystal/pull/8978).

## Shards

A new version of Shards (0.10.0) has been released. Until now you probably have been using Shards 0.8.1 which lacks some features. Shards 0.9.0 polished many use cases, but it uses a SAT solver, which doesn’t scale. For Shards 0.10.0 we created [crystal-molinillo](https://github.com/crystal-lang/crystal-molinillo) a port of the dependency resolution algorithm used by [Bundler](https://bundler.io/) and [CocoaPods](https://cocoapods.org/).

You can read the rest of the updates in the [release changelog](https://github.com/crystal-lang/shards/releases/tag/v0.10.0).

We will be eagerly waiting for feedback from you on Shards to polish it before 1.0.

## Standard library

### Errno no more

Having as much as possible portable code is part of the goal of the std-lib. One of the areas that were in need of polishing was how `Errno` and `WinError` were handled. The `Errno` and `WinError` exceptions are now gone, and were replaced by a new hierarchy of exceptions. Unfortunately, there is no easy way to make a smooth transition here with deprecation warnings. The `IO::Timeout` exception was renamed to `IO::TimeoutError` to match the new hierarchy:

* `Exception`
  * `RuntimeError`
  * `IO::Error`
    * `IO::TimeoutError` (inherits `IO::Error`)
    * `File::Error` (inherits `IO::Error`)
      * `File::NotFoundError`
      * `File::AccessDeniedError`
      * `File::AlreadyExistsError`
    * `Socket::Error` (inherits `IO::Error`)
      * `Socket::ConnectError`
      * `Socket::BindError`

So, you can now use these new types to catch specific errors instead of checking `Errno` values. We included the most used errors as classes. If there is no specific class, the base `File::Error` or `Socket::Error` will be raised with a meaningful description.

The `Errno` or `WinError` underlying value is still present if you need it, via the `SystemError` module included in this new hierarchy. But it is better if you avoid using it.

Read more at [#8885](https://github.com/crystal-lang/crystal/pull/8885).

### Log

The former `Logger` module is deprecated and will be removed soon. Its replacement is the `Log` module: it’s shorter, more flexible and convenient.

You can use the top-level `Log` constant to emit log entries, or you can declare one inside your module or class. This allows the entries to be emitted from a _source_.

Each source will be configured to send the entries to different _backends_ depending on the severity level. If you initialize the logging with `Log.setup_from_env` you will be able to filter the level and the sources using the `CRYSTAL_LOG_LEVEL` and `CRYSTAL_LOG_SOURCES` environment variables.

```crystal
# file app.cr
require "log"

Log.setup_from_env

class MyApp
  Log = ::Log.for(self)

  def run
	Log.debug { "the app is running" } # log from myapp source
  end
end

MyApp.new.run
Log.info { "finished" } # log from the top-level source
```

If you want to log see all the log entries of the app above, you will need to set both environment variables, since their default values are `CRYSTAL_LOG_LEVEL=INFO` `CRYSTAL_LOG_SOURCES=""` (only top-level).

```
$ CRYSTAL_LOG_LEVEL=DEBUG CRYSTAL_LOG_SOURCES="*" ./app
D, [2020-03-30T21:54:50.079554000Z #26206]   DEBUG -- app:my_app: the app is running
I, [2020-03-30T21:54:50.079624000Z #26206]    INFO -- app:: finished
```

Read more at [#8847](https://github.com/crystal-lang/crystal/pull/8847) and check [the docs](https://crystal-lang.org/api/0.34.0/Log.html) for how you can define your own backends and use more advanced features of this module.

### Top level cleanup

As we prepare for 1.0, we wanted to iterate and clean up some of the top-level of the std-lib and prelude. That is the reason behind many deprecations that involved part of `Colorize` in [#8892](https://github.com/crystal-lang/crystal/pull/8892), `Iconv` in [#8890](https://github.com/crystal-lang/crystal/pull/8890), `DL` [#8882](https://github.com/crystal-lang/crystal/pull/8882).

Some modules were moved out of the top-level: `Adler32` and `CRC32` are inside `Digest` [#8881](https://github.com/crystal-lang/crystal/pull/8881), and `AtExitHandlers` inside `Crystal` [#8883](https://github.com/crystal-lang/crystal/pull/8883).

There might be some more cleanups/renames before 1.0 to avoid wanting some trivial early breaking-changes.

### Collections

On the performance corner of this release, when using `Array#fill` for writing all zero values, it will now use `memset` for the entire underlying buffer, instead of iterating every position. Read more at [#8903](https://github.com/crystal-lang/crystal/pull/8903).

### Serialization

There is a small breaking change in `YAML` in order to align the API of all builders. `YAML::Builder.new` with block was renamed to `YAML::Builder.build` in [#8896](https://github.com/crystal-lang/crystal/pull/8896).

When using the different format builders, `IO#flush` will be called to ensure all the content will get through in case you are not closing properly the destination file. This applies to `CSV`, `INI`, `JSON`, `XML`, and `YAML` builders. Read more at [#8876](https://github.com/crystal-lang/crystal/pull/8876).

### Time

It’s time for more breaking-changes in favor of less error-prone code. The `Time::Span` initialization API will use mandatory named arguments, like `Time::Span.new minutes: 2, seconds: 3`. Read more at [#8257](https://github.com/crystal-lang/crystal/pull/8257).

### Files

When closing a `File` or `Socket` the internal `fd` is set to `-1` to force an invalid file descriptor and avoid mixing `fd` from different `IO`s. In single-thread, this was never an issue, but on multi-thread, as usual, issues like this one can cause big headaches. Read more at [#8873](https://github.com/crystal-lang/crystal/pull/8873).

The `IO::Buffered#flush_on_newline` is back. And its default value will be helpful for building CLI tools and pipe them into other commands. Read more at [#8935](https://github.com/crystal-lang/crystal/pull/8935).

### HTTP

The WebSocket support was lacking the proper handling of close code. In order to implement them, a breaking-change on the server-side and in client-side parts was needed. Read more at [#8975](https://github.com/crystal-lang/crystal/pull/8975) and [#8981](https://github.com/crystal-lang/crystal/pull/8981).

### Windows

The windows support is moving forward while enabling more specs, and more contributors are jumping into the adventure. Check out [#8683](https://github.com/crystal-lang/crystal/pull/8683) and [#8822](https://github.com/crystal-lang/crystal/pull/8822), [#8885](https://github.com/crystal-lang/crystal/pull/8885), [#8958](https://github.com/crystal-lang/crystal/pull/8958).

## Tools

The `crystal init` tool got some polishing. The name of the shard is validated with respect [shards spec](https://github.com/crystal-lang/shards/blob/master/SPEC.md#name) and it can be inferred from the directory. Read more at [#8737](https://github.com/crystal-lang/crystal/pull/8737).

The `crystal docs` tool will now show warnings. In previous releases we switched to `:ditto:` and `:nodoc:` as magic comments. But we missed showing you the warnings in case you forget to add the colons. Read more at [#8880](https://github.com/crystal-lang/crystal/pull/8880).


## Next steps

Please update your Crystal and report any issues. We will keep moving forward and start the development focusing on 0.35. There won’t be many more 0.x releases. We are getting super close to 1.0!.

Again, we will be eagerly waiting for feedback from you on Shards to polish it before 1.0.

All deprecation warnings will soon be gone, and there will be errors in the next release. We want a clean 1.0.

> **THANKS:**
> We have been able to do all of this thanks to the continued support of [84codes](https://www.84codes.com/), [Nikola Motor Company](https://nikolamotor.com/) and every other [sponsor](/sponsors). It is extremely important for us to sustain the support through donations, so that we can maintain this development pace. [OpenCollective](https://opencollective.com/crystal-lang) and ~~[Bountysource](https://salt.bountysource.com/teams/crystal-lang)~~ are two available channels for that.
>
> Reach out to [crystal@manas.tech](mailto:crystal@manas.tech) if you’d like to become a direct sponsor or find other ways to support Crystal. We thank you in advance!
