You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: _blogposts/2025-09-01-let-unwrap.mdx
+5-41Lines changed: 5 additions & 41 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -25,51 +25,15 @@ let getUser = async (id) => {
25
25
}
26
26
```
27
27
28
-
This desugars to a **sequence** of `switch`/early-returns that you’d otherwise write by hand, so there’s **no extra runtime cost** and it plays nicely with `async/await`. Same idea works for `option` with `Some(...)` (and the PR also extends support so the left pattern can be `Error(...)`/`None`, not just `Ok(...)`/`Some(...)`). ([[ReScript Forum](https://forum.rescript-lang.org/t/proposing-new-syntax-for-zero-cost-unwrapping-options-results/6227)][2], [[GitHub](https://github.com/rescript-lang/rescript/pull/7582/files)][3])
28
+
This desugars to a **sequence** of `switch`/early-returns that you’d otherwise write by hand, so there’s **no extra runtime cost** and it plays nicely with `async/await`. Same idea works for `option` with `Some(...)` (and the PR also extends support so the left pattern can be `Error(...)`/`None`, not just `Ok(...)`/`Some(...)`).
29
29
30
-
### Where it works (and doesn’t)
31
-
32
-
* Targets **built-ins** only: `result` and `option`. (Custom variants still need `switch`.) ([[ReScript Forum](https://forum.rescript-lang.org/t/proposing-new-syntax-for-zero-cost-unwrapping-options-results/6227)][2])
33
-
***Block/local bindings** only; tests show top-level usage is rejected. ([[GitHub](https://github.com/rescript-lang/rescript/pull/7582/files)][3])
34
-
* The printed JS is the straightforward if/return form (i.e., “zero cost”). ([[ReScript Forum](https://forum.rescript-lang.org/t/proposing-new-syntax-for-zero-cost-unwrapping-options-results/6227)][2])
30
+
Beware it targets built-ins only: `result` and `option`. (Custom variants still need `switch`.) And it is for block or local bindings only; top-level usage is rejected.
31
+
Compiled JS code is the straightforward if/return form (i.e., “zero cost”).
35
32
36
33
### How to enable it (experimental)
37
34
38
-
* The PR adds an **experimental-features infrastructure** to the toolchain and **CLI support**: `-enable-experimental …`. Rewatch reads config from `rescript.json` and forwards the feature(s) to the compiler. (See `rewatch` config + compile changes and the new compiler flag.) ([[GitHub](https://github.com/rescript-lang/rescript/pull/7582/files)][3])
39
-
* There are tests and docs stubs around the experimental toggle plus “feature not enabled” error cases. ([[GitHub](https://github.com/rescript-lang/rescript/pull/7582/files)][3])
40
-
41
-
> In short: add the feature in `rescript.json` via the new “experimental features” setting (per the updated `CompilerConfigurationSpec.md`), or pass `-enable-experimental` in your build; otherwise `let?` is unavailable. ([[GitHub](https://github.com/rescript-lang/rescript/pull/7582/files)][3])
42
-
43
-
# Dev notes (what changed under the hood)
44
-
45
-
***Lexer/Parser/Printer:** new token for `let?`, grammar rules, and pretty-printer support. ([[GitHub](https://github.com/rescript-lang/rescript/pull/7582/files)][3])
46
-
***Frontend transform:** AST handling lowers `let?` to the equivalent `switch`/early return; tailored super-errors for misuse. ([[GitHub](https://github.com/rescript-lang/rescript/pull/7582/files)][3])
47
-
***Feature gate:** new module(s) to register/enable experimental features, with CLI wiring and rewatch config reading. ([[GitHub](https://github.com/rescript-lang/rescript/pull/7582/files)][3])
48
-
***Tests:** syntax parsing, printer snapshots, super-errors (e.g., “feature not enabled”, “top-level not allowed”, “not supported variant”, and return-type mismatch). ([[GitHub](https://github.com/rescript-lang/rescript/pull/7582/files)][3])
49
-
50
-
# Safety analysis: can this break anything when **off**?
51
-
52
-
**Bottom line:** extremely low risk when the flag is **off**.
35
+
We have added an **experimental-features infrastructure** to the toolchain. The corresponding compiler flag is `-enable-experimental`. This means you can enable `let?` in your `rescript.json`s `compiler-flags` and it forwards the feature to the compiler.
53
36
54
-
Why:
55
-
56
-
1.**Gated by default.** The feature is unreachable unless explicitly enabled; using `let?` without the gate yields a dedicated “feature not enabled” error (there are fixtures for this). That means existing codebases remain unaffected. ([[GitHub](https://github.com/rescript-lang/rescript/pull/7582/files)][3])
57
-
2.**New syntax, not repurposed.**`let?` didn’t previously parse; recognizing it only at a `let` binding start avoids collisions with existing `?` uses (e.g., ternary) elsewhere in expressions. Parser tests were added to lock this down. ([[GitHub](https://github.com/rescript-lang/rescript/pull/7582/files)][3])
58
-
3.**No runtime path changes.** It’s a compile-time sugar that lowers to the same `switch`/return structure you’d hand-write. If you don’t use it, nothing in your generated JS changes. ([[ReScript Forum](https://forum.rescript-lang.org/t/proposing-new-syntax-for-zero-cost-unwrapping-options-results/6227)][2])
59
-
4.**Confined scope.** Even when enabled, top-level `let?` is rejected; only local/block bindings are supported. This reduces any accidental global impact. ([[GitHub](https://github.com/rescript-lang/rescript/pull/7582/files)][3])
60
-
5.**Tooling guarded.** The PR tracks TODOs for error coverage and editor support; with the gate off, current editor plugins behave as before. ([[GitHub](https://github.com/rescript-lang/rescript/pull/7582)][1])
***Tokenization side-effects:** The scanner learns the `let?` token, but the feature gate + grammar location prevents it from altering how existing, valid programs lex/parse when you don’t write `let?`. Tests cover “not enabled” and misuse shapes. ([[GitHub](https://github.com/rescript-lang/rescript/pull/7582/files)][3])
65
-
***Error text churn:** Some super-error messages were added (including a hint when code looks *eligible* for `let?`). That only triggers in error paths; it won’t change successful builds. ([[GitHub](https://github.com/rescript-lang/rescript/pull/7582/files)][3])
66
-
67
-
**Conclusion:** With the experimental flag **off**, there are no functional or runtime changes, and parser behavior for all previously valid code paths is preserved. It’s safe to ship behind the flag.
68
-
69
-
---
37
+
This is purely a syntactical change so performance is not affected.
70
38
71
-
If you want, I can also jot down a tiny rollout checklist (enable flag in a sample app, verify editor plugin snapshot, run the super-errors suite) next.
72
39
73
-
[1]: https://github.com/rescript-lang/rescript/pull/7582"PoC of let? by zth · Pull Request #7582 · rescript-lang/rescript · GitHub"
74
-
[2]: https://forum.rescript-lang.org/t/proposing-new-syntax-for-zero-cost-unwrapping-options-results/6227"Proposing new syntax for zero-cost unwrapping options/results - Development - ReScript Forum"
75
-
[3]: https://github.com/rescript-lang/rescript/pull/7582/files"PoC of let? by zth · Pull Request #7582 · rescript-lang/rescript · GitHub"
0 commit comments