diff --git a/CHANGELOG.md b/CHANGELOG.md index 2917714028..48ed6d494b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ #### :bug: Bug fix +- Fix option optimisation that resulted in incorrect JS output. https://github.com/rescript-lang/rescript/pull/7766 - Fix formatting of nested records in `.resi` files. https://github.com/rescript-lang/rescript/pull/7741 - Don't format and don't check formatting of dependencies. https://github.com/rescript-lang/rescript/pull/7748 - Fix `rescript-editor-analysis semanticTokens` returning invalid JSON in certain cases. https://github.com/rescript-lang/rescript/pull/7750 diff --git a/compiler/core/lam_pass_remove_alias.ml b/compiler/core/lam_pass_remove_alias.ml index 67472564fe..6b66d43ea0 100644 --- a/compiler/core/lam_pass_remove_alias.ml +++ b/compiler/core/lam_pass_remove_alias.ml @@ -26,16 +26,17 @@ type outcome = Eval_false | Eval_true | Eval_unknown let id_is_for_sure_true_in_boolean (tbl : Lam_stats.ident_tbl) id = match Hash_ident.find_opt tbl id with - | Some (ImmutableBlock _) - | Some (Normal_optional _) - | Some (MutableBlock _) - | Some (Constant (Const_block _ | Const_js_true)) -> - Eval_true + | Some + (Normal_optional + (Lconst (Const_js_false | Const_js_null | Const_js_undefined _))) -> + Eval_false + | Some (Constant Const_js_true) -> Eval_true | Some (Constant (Const_int {i})) -> if i = 0l then Eval_false else Eval_true | Some (Constant (Const_js_false | Const_js_null | Const_js_undefined _)) -> Eval_false | Some - ( Constant _ | Module _ | FunctionId _ | Exception | Parameter | NA + ( Normal_optional _ | ImmutableBlock _ | MutableBlock _ | Constant _ + | Module _ | FunctionId _ | Exception | Parameter | NA | OptionalBlock (_, (Undefined | Null | Null_undefined)) ) | None -> Eval_unknown diff --git a/tests/tests/src/option_optimisation.mjs b/tests/tests/src/option_optimisation.mjs new file mode 100644 index 0000000000..aa7e495080 --- /dev/null +++ b/tests/tests/src/option_optimisation.mjs @@ -0,0 +1,35 @@ +// Generated by ReScript, PLEASE EDIT WITH CARE + +import * as Primitive_option from "rescript/lib/es6/Primitive_option.js"; + +function boolean(val1, val2) { + let a = val1; + let b = val2; + if (b || a) { + return "a"; + } else { + return "b"; + } +} + +function $$null(val1, val2) { + let a = Primitive_option.some(val1); + let b = Primitive_option.some(val2); + let tmp = Primitive_option.valFromOption(b); + if (tmp !== null && tmp !== undefined) { + return "a"; + } + tmp === null; + let tmp$1 = Primitive_option.valFromOption(a); + if (tmp$1 == null) { + return "b"; + } else { + return "a"; + } +} + +export { + boolean, + $$null, +} +/* No side effect */ diff --git a/tests/tests/src/option_optimisation.res b/tests/tests/src/option_optimisation.res new file mode 100644 index 0000000000..32d3667d29 --- /dev/null +++ b/tests/tests/src/option_optimisation.res @@ -0,0 +1,21 @@ +let boolean = (~val1: bool, ~val2: bool) => { + let a = Some(val1) + let b = Some(val2) + + switch (a, b) { + | (_, Some(true)) + | (Some(true), _) => "a" + | _ => "b" + } +} + +let null = (~val1: Nullable.t, ~val2: Nullable.t) => { + let a = Some(val1) + let b = Some(val2) + + switch (a, b) { + | (_, Some(Value(_))) + | (Some(Value(_)), _) => "a" + | _ => "b" + } +}