Crystal 1.19.0 is released!
We are announcing a new Crystal release 1.19.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
Section titled StatsThis release includes 237 changes since 1.18.2 by 24 contributors. We thank all the contributors for all the effort put into improving the language! ❤️
Changes
Section titled ChangesBelow we list the most remarkable changes in the language, compiler and stdlib. For more details, visit the full changelog.
We do not expect any breaking changes in existing code. If you notice any unexpected issues, please let us know in the issue tracker or forum.
Breaking
Section titled BreakingThe following changes break prior behavior of the compiler, but we expect them to not have much effect in existing code. If you notice any unexpected issues, please let us know in the issue tracker or forum.
Compiler flags now have values
Section titled Compiler flags now have valuesThe flag? macro is now aware of name-value mappings in the form of
name=value where flag?(:name) will now return the respective value as a
StringLiteral (#16310). A key without a value returns true as implicit
value, as before.
Instead of returning a BoolLiteral the flag? macro might now return a
StringLiteral which might be unexpected. The value is still truthy and
shouldn’t cause issues in practice.
For example, the value printed by `` may now be:
- (not defined) =>
false -Dname=>true-Dname=value=>"value"-Dname=some,other,data=>"some,other,data"
Thanks, @straight-shoota
Adjust monotonic clocks
Section titled Adjust monotonic clocksThe monotonic clock has been adjusted on Linux and macOS to include suspended time, when they previously counted the system uptime.
UNIX targets still use CLOCK_MONOTONIC except for Linux that now uses
CLOCK_BOOTTIME (#16516) and macOS that now uses CLOCK_MONOTONIC_RAW
instead of mach_absolute_time that internally used CLOCK_UPTIME_RAW
(#16516, #16492).
The change is affecting Time.measure for example, that should now include
suspended time across the different targets, rather than sometimes including
it, and sometimes not.
Execution contexts
Section titled Execution contextsExecution contexts from RFC 0002 continue as a final preview feature with
opt-in with compiler flags -Dpreview_mt -Dexecution_context and we plan to
finally enable the feature by default in the 1.20 release!
There has not been huge developments to the feature, but corrections to fix the remaining thread safety issues in the standard library, for example:
- Add thread safety to default random (#16174)
- Closing system fd is thread unsafe (#16289)
- Thread safety of
Exception::Callstack(#16504)
We started to merge synchronization primitives from ysbaddaden/sync
into the standard library as well:
- Add
Sync::MutexandSync::RWLock(#16399) - Add
Sync::ConditionVariable(#16440) - Add
Sync::ExclusiveandSync::Shared(#16487)
This effort is part of the ongoing project to improve multi-threading support with the help of 84codes.
Thanks, @ysbaddaden
Time
Section titled TimeIntroduces the Time::Instant type to represent instants on the monotonic
timeline as defined in RFC 0015 instead of overloading the Time::Span type
that represents a duration, not an instant (#16490). We expect a clearer and
safer API:
Time::Instantrepresents a single point on the monotonic timeline.Time::Spancontinues to represent a duration.- Subtracting two
Time::Instantinstances yields aTime::Span. - Adding/subtracting a
Time::Spanto/from anTime::Instantyields a newTime::Instant.
We also adjusted the monotonic clock (#16516), applied the changes (#16498)
and deprecated Time.monotonic (#16545).
For example:
timeout = 5.seconds
start = Time.instant
while start.elapsed < timeout
# do something
end
In order to migrate existing code to Time::Instant, replace calls to Time.monotonic with Time.instant. If the instant time reading is stored in an explicitly typed variable (e.g. an instance variable), change the type from Time::Span to Time::Instant. The APIs of these types are very similar so most use cases should not need any further adaptions.
Finally, we made some further adjustments:
- Treat GMT as a legacy alias of UTC (#16292)
- Add
/etc/zoneinfoto zoneinfo lookup paths (#16463) - Add support for
$TZDIR(#16466)
Thanks, @straight-shoota
Process
Section titled ProcessA long refactor of spawning sub-processes has started. It encompasses a tedious
cleanup and safety fixes related to finding the command as well as building the
arguments and environment variables, to eventually move on from the classic
fork then exec to the more modern posix_spawn on UNIX targets.
- Create
argvbeforefork(#16286, #16321) - Move
make_envpbeforefork(#16351) - Use
execvpewhen available (#16294, #16311) - Replace
Dir.cdwith a non-raising alternative in pre-exec (#16352, #16369) - Fix reset directory if
Process.execfails (#16383) - Disable process cancellation during
fork(#16446)
Thanks, @straight-shoota
Standard library
Section titled Standard libraryNew methods:
- Add
NamedTuple#reverse_merge(#16229) - Add
Set#map!(#16271) - Add
Hash#transform_keys!(#16280) - Add
OpenSSL::SSL::Context::Server#on_server_namefor SNI (#16452, #16525) - Add
IPSocket#ipv6_only(#16347) - Add
Int.from_digitsas inverse ofInt#digits(#16237) - Add
BigInt.from_digits(#16259) - Add
Int#tdivmod(#16258) - Add
Random.next_boolandRandom.next_int(#16297) - Add
Random#splitandRandom.splitfor splittable PRNGs (#16342, #16495) - Add
Pointer#fill(#16338) - Add
Process.debugger_present?for Windows and Linux (#16248) - Add
Path#relative?(#16473) - Add
YAML::Nodes.parse_all(#16247) - Add
::exit(Process::Status)(#16436)
Enhancements:
- Support large JSON files (#16211)
- Support deserialization of YAML anchors of value types (#16186)
- Add end locations to scalars and aliases in
YAML::Nodes.parse(#16187) - Set
JSON::SerializableError#attributewhen appropriate (#16158) - Add
remove_emptyparameter toString#each_line(#16232) - Add
weeksparameter toTime::Span.new(#16208) - Support 0X, 0O, 0B prefixes in string to integer conversion (#16226)
Thanks, @andrykonchin, @carlhoerberg, @HertzDevil, @ysbaddaden, @straight-shoota, @RX14, @Sija, @spuun
The memory management model for libxml2 changed in Crystal 1.17 to become manual instead of integrating the GC. The change introduced some memory leaks that have now been fixed.
- Memory leak in
XML.parseandXML.parse_htmlmethods (#16414) - Memory leak in
XML::Document#finalize(#16418) - Memory leak in
XML::Node#content=(#16419) - Fix use after unlink in
XML::Node(#16432)
Thanks, @toddsundsted
Macros
Section titled MacrosNew methods:
StringLiteral#gsub(&)(#16376)StringLiteral#split(RegexLiteral)(#16378)StringLiteral#match(#16464)
Thanks, @Blacksmoke16, @HertzDevil
- All overloads of
ArrayLiteral#[]returnnilon out of bounds (#16453)
Thanks, @HertzDevil
Compiler
Section titled CompilerThe compiler is now always built with execution contexts, and the LLVM codegen is now always multithreaded for every target, including Windows. We can finally wave goodbye to fork, and Windows should see a performance boost.
Tools:
Thanks [@nobodywasishere], @straight-shoota
Infra
Section titled InfraWe finally build Linux ARM64 binaries of Crystal releases and nightlies. Tarballs are ready to download from github releases, docker images, snapcraft or the install-crystal github action.
- Build linux aarch64 tarballs (#16330)
- Build snap arm64 target (#16491)
- Enable multiarch docker builds (#16493)
- Encourage +1 reactions on issues and PRs for prioritization (#16241)
Thanks @straight-shoota, @ysbaddaden
Dependencies
Section titled DependenciesThe OpenSSL bindings now require OpenSSL 1.1.1+ or LibreSSL 3+. We expect the change to not have any effect since these versions are no longer distributed by any supported operating system.
Thanks @ysbaddaden
Deprecations
Section titled Deprecations- Deprecate single-letter macro fresh variables with indices (#16267)
- Deprecate macro fresh variables with constant names (#16293)
- Deprecate
StringLiteral#split(ASTNode)(#16439) - Deprecate
Time.monotonic(#16545) - Deprecate
Time#inspect(io, *, with_nanoseconds)(#16416)
Thanks @HertzDevil, @straight-shoota
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