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

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

This release comes with bug fixes, stability of the std-lib & runtime, some awaited language features and lots of cleanup.

There are [117 commits since 0.32.1](https://github.com/crystal-lang/crystal/compare/0.32.1...0.33.0) by 29 contributors.

Let’s review some 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.33.0) which has a lot of valuable information.

## Language changes

The new `select/timeout` language construct allows you to perform a blocking channel operation but timeout after a specific amount of time. It was previously possible to do manually, but it required some boilerplate and a dedicated fiber. This is now possible while taking advantage of libevent directly.

```crystal
select
when x = ch.receive
  puts "got #{x}"
when timeout(1.second)
  puts "timeout"
end
```

`timeout` is not a top-level method and is expected to be used only in a blocking `select` `when` condition (ie: without an `else`). Read more about `timeout` in select statements in [#8506](https://github.com/crystal-lang/crystal/pull/8506).

### Macros

In the built-in macros the `TypeNode#name` got extended with a new overload that allows you to pick whether you want (or not) the generic arguments when getting the type’s name (default is to include them). Read more at [#8483](https://github.com/crystal-lang/crystal/pull/8483).

```crystal
class Foo(T); end

module Bar::Baz; end

{% raw %}{{Bar::Baz.name}}{% endraw %}                 # => Bar::Baz
{% raw %}{{Foo.name}}{% endraw %}                      # => Foo(T)
{% raw %}{{Foo.name(generic_args: false)}}{% endraw %} # => Foo
```

## Compiler

There were some memory corruption bugs because we used `memset` and `memcpy` 32-bits primitives in 64-bits machines. They are now fixed in [#8746](https://github.com/crystal-lang/crystal/pull/8746).

Now, the default `CRYSTAL_PATH` gives precedence to `./lib` over embedded std-lib so your shards can override some std-lib modules if needed. Read more at [#8752](https://github.com/crystal-lang/crystal/pull/8752).

We did some clean-ups and completely dropped the support for previously deprecated comma separators in enums. Read more at [#8657](https://github.com/crystal-lang/crystal/pull/8657).

## Standard library

We took the time to do some clean-ups regarding various previously deprecated methods and modules. Some of them deprecated almost over a year ago. `PartialComparable`, `Crypto::Bcrypt::Password#==`, `HTTP::Server::Response#respond_with_error`, `JSON::PullParser::Kind#==`, `Symbol#==(JSON::PullParser::Kind)`, `JSON::Token#type`, `String#at`, `Time.new`, `Time.now`, `Time.utc_now`, `URI.escape`, `URI.unescape` are really no longer available. Read more at [#8646](https://github.com/crystal-lang/crystal/pull/8646), [#8596](https://github.com/crystal-lang/crystal/pull/8596).

There are also some additions. `Object#in?(collection)` is analogous to `Enumerable#includes?(obj)` but with the receiver and argument swapped.

```crystal
42.in?(0..100)         # => true
4242.in?(0..100)       # => false
:baz.in?(:foo, :bar)   # => false
:bar.in?({:foo, :baz}) # => false
:foo.in?([:foo, :bar]) # => true
```

Read more at [#8720](https://github.com/crystal-lang/crystal/pull/8720) and check many of the usages in the current std-lib at [#8723](https://github.com/crystal-lang/crystal/pull/8723).

### Serialization

The JSON deserialization improved to work better with some union types in [#8689](https://github.com/crystal-lang/crystal/pull/8689) and the `JSON::PullParser` deals properly with overflows in [#8698](https://github.com/crystal-lang/crystal/pull/8698).

The `dig?` methods for `JSON::Any` and `YAML::Any` got fixed to avoid raising on non-structure values. Read more at [#8745](https://github.com/crystal-lang/crystal/pull/8745).

### Files

How File, User and Group interact with each other keeps evolving to find a sweet spot. `File::Info#owner`, and `File::Info#group` are deprecated in favor of `#owner_id`, and `#group_id`. Read more at [#8007](https://github.com/crystal-lang/crystal/pull/8007).

### Networking

The handling of `IO` got more robust to deal with some race conditions in multi-thread and avoid using invalid file descriptors in libevent after fork. Read more at [#8707](https://github.com/crystal-lang/crystal/pull/8707) and [#8733](https://github.com/crystal-lang/crystal/pull/8733).

`OpenSSL::SSL::Socket` was improved to deal with some misbehaving parties out in the wild.  Read more at [#8540](https://github.com/crystal-lang/crystal/pull/8540).

### Concurrency

Sometimes in generic types, using `Nil` might cause some glitches. Like in `Array(Nil)`, how would you distinguish if `#[]?` returns the stored `nil` or the out-of-bounds value. Even though sometimes it is still useful to use `Nil` as a type argument like in `Channel(Nil)`. `Future(Nil)` should now be working without surprises. Read more at [#8650](https://github.com/crystal-lang/crystal/pull/8650).

We’ve been paying attention to sporadic failures on the CI multi-thread jobs. Sometimes the specs need to be iterated since they were written with a different single-thread mindset. Read more at [#8592](https://github.com/crystal-lang/crystal/pull/8592), [#8643](https://github.com/crystal-lang/crystal/pull/8643), and [#8724](https://github.com/crystal-lang/crystal/pull/8724).

### Runtime

`IO::FileDescriptor.from_stdio` now returns an `IO` with blocking mode depending on the type of the file descriptor used for STDIN, STDOUT and STDERR. Read more at [#8787](https://github.com/crystal-lang/crystal/pull/8787).

Some changes in the runtime should improve the error reporting and exception handling.
Read more at [#8728](https://github.com/crystal-lang/crystal/pull/8728), [#8499](https://github.com/crystal-lang/crystal/pull/8499), [#8743](https://github.com/crystal-lang/crystal/pull/8743).

Another addition that will reduce some paper cuts is a new top-level exception handler reporting. Read more at [#8735](https://github.com/crystal-lang/crystal/pull/8735), [#8791](https://github.com/crystal-lang/crystal/pull/8791).

Sometimes `puts` and `dprintf` are used to print to STDOUT or STDERR. But the latter is not portable. `Crystal::System.print_error` was extended to handle `printf`-like format. So it should be used instead of `dprintf` usually. Read more at [#8786](https://github.com/crystal-lang/crystal/pull/8786).

### Spec

Usually using specs the `Spec::DotFormatter` shows… dots! The `Spec::JUnitFormatter` is another option that is a good fit for richer reporting. It's got improved with lots of information in [#8599](https://github.com/crystal-lang/crystal/pull/8599).

As a bonus point this reporting was integrated in our CircleCI jobs so we can get some concise reports of failures, slow test and other statistics in the test summary.  Read more at [#8617](https://github.com/crystal-lang/crystal/pull/8617).

### Doc generator

We finally settled to use `:ditto:` and `:nodoc:` for the doc generator. So you should always put the `:` around those words when documenting your code. Read more at [#6362](https://github.com/crystal-lang/crystal/pull/6362).

## Platforms

Regarding Windows support there was some movement. A Windows CI using GitHub Actions was added in [#8676](https://github.com/crystal-lang/crystal/pull/8676) to help us move forward and not backwards. The `system` module in prelude was enabled in [#8661](https://github.com/crystal-lang/crystal/pull/8661). More specs got fixed to work in [#8670](https://github.com/crystal-lang/crystal/pull/8670). And a helper script to identify working std-lib specs was added in [#8664](https://github.com/crystal-lang/crystal/pull/8664).

Regarding Alpine we are now also running it in the CI in [#7420](https://github.com/crystal-lang/crystal/pull/7420) and you might [have read](/2020/02/02/alpine-based-docker-images/) about the Alpine Docker images we are now building since [#8708](https://github.com/crystal-lang/crystal/pull/8708).

We started to use `lld` instead of `ld` in Linux builds since it seems we were hitting some `ld` limitations. In case you experience them you might also want to move to `lld`. If it is available the `Makefile` will take care to use it. Read more at [#8641](https://github.com/crystal-lang/crystal/pull/8641).

## Next steps

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

It will also be helpful if your shards are tested 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.

The upcoming 0.34 is likely to include an updated shards, so using nightly would help us to collect feedback from it.

> **THANKS:**
> We have been able to do all of this thanks to the continued support of [84codes](https://www.84codes.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!
