v2026.7.16
A strict drop-in policy — reject, don't silently fall back to backtracking.
The std::regex and re drop-ins used to differ: the Python binding rejected an unsupported pattern, while
real::compat silently fell back to std::regex — reintroducing the ReDoS the library exists to avoid, on
exactly the patterns a caller can least audit. Both are now strict by default.
- A pattern the linear engine cannot represent (a backreference, a conditional, an unbounded lookaround) is
rejected, not silently delegated — so every accepted pattern is a linear-time, ReDoS-safe guarantee.
In C++ that is aregex_errorwitherror_complexityand a REAL-identifiable message; in Python, a
real.error. A pattern invalid for both engines still reports the standard library's own error code,
so a syntax error stays a syntax error — a true drop-in there. - Fallback is opt-in and observable.
real::compat::regex(pat, flags, policy::fallback)in C++, and
real.compile(pat, fallback=True)(or module-widereal.fallback = True) in Python, restore delegation
tostd::regex/refor ineligible patterns — forfeiting the linear-time guarantee for those.uses_real()
/uses_fallback()/policy()(C++) andPattern.engine(Python,"real"or"re") always tell you
which backend backs a pattern.
Also: the dev tooling is consolidated under tools/ (the Unicode-table codegen joins the layering check).
This changes the compat default while it is still pre-adoption; migrate a caller that wants the old behaviour
by passing policy::fallback / fallback=True. See COMPATIBILITY.md's "The drop-in policy".