#Dev

Racket 9.2 Brings Safer Pattern Matching, Typed Racket Improvements, and Unicode 17 Support

Tech Essays Reporter
5 min read

Racket 9.2, released on 27 May 2026, tightens the semantics of the `match` form, fixes unsound Typed Racket type handling for complex results, upgrades Unicode handling, and adds a host of internal refinements such as a new foreign‑interface core form, cross‑phase persistent modules, and better stepper displays.

Introduction

On 27 May 2026 the Racket team announced the availability of Racket 9.2 (download page). While the release is littered with dozens of bug fixes, three changes stand out as conceptually significant: a stricter match form that eliminates a class of subtle runtime errors, a correction to Typed Racket’s handling of asin and acos that restores soundness, and the adoption of Unicode 17.0 for all string and character operations. Together they illustrate how a language that has long prized both expressive power and formal rigor continues to evolve its core abstractions.

Safer non‑linear pattern matching

The match form is one of Racket’s most celebrated syntactic conveniences, allowing developers to deconstruct data structures with a syntax reminiscent of functional languages such as Haskell or OCaml. In earlier versions, non‑linear patterns—patterns that bind the same identifier more than once—were permitted even when the pattern was used with the ellipsis (...) operator. This created a loophole: the language would not verify that the repeated sub‑patterns actually matched the same value, potentially leading to silent logical bugs.

What changed?

  • Equality enforcement – When a non‑linear pattern appears inside a repeated context (...), the matcher now checks that the two (or more) matched sub‑values are equal according to equal?. If they differ, the pattern fails rather than silently succeeding.
  • Rejection of mixed usage – A pattern that mixes a repeated occurrence of a variable with a non‑repeated one is now rejected outright. For example, (match v [(list x ... x) …]) will raise a compile‑time error because x appears both inside and outside the ellipsis.

Implications

Existing code that relied on the former lax behavior may now encounter match failures at runtime or compile‑time errors during migration. The change, however, eliminates a whole class of bugs that were previously only discoverable through exhaustive testing. Developers are encouraged to refactor such patterns by introducing explicit equality checks or by restructuring data so that repeated variables are not needed.

Typed Racket’s asin/acos soundness fix

Typed Racket provides static type checking for Racket programs, but its interaction with the underlying numeric tower has always been delicate. The asin and acos procedures can return complex numbers when their argument lies outside the interval [-1, 1]. Prior to 9.2 the Typed Racket type signatures for these functions incorrectly suggested they always return a real number, which could lead to unsound type inference and runtime type errors.

The repair

The type signatures now correctly reflect the possibility of a complex result, using the Complex supertype where appropriate. Consequently, code that previously compiled under the assumption of a real result may now be rejected at compile time, prompting the programmer to handle the complex case explicitly (e.g., via real-part, imag-part, or a conditional guard).

Broader impact

This adjustment reinforces Typed Racket’s commitment to type safety rather than convenience. It also serves as a reminder that even well‑tested numeric libraries can harbor subtle type mismatches, especially when extending the language’s numeric tower.

Unicode 17.0 integration

Racket’s string and character primitives now operate on Unicode 17.0, the most recent version of the Unicode Standard. This upgrade brings support for newly added scripts, emoji, and grapheme clusters, ensuring that Racket applications can process modern text without resorting to external libraries.

  • Practical benefit – Functions such as string-upcase, string-downcase, and char-alphabetic? now recognize the latest character properties.
  • Potential pitfalls – Code that performed manual code‑point arithmetic may need to be revisited, as the numeric values of some characters have shifted with the new version.

Other noteworthy enhancements

Feature Description
#%foreign-inline A new core syntactic form exposing low‑level linklet facilities; code that enumerates core forms must be updated.
terminal-file-position Counts bytes written to terminal‑connected ports (e.g., stdin, stderr).
Cross‑phase persistent modules Allows a broader class of quoted data to survive across compilation phases, simplifying macro libraries.
Kernel‑only rewrites Implementations of member, memw, when, unless, let/ec, and cond now rely solely on racket/kernel syntax, reducing dependency surface.
impersonator-property-predicate-procedure? Predicate to identify procedures created by make-impersonator-property.
Typed Racket struct printing Polymorphic struct types are displayed with explicit type arguments (e.g., (Array Byte)) rather than internal identifiers.
Stepper number display Aligns numeric formatting with the language’s current locale settings.
Scribble scaling Documents not using the racket-manual style now default to an initial scale of 1.0; the manual style retains 0.8 but can be overridden via the initial-scale property.
Margin notes Appear inline on narrow displays across all styles, improving readability on mobile devices.
.dmg big‑bang programs Correct handling of the close-on-stop flag, fixing a long‑standing packaging issue on macOS.

Community and contribution

The release acknowledges a long list of contributors, ranging from core maintainers like Matthew Flatt and Matthias Felleisen to community members such as Pavel Panchekha and Vincent Lee. As a community‑driven project, Racket continues to welcome new contributors; the repository’s README.md provides guidance on getting started, and discussions thrive on the Racket Discourse and Discord channels.

Looking ahead

While Racket 9.2 is primarily a maintenance release, the internal groundwork for a more static ffi2 foreign interface hints at future expansions in inter‑language operability. Developers interested in low‑level bindings should keep an eye on the forthcoming package that will expose this interface.


In summary, Racket 9.2 tightens pattern‑matching semantics, restores soundness to Typed Racket’s trigonometric functions, and embraces the latest Unicode standard, all while delivering a suite of incremental improvements that collectively raise the language’s reliability. Users are encouraged to upgrade, review any code that relied on the now‑repaired behaviours, and participate in the vibrant Racket community.

Comments

Loading comments...