---
title: Crystal 1.11.0 is released!
version: 1.11.0
date: 2024-01-08
summary:
author: straight-shoota
comment_href: https://disqus.com/home/discussion/crystal-lang/crystal_1110_is_released/
---
We are announcing a new Crystal release with several new features and bug fixes.

Pre-built packages are available on [GitHub Releases](https://github.com/crystal-lang/crystal/releases/tag/1.11.0)
and our official distribution channels.
See [crystal-lang.org/install](https://crystal-lang.org/install/) for
installation instructions.

## Stats

This release includes [178 changes since 1.10.1](https://github.com/crystal-lang/crystal/pulls?q=is%3Apr+milestone%3A1.11.0)
by 28 contributors. We thank all the contributors for all the effort put into
improving the language! ❤️

## Changes

Below we list the most remarkable changes in the language, compiler and stdlib.
This is a pretty big release with lots of things going on, so hold tight 🚀

For details, visit the [full changelog](https://github.com/crystal-lang/crystal/releases/tag/1.11.0).

### LLVM 18

One of the biggest steps forward is support for upcoming LLVM 18 which allows linking LLVM dynamically on Windows ([#14101](https://github.com/crystal-lang/crystal/pull/14101)).
Additionally, LLVM 18 now provides everything we need in the upstream C API, removing the need for our wrapper extension `llvm_ext`. It's still necessary for older LLVM versions, so we'll keep it around for a while. But the future tool chain is getting simplified. Read more in [#13946](https://github.com/crystal-lang/crystal/issues/13946).

*Thanks [@HertzDevil](https://github.com/HertzDevil)*

### Compiler Optimization Levels

The compiler gains four distinct optimization levels:

* `-O0`: No optimization
* `-O1`: Low optimization
* `-O2`: Middle optimization
* `-O3`: High optimization

Each level activates the respective LLVM `RunPasses` and `CodeGenOptLevel` optimizations.

`-O3` corresponds to the existing release mode and `-O0` corresponds to the default non-release mode. `-O0` remains the default and `--release` is equivalent to `-O3 --single-module`.

Effectively, this introduces two optimization choices between the previous full or nothing. And it's now possible to use high optimization without `--single-module`.

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

*Thanks [@kostya](https://github.com/kostya)*

### Alignment primitives

The language has two new reflection primitives: [`alignof`](https://crystal-lang.org/reference/1.11/syntax_and_semantics/alignof.html) and [`instance_alignof`](https://crystal-lang.org/reference/1.11/syntax_and_semantics/instance_alignof.html) return a type's memory alignment ([#14087](https://github.com/crystal-lang/crystal/pull/14087)). This allows implementing type-aware allocators in native Crystal with properly aligned pointers.
They are siblings of `sizeof` and `instance_sizeof` and can be used in the same way.

```crystal
class Foo
  def initialize(@x : Int8, @y : Int64, @z : Int16)
  end
end

Foo.new(1, 2, 3)

instance_alignof(Foo) # => 8
```

> **NOTE:** Effect on existing code
> The introduction of these primitives makes it impossible to define methods of the same names. So `def alignof` or `def instance_alignof` are now invalid syntax.
> We don't expect there to be a big impact in practice.

*Thanks [@HertzDevil](https://github.com/HertzDevil)*

### `dll` parameter in `Link` annotation

The [`Link`](https://crystal-lang.org/api/1.11.0/Link.html) annotation has a new parameter `dll` for specifying dynamic link libraries on Windows ([#14131](https://github.com/crystal-lang/crystal/pull/14131)).

```crystal
@[Link(dll: "foo.dll")]
lib LibFoo
end
```

*Thanks [@HertzDevil](https://github.com/HertzDevil)*

### Macro `@caller` context

Macros now have a reference to their calling context via the special instance variable [`@caller`](https://crystal-lang.org/reference/1.11/syntax_and_semantics/macros/index.html#call-information) ([#14055](https://github.com/crystal-lang/crystal/issues/14055)).

```crystal
macro foo
{%- raw -%}
  {{- @caller.line_number }}
{% endraw %}
end

foo # => 5
```

*Thanks [@Blacksmoke16](https://github.com/Blacksmoke16)*

### New collection methods

[`Enumerable#present?`](https://crystal-lang.org/api/1.11.0/Enumerable.html#present?:Bool-instance-method) is a direct inversion of `#empty?` avoiding some quirks with the similar, but not-quite, `#any?` ([#13847](https://github.com/crystal-lang/crystal/issues/13847)).

*Thanks [@straight-shoota](https://github.com/straight-shoota)*

[`Enumerable#each_step`](https://crystal-lang.org/api/1.11.0/Enumerable.html#each_step(n:Int,*,offset:Int=0,&:T-%3E):Nil-instance-method) and [`Iterable#each_step`](https://crystal-lang.org/api/1.11.0/Iterable.html#each_step(n:Int)-instance-method) are direct methods for creating step iterators ([#13610](https://github.com/crystal-lang/crystal/pull/13610)).

*Thanks [@baseballlover723](https://github.com/baseballlover723)*

[`Enumerable(T)#to_set(& : T -> U) : Set(U) forall U`](https://crystal-lang.org/api/1.11.0/Enumerable.html#to_set(&block:T-%3EU):Set(U)forallU-instance-method) and [`#to_a(& : T -> U) forall U`](https://crystal-lang.org/api/1.11.0/Enumerable.html#to_a%28%26%3AT-%3EU%29%3AArray%28U%29forallU-instance-method) allow materialising an `Enumerable` into a pre-defined collection, which gives more flexibility than the standard `#to_set` and `#to_a` methods ([#12654](https://github.com/crystal-lang/crystal/pull/12654), [#12653](https://github.com/crystal-lang/crystal/pull/12653)).

*Thanks [@caspiano](https://github.com/caspiano)*

### Numeric enhancements

[`BigFloat#**`](https://crystal-lang.org/api/1.11.0/BigFloat.html#%2A%2A%28other%3ABigInt%29%3ABigFloat-instance-method) now works for all `Int::Primitive` arguments and supports the full exponent range for `BitInt` arguments ([#13971](https://github.com/crystal-lang/crystal/pull/13971), [#13881](https://github.com/crystal-lang/crystal/pull/13881))

Floating point to string conversion in `printf` uses the Ryu algorithm ([#8441](https://github.com/crystal-lang/crystal/issues/8441)).

New methods [`Float::Primitive.to_hexfloat`](https://crystal-lang.org/api/1.11.0/Float64.html#to_hexfloat:String-instance-method), [`.parse_hexfloat`](https://crystal-lang.org/api/1.11.0/Float64.html#parse_hexfloat(str:String):self-class-method), and [`.parse_hexfloat?`](https://crystal-lang.org/api/1.11.0/Float64.html#parse_hexfloat(str:String):self-class-method) allow conversion to and from the hexfloat format ([#14027](https://github.com/crystal-lang/crystal/pull/14027)).

More math features:

- [`Math.fma`](https://crystal-lang.org/api/1.11.0/Math.html#fma(value1,value2,value3)-instance-method) ([#13934](https://github.com/crystal-lang/crystal/pull/13934))
- [`Number#integer?`](https://crystal-lang.org/api/1.11.0/Number.html#integer?:Bool-instance-method) ([#13936](https://github.com/crystal-lang/crystal/pull/13936))
- [`Int32#abs_unsigned`](https://crystal-lang.org/api/1.11.0/Int32.html#abs_unsigned:UInt32-instance-method), [`#neg_signed`](https://crystal-lang.org/api/1.11.0/Int32.html#neg_signed:self-instance-method) ([#13938](https://github.com/crystal-lang/crystal/pull/13938))
- [`Int::Primitive#to_signed`](https://crystal-lang.org/api/1.11.0/Int32.html#to_signed:Int32-instance-method), [`#to_signed!`](https://crystal-lang.org/api/1.11.0/Int32.html#to_signed%21%3AInt32-instance-method), [`#to_unsigned`](https://crystal-lang.org/api/1.11.0/Int32.html#to_unsigned:UInt32-instance-method), [`#to_unsigned!`](https://crystal-lang.org/api/1.11.0/Int32.html#to_unsigned%21%3AUInt32-instance-method) ([#13960](https://github.com/crystal-lang/crystal/pull/13960))

*Thanks [@HertzDevil](https://github.com/HertzDevil)*

### Enhancements for `crystal spec`

`crystal spec` gets two new commands for introspection:

`crystal spec --dry-run` prints all active specs without actually executing any spec code ([#13804](https://github.com/crystal-lang/crystal/pull/13804)).

*Thanks [@nobodywasishere](https://github.com/nobodywasishere)*

`crystal spec --list-tags` lists all tags defined in the spec suite ([#13616](https://github.com/crystal-lang/crystal/pull/13616)).

*Thanks [@baseballlover723](https://github.com/baseballlover723)*

### Enhancements for `crystal tool unreachable`

The basic implementation of `crystal tool unreachable` from Crystal 1.10 gets some useful enhancements.

- The `--tallies` option prints all methods and the total number of calls. Those with a zero tally are unreachable ([#13969](https://github.com/crystal-lang/crystal/pull/13969)).
- The `--check` flag exits with a failure status if there is any unreachable code ([#13930](https://github.com/crystal-lang/crystal/pull/13930)).
- Annotations show up in the output ([#13927](https://github.com/crystal-lang/crystal/pull/13927)).
- New output format: CSV ([#13926](https://github.com/crystal-lang/crystal/pull/13926)).
- Paths in the output are relativized, making it more succinct ([#13929](https://github.com/crystal-lang/crystal/pull/13929)).

*Thanks [@straight-shoota](https://github.com/straight-shoota)*

### Inherited macros in API docs

Inherited macros are now exposed in the API docs. They had previously been hidden, in contrast to inherited defs ([#13810](https://github.com/crystal-lang/crystal/pull/13810)).

*Thanks [@Blacksmoke16](https://github.com/Blacksmoke16)*

### Text

- [`Regex::MatchData#to_s`](https://crystal-lang.org/api/1.11.0/Regex/MatchData.html#to_s:String-instance-method) returns the matched substring ([#14115](https://github.com/crystal-lang/crystal/pull/14115)).
    *Thanks [@Vendicated](https://github.com/Vendicated)*
- The new [`EOL`](https://crystal-lang.org/api/1.11.0/toplevel.html#EOL)constant (End-Of-Line) is a portable reference to the system-specific new line character sequence ([#11303](https://github.com/crystal-lang/crystal/pull/11303)). *Thanks [@postmodern](https://github.com/postmodern)*
- We got new version-specific constructors for [`UUID`](https://crystal-lang.org/api/1.11.0/UUID.html): [`.v1`](https://crystal-lang.org/api/1.11.0/UUID.html#v1%28%2A%2Cclock_seq%3AUInt16%7CNil%3Dnil%2Cnode_id%3AMAC%7CNil%3Dnil%29%3Aself-class-method), [`.v2`](https://crystal-lang.org/api/1.11.0/UUID.html#v2%28domain%3ADomain%2Cid%3AUInt32%2Cnode_id%3AMAC%7CNil%3Dnil%29%3Aself-class-method), [`.v3`](https://crystal-lang.org/api/1.11.0/UUID.html#v3%28name%3AString%2Cnamespace%3AUUID%29%3Aself-class-method), [`.v4`](https://crystal-lang.org/api/1.11.0/UUID.html#v4%28randomr%3ARandom%3DRandom%3A%3ASecure%29%3Aself-class-method), and [`.v5`](https://crystal-lang.org/api/1.11.0/UUID.html#v5%28name%3AString%2Cnamespace%3AUUID%29%3Aself-class-method) ([#13693](https://github.com/crystal-lang/crystal/pull/13693)).
    *Thanks [@threez](https://github.com/threez)*
- [`StringScanner`](https://crystal-lang.org/api/1.11.0/StringScanner.html) now supports `String` and `Char` patterns ([#13806](https://github.com/crystal-lang/crystal/pull/13806)).
    *Thanks [@funny-falcon](https://github.com/funny-falcon)*
- `Char::Reader` got some nilable character accessors: [`#current_char?`](https://crystal-lang.org/api/1.11.0/Char/Reader.html#current_char%3F%3AChar%7CNil-instance-method), [`#next_char?`](https://crystal-lang.org/api/1.11.0/Char/Reader.html#next_char%3F%3AChar%7CNil-instance-method), [`#previous_char?`](https://crystal-lang.org/api/1.11.0/Char/Reader.html#previous_char%3F%3AChar%7CNil-instance-method) ([#14012](https://github.com/crystal-lang/crystal/pull/14012)).
    *Thanks [@HertzDevil](https://github.com/HertzDevil)*
- [`String#matches_full?`](https://crystal-lang.org/api/1.11.0/String.html#matches_full?(regex:Regex):Bool-instance-method) is a simple API when you need a regular expression to match the entire string ([#13968](https://github.com/crystal-lang/crystal/pull/13968)).
    *Thanks [@straight-shoota](https://github.com/straight-shoota)*

### Misc

- The capacity of `String::Buffer` and `IO::Memory` was unintentionally limited to 1GB. They now support the full range up to `Int32::MAX`, i.e. 2GB ([#13989](https://github.com/crystal-lang/crystal/pull/13989)).
    *Thanks [@straight-shoota](https://github.com/straight-shoota)*
- There was a nasty bug in `Number#format` which could mess with the integral part. It is now fixed in [#14061](https://github.com/crystal-lang/crystal/pull/14061).
    *Thanks [@HertzDevil](https://github.com/HertzDevil)*
- Vendored shards `markd` and `reply` are no longer referenced by paths relative to the compiler source tree. This means they can be local dependencies (i.e. in `lib`) when using the compiler as a library ([#13992](https://github.com/crystal-lang/crystal/pull/13992)).
    *Thanks [@nobodywasishere](https://github.com/nobodywasishere)*
- There are two new constants which provide information on the compiler host and target: `Crystal::HOST_TRIPLE` and `TARGET_TRIPLE` ([#13823](https://github.com/crystal-lang/crystal/pull/13823)).
    *Thanks [@HertzDevil](https://github.com/HertzDevil)*

### Shards 0.17.4

The bundled shards release was updated to [0.17.4](https://github.com/crystal-lang/shards/releases/tag/v0.17.4) which brings a couple minor bugfixes. ([#14133](https://github.com/crystal-lang/crystal/pull/14133)).

*Thanks [@straight-shoota](https://github.com/straight-shoota)*

### Experimental: `ReferenceStorage` and `.pre_initialize`

We've started an effort to make it easier to use custom allocation mechanisms in Crystal and decouple allocation from initialization.
The main tool is [`Reference.pre_initialize`](https://crystal-lang.org/api/1.11.0/Reference.html#pre_initialize(address:Pointer)-class-method) which performs the rudimentary object initialization, before actually calling `#initialize`.

 [`Reference.unsafe_construct`](https://crystal-lang.org/api/1.11.0/Reference.html#unsafe_construct%28address%3APointer%2C%2Aargs%2C%2A%2Aopts%29%3Aself-class-method) is a higher level API on top of that.
[`ReferenceStorage`](https://crystal-lang.org/api/1.11.0/ReferenceStorage.html) represents a static buffer for a reference allocation.

These APIs are experimental and might be subject to change. We expect more features in this direction in future releases. Join the discussion about custom reference allocation at [#13481](https://github.com/crystal-lang/crystal/issues/13481).

> *NOTE:* `ReferenceStorage` was removed again in 1.11.1 due to compatibility issues with older versions of the standard library ([#14207]). It will come back with an improved implementation.

*Thanks [@HertzDevil](https://github.com/HertzDevil)*

[#14207]: https://github.com/crystal-lang/crystal/pull/14207

## Deprecations

- Splat operators in macro expressions are deprecated. Use `.splat` instead ([#13939](https://github.com/crystal-lang/crystal/pull/13939))
- `LLVM.start_multithreaded` and `.stop_multithreaded`. They have no effect ([#13949](https://github.com/crystal-lang/crystal/pull/13949))
- `LLVMExtSetCurrentDebugLocation` from `llvm_ext.cc` for LLVM 9+ ([#13965](https://github.com/crystal-lang/crystal/pull/13965))
- `Char::Reader#@end` ([#13920](https://github.com/crystal-lang/crystal/pull/13920))

> **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).
> To maintain and increase the development pace, donations and sponsorships are
> essential. [OpenCollective](https://opencollective.com/crystal-lang) is
> available 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!
