Racket v9.2 is here with breaking pattern checks and sounder types

Racket v9.2 ships today with several breaking changes that will catch bugs in existing code. The release, announced by Stephen De Gabrielle and John Clements, focuses on correctness improvements in pattern matching, Typed Racket, and internal infrastructure.

Breaking change: match now enforces non-linear pattern equality

The headline change is in the match form. When a pattern uses the same variable multiple times with ... (non-linear patterns), v9.2 now checks that the matched subsequences are equal. For example:

(match '(a b a b)
  [(list x ... x ...) 'dup]  ;; v9.2: checks that first and second halves are equal
  [_ 'no])
;; => 'dup

Previously, Racket would silently bind x to the first sequence and ignore the second. Now it raises a match failure if the two parts differ. Additionally, match rejects patterns where a variable is used both with and without .... This repair could cause existing code to fail at compile time.

Typed Racket: asin and acos now sound for complex results

Typed Racket's types for asin and acos previously allowed unsound results when the function produced a complex number. v9.2 corrects this, which may cause existing Typed Racket code to fail at compile time if it relied on the unsound behavior.

#lang typed/racket
(asin 2.0)  ;; v9.2: returns a Complex, previously returned Real incorrectly

Unicode 17.0 support

Character and string operations now use Unicode 17.0, the latest standard. This means better support for new emoji and scripts.

Internal FFI2 groundwork and #%foreign-inline

The release includes a new core syntactic form #%foreign-inline for unsafe access to linklet-layer facilities. This is part of the internal "ffi2" foreign interface, which will be packaged separately in the future. Any code that enumerates all core forms must be updated.

Other notable changes

  • terminal-file-position now counts bytes written to terminal ports (stdin, stderr).
  • Cross-phase persistent modules support more types of quoted data.
  • The implementations of member, memw, when, unless, let/ec, and cond were rewritten to use only racket/kernel syntax.
  • impersonator-property-predicate-procedure? identifies procedures created by make-impersonator-property.
  • Typed Racket polymorphic struct types print with type arguments (e.g., (Array Byte)) instead of internal representations.
  • The stepper's number display now respects language settings.
  • Scribble documents without the Racket-manual style get an initial-scale of 1.0 (configurable via initial-scale property).
  • Margin notes appear inline on narrow displays in all styles.
  • Big-bang programs distributed as .dmg files handle close-on-stop correctly.

Community and contributions

29 people contributed to this release, including core developers Matthew Flatt, Matthias Felleisen, and Robby Findler. The full list is in the announcement.

How to update

Download from https://download.racket-lang.org/. Check your existing code for the breaking changes in match and Typed Racket before upgrading.