Skip to content
GitHub Repository Forum RSS-Newsfeed

Crystal 1.16.0 is released!

Johannes Müller

We are announcing a new Crystal release 1.16.0 with several new features and bug fixes.

Pre-built packages are available on GitHub Releases and our official distribution channels. See crystal-lang.org/install for installation instructions.

Stats

This release includes 162 changes since 1.15.1 by 19 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. For more details, visit the full changelog.

Breaking

The following changes break prior behavior of the compiler, but we expect them to not break much in existing code. If this is not the case, please let us know in the issue tracker or forum.

Fixed implementation of File.match?

The implementation of File.match? was insufficient and has been replaced by a new algorithm. This change should not affect any behaviour that was previously working as documented.

The correction of implementation bugs leads to the following changes in observed behaviour:

  • Wildcard and globstar are able to match non-greedily. For example, **/a now matches a.
  • Globstar matches full path segments only, otherwise it’s just two wildcards (which is equivalent to a single one). For example, a** no longer matches ab/c (but it matches ab).
  • Subpatterns in branches are parsed with respect to their respective syntactical context. For example, {[}]} now matches }. It parses as a branch with one subpattern that describes the character set }. Previously, this was a parse error.
  • Escapes for special character are recognized. For example, \\t now matches \t while previously it matched t.
  • The grammar for parsing character classes is more flexible. For example, [a-], now matches a and -. Previously, it was a pattern error (incomplete character range).

Note: Dir.glob is implemented differently and is not affected by that invalid behaviour. There were no changes to it.

Thanks, @straight-shoota

Parameter name suffixes are deprecated

The suffixes ? and ! for parameter names of defs, macros and blocks are deprecated. This aligns them with other variable names. They produce a warning now (#12197).

Thanks, @potomak

Implicit return type of Enumerable#sum and #product

Enumerable#sum and #product no longer resolve an implicit return type when the element type is a union. This can’t work reliably. Instead, you need to specify the sum/product type explicitly by the initial parameter with a value of the intended return type (#15314). In effect, this moves a runtime error condition to a compile time error.

# Crystal 1.16.0
[1, 10000000000_u64].sum # Error: `Enumerable#sum` and `#product` do not support Union types.
                         # Instead, use `Enumerable#sum(initial)` and `#product(initial)`,
                         # respectively, with an initial value of the intended type of the call.

# Crystal < 1.16.0
[1, 10000000000_u64].sum # OverflowError: Arithmetic overflow

# Passing an explicit initial value works, before and after:
[1, 10000000000_u64].sum(0_u64) # => 10000000001_u64

Thanks, @rvprasad

Resource string in HTTP::Request

HTTP::Request was fixed to correctly parse HTTP resource strings that look like an absolute URL. This may break code that relied on the previous, buggy behaviour (#15499).

# Crystal 1.16.0
HTTP::Request.new("GET", "http://example.com/foo").path # => "http://example.com/foo"

# Crystal < 1.16.0
HTTP::Request.new("GET", "http://example.com/foo").path # => "/foo"

Thanks, @straight-shoota

Environment changes for subcommands

The compiler won’t set the environment variable $CRYSTAL when running a process for a subcommand. This variable was only in introduced in #14953 in 1.14.0. We addded a more flexible alternative $CRYSTAL_EXEC_PATH, and the equivalent to $CRYSTAL is now $CRYSTAL_EXEC_PATH/crystal. The compiler also prepends its path to $PATH (#15186).

Thanks, @straight-shoota

Execution Contexts

Execution contexts from RFC 0002 are available as a preview feature. It has already proven to be quite robust, but there might be some rough edges.

You can test execution contexts with the compiler flags -Dpreview_mt -Dexecution_context. The default context is single threaded (unlike standalone -Dpreview_mt). But you can then start additional contexts as you need (for example, a Fiber::ExecutionContext::MultiThreaded or Fiber::ExecutionContext::Isolated).

mt_context = Fiber::ExecutionContext::MultiThreaded.new("worker-threads", 4)

10.times do
  mt_context.spawn do
    do_something
  end
end

gtk = Fiber::ExecutionContext::Isolated.new("Gtk") do
  Gtk.main
end
gtk.wait

Execution contexts are supported on most targets, including, Linux, macOS, Windows and the different BSDs, on X86 and ARM architectures. This addition marks the peak of the ongoing project to improve multi-threading support with the help of 84codes.

Language

Thanks, @HertzDevil

Thanks, @HertzDevil

Standard library

  • Several bug fixes and performance improvements to Path handling, especially for Windows paths.

Thanks, @HertzDevil

Thanks, @punteek

Thanks, @ysbaddaden

Compiler

  • The compiler CLI understand the long option --output everywhere, instead of just the short variant -o (#15519). It also accepts a directory name as value, in which case the file name is derived from the source filename (#15471).

Thanks, @HertzDevil, @straight-shoota

  • The compiler respects the environment variable $MACOSX_DEPLOYMENT_TARGET, which gets rid of annoying linker warnings when target versions are mismatched (#15603)

Thanks, @HertzDevil

Compiler tools

The doc generator can optionally include private and protected objects as well as objects in lib bindings (lib, fun, union, cstruct, external, and type), as proposed in RFC 0011. The :showdoc: directive enables that.

# :showdoc:
#
# Documentation for LibFoo
lib Foo
  # Documentation for function foo
  fun foo : Void
end

# :showdoc:
#
# Documentation for method bar
private def bar
end

Thanks @nobodywasishere

Dependency Updates

  • Support for LLVM 20 (#15412)

Thanks, @HertzDevil

Deprecations


Thanks

We have been able to do all of this thanks to the continued support of 84codes and every other sponsor. To maintain and increase the development pace, donations and sponsorships are essential. OpenCollective is available for that.

Reach out to crystal@manas.tech if you’d like to become a direct sponsor or find other ways to support Crystal. We thank you in advance!

Contribute

Discussions on the web

  • Crystal 1.16.0 () on HackerNews (102 points · 29 comments)