---
title: Crystal 0.20.0 released!
version: 0.20.0
summary: :-)
thumbnail: +
author: asterite
---

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

Aside from the usual bugfixes and some performance improvements there's
a lot of new stuff here.

## Shards 0.7.0

Crystal 0.20.0 comes with [version 0.7.0 of shards](https://github.com/crystal-lang/shards/releases/tag/v0.7.0),
mostly maintained by [Julien Portalier](https://github.com/ysbaddaden),
whichs has a few new goodies like a `build` command and informational
`crystal` (version) and `libraries` entries in the `shard.yml` file.
Support for GitLab dependencies was also added.

## Line and file number information in backtraces

[Julien Portalier](https://github.com/ysbaddaden) also added
[line and file number information to exception backtraces](https://github.com/crystal-lang/crystal/pull/3303)
when programs are compiled with `-d` or `--debug`.
For example:

```ruby
# example.cr

def foo
  bar
end

def bar
  raise "OH NO!"
end

foo
```

Compiling and running:

<pre class="code">
$ crystal build example.cr -d
$ dsymutil --flat example # only needed on Mac OSX
$ ./example
OH NO! (Exception)
0x434f00: *bar:NoReturn at /opt/crystal/example.cr 8:3
0x434ee6: ??? at /opt/crystal/example.cr 4:3
0x431273: ??? at /opt/crystal/example.cr 11:1
0x434da9: main at /root/.cache/crystal/macro93695696.cr 12:15
0x7f9c98798f45: __libc_start_main at ??
0x430c29: ??? at ??
0x0: ??? at ??
</pre>

File, line and column numbers appear on the right side. There's still some
things to improve here, but this is definitely and improvement and now
it's so much easier to trace an exception back to the source code.

## ARM and AArch64 support

[Julien Portalier](https://github.com/ysbaddaden) is also the one who
[added](https://github.com/crystal-lang/crystal/pull/3424)
support for these platforms.

## LLVM 3.9 support

By... guess who? [Julien Portalier](https://github.com/ysbaddaden) once again!
If we had something like "Crystal Awards", well, now we know who would get
the first place prize, right? ;-)

## HTTP client and server streaming

Before 0.20.0 an `HTTP::Server` handler would receive a request with its
entire body already loaded in memory. This wasn't optimal, as maybe the
body is needed, or it needs to be streamed. 0.20.0 introduces this (breaking)
change. So, for example, one can stream a request directly into a JSON-mapped
object, thus avoiding many intermediate memory allocations. For example:

```ruby
require "http/server"
require "json"

class Point
  JSON.mapping x: Float64, y: Float64
end

# Accepts a JSON object representing a point and
# returns its absolute value (distance)
server = HTTP::Server.new(4567) do |context|
  request, response = context.request, context.response
  body = request.body
  if body
    point = Point.from_json(body)
    abs = Math.sqrt(point.x ** 2 + point.y ** 2)
    response.content_type = "application/json"
    {abs: abs}.to_json(response)
  else
    response.status_code = 400 # bad request
    response.content_type = "text/plain"
    response.puts "Missing body"
  end
end
puts "Listening on port 4567"
server.listen
```

And then:

<pre class="code">
$ curl localhost:4567 -XPOST --data '{"x": 3, "y": 4}'
{"abs":5.0}
</pre>

Also, an `IO` can be passed into an `HTTP::Client` when perfoming a POST or PUT,
so you can now upload a file very easily:

```ruby
require "http/client"

response = File.open("some_file.txt") do |file|
  HTTP::Client.post("http://example.com", body: file)
end
```

## Unicode aware methods for String and Char

Methods like `String#downcase` and `String#upcase` are now unicode aware.

Where previously a program behaved like this:

```ruby
"RubyConf 2016 at São Paulo was awesome!".upcase
  # => "RUBYCONF 2016 AT SãO PAULO WAS AWESOME!"
```

(notice the small 'ã')

Now it behaves correctly:

```ruby
"RubyConf 2016 at São Paulo was awesome!".upcase
  # => "RUBYCONF 2016 AT SÃO PAULO WAS AWESOME!"
```

This of course works for any language, and even some complex ligatures are
handled:

```ruby
"ЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЁЯЧСМИТЬБЮ".downcase
  # => "йцукенгшщзхъфывапролджэёячсмитьбю"
"baﬄe".upcase # => "BAFFLE"
```

(The last example has 'ﬄ', which is a single character, but expands to
three when upcased)

And even turkic is supported, where uppercase "i" is "İ" (an "I" with a dot):

```ruby
"aeıiou".upcase(Unicode::CaseOptions::Turkic)
  # => "AEIİOU"
```

## Random enhancements

These are not random enhancements, but rather enhancements to the
[Random module](https://crystal-lang.org/api/0.20.0/Random.html).
Specifically, the ability to [generate random integers of any type
and any range](https://github.com/crystal-lang/crystal/pull/3402),
without overflow issues.

```ruby
rand(Int64::MIN..Int64::MAX) # => 4544345849288905241
```

Thank you
[Oleh Prypin](https://github.com/BlaXpirit) for another
excellent contribution!

## Optimized Array#sort

[Tatsujin Chin](https://github.com/c910335) sent a PR that
replaces the old quicksort implementation with an
[introsort](https://en.wikipedia.org/wiki/Introsort) one.
The end result is that this is now not only faster than the
old implementation, but also
[faster than implementations in other languages](https://gist.github.com/firejox/4d300495811c1dda65fefc1b76fc57b6),
like c's `qsort` and c++'s `std::sort`. Super thank you,
Tatsujin Chin!

## API docs have a nicer style

The style improvements include font changes and layout fixes.
[Take a look!](https://crystal-lang.org/api)

Special handling of common comments like TODO, OPTIMIZE and DEPRECATED
was also added, and is now shown highlighted. Thank you
[Sam Eaton](https://github.com/samueleaton)!

## And more...

Make sure to read the [full changelog](https://github.com/crystal-lang/crystal/releases/tag/0.20.0)
for all the details, and upgrade instruccions due to some breaking changes.

> **THANKS:**
> We'd also like to thank everyone else that made this release possible
> with their contributions, reviews and suggestions.
