Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@

- Reanalyze: add glob pattern support for suppress/unsuppress configurations (e.g., `"src/generated/**"`). https://github.com/rescript-lang/rescript/pull/8277
- Add optional `~locales` and `~options` parameters to `String.localeCompare`. https://github.com/rescript-lang/rescript/pull/8287
- Add support for pattern matching/destructuring of record rest. https://github.com/rescript-lang/rescript/pull/8317

#### :bug: Bug fix

Expand Down
2 changes: 1 addition & 1 deletion analysis/reanalyze/src/DeadValue.ml
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ let collectPattern ~config ~refs :
fun super self pat ->
let posFrom = pat.Typedtree.pat_loc.loc_start in
(match pat.pat_desc with
| Typedtree.Tpat_record (cases, _clodsedFlag) ->
| Typedtree.Tpat_record (cases, _clodsedFlag, _rest) ->
cases
|> List.iter (fun (_loc, {Types.lbl_loc = {loc_start = posTo}}, _pat, _) ->
if !Config.analyzeTypes then
Expand Down
2 changes: 1 addition & 1 deletion analysis/src/CompletionFrontEnd.ml
Original file line number Diff line number Diff line change
Expand Up @@ -514,7 +514,7 @@ let completionWithParser1 ~currentFile ~debug ~offset ~path ~posCursor
(NPolyvariantPayload {itemNum = 0; constructorName = txt}
:: patternPath)
?contextPath p
| Ppat_record (fields, _) ->
| Ppat_record (fields, _, _rest) ->
Ext_list.iter fields (fun {lid = fname; x = p} ->
match fname with
| {Location.txt = Longident.Lident fname} ->
Expand Down
4 changes: 2 additions & 2 deletions analysis/src/CompletionPatterns.ml
Original file line number Diff line number Diff line change
Expand Up @@ -102,12 +102,12 @@ and traversePattern (pat : Parsetree.pattern) ~patternPath ~locHasCursor
[Completable.NTupleItem {itemNum}] @ patternPath)
~resultFromFoundItemNum:(fun itemNum ->
[Completable.NTupleItem {itemNum = itemNum + 1}] @ patternPath)
| Ppat_record ([], _) ->
| Ppat_record ([], _, _rest) ->
(* Empty fields means we're in a record body `{}`. Complete for the fields. *)
someIfHasCursor
("", [Completable.NRecordBody {seenFields = []}] @ patternPath)
"Ppat_record(empty)"
| Ppat_record (fields, _) -> (
| Ppat_record (fields, _, _rest) -> (
let fieldWithCursor = ref None in
let fieldWithPatHole = ref None in
Ext_list.iter fields (fun {lid = fname; x = f} ->
Expand Down
2 changes: 1 addition & 1 deletion analysis/src/DumpAst.ml
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ let rec printPattern pattern ~pos ~indentation =
| None -> ""
| Some pat -> "," ^ printPattern pat ~pos ~indentation)
^ ")"
| Ppat_record (fields, _) ->
| Ppat_record (fields, _, _rest) ->
"Ppat_record(\n"
^ addIndentation (indentation + 1)
^ "fields:\n"
Expand Down
2 changes: 1 addition & 1 deletion analysis/src/Hint.ml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ let inlay ~path ~pos ~maxLength ~debug =
let rec processPattern (pat : Parsetree.pattern) =
match pat.ppat_desc with
| Ppat_tuple pl -> pl |> List.iter processPattern
| Ppat_record (fields, _) ->
| Ppat_record (fields, _, _rest) ->
Ext_list.iter fields (fun {x = p} -> processPattern p)
| Ppat_array fields -> fields |> List.iter processPattern
| Ppat_var {loc} -> push loc Type
Expand Down
2 changes: 1 addition & 1 deletion analysis/src/ProcessCmt.ml
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ let rec forStructureItem ~(env : SharedTypes.Env.t) ~(exported : Exported.t)
| Tpat_tuple pats | Tpat_array pats | Tpat_construct (_, _, pats) ->
pats |> List.iter (fun p -> handlePattern [] p)
| Tpat_or (p, _, _) -> handlePattern [] p
| Tpat_record (items, _) ->
| Tpat_record (items, _, _rest) ->
items |> List.iter (fun (_, _, p, _) -> handlePattern [] p)
| Tpat_variant (_, Some p, _) -> handlePattern [] p
| Tpat_variant (_, None, _) | Tpat_any | Tpat_constant _ -> ()
Expand Down
2 changes: 1 addition & 1 deletion analysis/src/ProcessExtra.ml
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ let pat ~(file : File.t) ~env ~extra (iter : Tast_iterator.iterator)
in
(* Log.log("Entering pattern " ++ Utils.showLocation(pat_loc)); *)
(match pattern.pat_desc with
| Tpat_record (items, _) ->
| Tpat_record (items, _, _rest) ->
addForRecord ~env ~extra ~recordType:pattern.pat_type items
| Tpat_construct (lident, constructor, _) ->
addForConstructor ~env ~extra pattern.pat_type lident constructor
Expand Down
2 changes: 1 addition & 1 deletion analysis/src/SemanticTokens.ml
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,7 @@ let command ~debug ~emitter ~path =
| Ppat_construct ({txt = Lident ("true" | "false")}, _) ->
(* Don't emit true or false *)
Ast_iterator.default_iterator.pat iterator p
| Ppat_record (cases, _) ->
| Ppat_record (cases, _, _rest) ->
Ext_list.iter cases (fun {lid = label} ->
emitter |> emitRecordLabel ~label ~debug);
Ast_iterator.default_iterator.pat iterator p
Expand Down
3 changes: 2 additions & 1 deletion analysis/src/SignatureHelp.ml
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,8 @@ let signatureHelp ~path ~pos ~currentFile ~debug ~allowForConstructorPayloads =
match tupleItemWithCursor with
| None -> -1
| Some i -> i)
| `ConstructorPat (_, {ppat_desc = Ppat_record (fields, _)}) -> (
| `ConstructorPat (_, {ppat_desc = Ppat_record (fields, _, _rest)})
-> (
let fieldNameWithCursor =
fields
|> List.find_map
Expand Down
2 changes: 1 addition & 1 deletion analysis/src/Xform.ml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ module IfThenElse = struct
in
match listToPat ~itemToPat items with
| None -> None
| Some patItems -> Some (mkPat (Ppat_record (patItems, Closed))))
| Some patItems -> Some (mkPat (Ppat_record (patItems, Closed, None))))
| Pexp_record (_, Some _) -> None
| _ -> None

Expand Down
4 changes: 2 additions & 2 deletions compiler/common/pattern_printer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ let untype typed =
| Tpat_variant (label, p_opt, _row_desc) ->
let arg = Option.map loop p_opt in
mkpat (Ppat_variant (label, arg))
| Tpat_record (subpatterns, closed_flag) ->
| Tpat_record (subpatterns, closed_flag, _rest) ->
let fields, saw_optional_rewrite =
List.fold_right
(fun (_, lbl, p, opt) (fields, saw_optional_rewrite) ->
Expand All @@ -97,7 +97,7 @@ let untype typed =
subpatterns ([], false)
in
let closed_flag = if saw_optional_rewrite then Closed else closed_flag in
mkpat (Ppat_record (fields, closed_flag))
mkpat (Ppat_record (fields, closed_flag, None))
| Tpat_array lst -> mkpat (Ppat_array (List.map loop lst))
in
loop typed
Expand Down
2 changes: 1 addition & 1 deletion compiler/core/lam_analysis.ml
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ let rec no_side_effects (lam : Lam.t) : bool =
(* whether it's mutable or not *)
| Pfield _ | Pval_from_option | Pval_from_option_not_nest
(* NOP The compiler already [t option] is the same as t *)
| Pduprecord
| Pduprecord | Precord_spread_new _
(* generic primitives *)
| Pobjcomp _ | Pobjorder | Pobjmin | Pobjmax | Pobjtag | Pobjsize
(* bool primitives *)
Expand Down
12 changes: 12 additions & 0 deletions compiler/core/lam_compile_primitive.ml
Original file line number Diff line number Diff line change
Expand Up @@ -603,6 +603,18 @@ let translate output_prefix loc (cxt : Lam_compile_context.t)
match args with
| [e1] -> E.obj ~dup:e1 []
| _ -> assert false)
| Precord_spread_new excluded -> (
match args with
| [e1] ->
(* Generate: (({field1, field2, ...rest}) => rest)(source)
This uses JS destructuring to cleanly extract the rest *)
let excluded_str = String.concat ", " excluded in
let code = Printf.sprintf "(({%s, ...__rest}) => __rest)" excluded_str in
E.call
~info:{arity = Full; call_info = Call_na; call_transformed_jsx = false}
(E.raw_js_code (Exp (Js_function {arity = 1; arrow = true})) code)
[e1]
| _ -> assert false)
| Phash -> (
match args with
| [e1; e2; e3; e4] -> E.runtime_call Primitive_modules.hash "hash" args
Expand Down
2 changes: 2 additions & 0 deletions compiler/core/lam_convert.ml
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,8 @@ let lam_prim ~primitive:(p : Lambda.primitive) ~args loc : Lam.t =
| Pfield (id, info) -> prim ~primitive:(Pfield (id, info)) ~args loc
| Psetfield (id, info) -> prim ~primitive:(Psetfield (id, info)) ~args loc
| Pduprecord -> prim ~primitive:Pduprecord ~args loc
| Precord_spread_new excluded ->
prim ~primitive:(Precord_spread_new excluded) ~args loc
| Praise _ -> prim ~primitive:Praise ~args loc
| Pobjcomp x -> prim ~primitive:(Pobjcomp x) ~args loc
| Pobjorder -> prim ~primitive:Pobjorder ~args loc
Expand Down
7 changes: 4 additions & 3 deletions compiler/core/lam_primitive.ml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ type t =
| Psetfield of int * Lam_compat.set_field_dbg_info
(* could have field info at least for record *)
| Pduprecord
| Precord_spread_new of string list
(* External call *)
| Pjs_call of {
prim_name: string;
Expand Down Expand Up @@ -226,9 +227,9 @@ let eq_primitive_approx (lhs : t) (rhs : t) =
| Pnull_to_opt | Pnull_undefined_to_opt | Pis_null | Pis_not_none | Psome
| Psome_not_nest | Pis_undefined | Pis_null_undefined | Pimport | Ptypeof
| Pfn_arity | Pis_poly_var_block | Pdebugger | Pinit_mod | Pupdate_mod
| Pduprecord | Pmakearray | Parraylength | Parrayrefu | Parraysetu
| Parrayrefs | Parraysets | Pjs_fn_make_unit | Pjs_fn_method | Phash
| Phash_mixstring | Phash_mixint | Phash_finalmix ->
| Pduprecord | Precord_spread_new _ | Pmakearray | Parraylength | Parrayrefu
| Parraysetu | Parrayrefs | Parraysets | Pjs_fn_make_unit | Pjs_fn_method
| Phash | Phash_mixstring | Phash_mixint | Phash_finalmix ->
rhs = lhs
| Pcreate_extension a -> (
match rhs with
Expand Down
1 change: 1 addition & 0 deletions compiler/core/lam_primitive.mli
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ type t =
| Pfield of int * Lambda.field_dbg_info
| Psetfield of int * Lambda.set_field_dbg_info
| Pduprecord
| Precord_spread_new of string list
| Pjs_call of {
(* Location.t * [loc] is passed down *)
prim_name: string;
Expand Down
2 changes: 2 additions & 0 deletions compiler/core/lam_print.ml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ let primitive ppf (prim : Lam_primitive.t) =
let instr = "setfield " in
fprintf ppf "%s%i" instr n
| Pduprecord -> fprintf ppf "duprecord"
| Precord_spread_new excluded ->
fprintf ppf "record_spread_new(%s)" (String.concat ", " excluded)
| Pjs_call {prim_name} -> fprintf ppf "%s[js]" prim_name
| Pjs_object_create _ -> fprintf ppf "[js.obj]"
| Praise -> fprintf ppf "raise"
Expand Down
7 changes: 6 additions & 1 deletion compiler/ext/warnings.ml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ type t =
| Bs_toplevel_expression_unit of
(string * top_level_unit_help) option (* 109 *)
| Bs_todo of string option (* 110 *)
| Bs_record_rest_empty (* 111 *)

(* If you remove a warning, leave a hole in the numbering. NEVER change
the numbers of existing warnings.
Expand Down Expand Up @@ -154,8 +155,9 @@ let number = function
| Bs_uninterpreted_delimiters _ -> 108
| Bs_toplevel_expression_unit _ -> 109
| Bs_todo _ -> 110
| Bs_record_rest_empty -> 111

let last_warning_number = 110
let last_warning_number = 111

let letter_all =
let rec loop i = if i = 0 then [] else i :: loop (i - 1) in
Expand Down Expand Up @@ -532,6 +534,9 @@ let message = function
`%s->ignore`"
help_text help_text
| _ -> "")
| Bs_record_rest_empty ->
"All fields of the rest type are already present in the explicit pattern. \
The rest record will always be empty."
| Bs_todo maybe_text ->
(match maybe_text with
| None -> "Todo found."
Expand Down
1 change: 1 addition & 0 deletions compiler/ext/warnings.mli
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ type t =
| Bs_toplevel_expression_unit of
(string * top_level_unit_help) option (* 109 *)
| Bs_todo of string option (* 110 *)
| Bs_record_rest_empty (* 111 *)

val parse_options : bool -> string -> unit

Expand Down
2 changes: 1 addition & 1 deletion compiler/frontend/ast_tuple_pattern_flatten.ml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ let flattern_tuple_pattern_vb (self : Bs_ast_mapper.mapper)
}
:: acc)
| _ -> {pvb_pat; pvb_expr; pvb_loc = vb.pvb_loc; pvb_attributes} :: acc)
| Ppat_record (lid_pats, _), Pexp_pack {pmod_desc = Pmod_ident id} ->
| Ppat_record (lid_pats, _, _rest), Pexp_pack {pmod_desc = Pmod_ident id} ->
Ext_list.map_append lid_pats acc (fun {lid; x = pat} ->
match lid.txt with
| Lident s ->
Expand Down
6 changes: 5 additions & 1 deletion compiler/frontend/bs_ast_mapper.ml
Original file line number Diff line number Diff line change
Expand Up @@ -425,8 +425,12 @@ module P = struct
| Ppat_construct (l, p) ->
construct ~loc ~attrs (map_loc sub l) (map_opt (sub.pat sub) p)
| Ppat_variant (l, p) -> variant ~loc ~attrs l (map_opt (sub.pat sub) p)
| Ppat_record (lpl, cf) ->
| Ppat_record (lpl, cf, rest) ->
record ~loc ~attrs
?rest:
(match rest with
| None -> None
| Some p -> Some (sub.pat sub p))
(List.map
(fun {lid; x = p; opt} ->
{lid = map_loc sub lid; x = sub.pat sub p; opt})
Expand Down
2 changes: 1 addition & 1 deletion compiler/ml/ast_helper.ml
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ module Pat = struct
let tuple ?loc ?attrs a = mk ?loc ?attrs (Ppat_tuple a)
let construct ?loc ?attrs a b = mk ?loc ?attrs (Ppat_construct (a, b))
let variant ?loc ?attrs a b = mk ?loc ?attrs (Ppat_variant (a, b))
let record ?loc ?attrs a b = mk ?loc ?attrs (Ppat_record (a, b))
let record ?loc ?attrs ?rest a b = mk ?loc ?attrs (Ppat_record (a, b, rest))
let array ?loc ?attrs a = mk ?loc ?attrs (Ppat_array a)
let or_ ?loc ?attrs a b = mk ?loc ?attrs (Ppat_or (a, b))
let constraint_ ?loc ?attrs a b = mk ?loc ?attrs (Ppat_constraint (a, b))
Expand Down
1 change: 1 addition & 0 deletions compiler/ml/ast_helper.mli
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ module Pat : sig
val record :
?loc:loc ->
?attrs:attrs ->
?rest:pattern ->
pattern record_element list ->
closed_flag ->
pattern
Expand Down
2 changes: 1 addition & 1 deletion compiler/ml/ast_iterator.ml
Original file line number Diff line number Diff line change
Expand Up @@ -398,7 +398,7 @@ module P = struct
iter_loc sub l;
iter_opt (sub.pat sub) p
| Ppat_variant (_l, p) -> iter_opt (sub.pat sub) p
| Ppat_record (lpl, _cf) ->
| Ppat_record (lpl, _cf, _rest) ->
List.iter
(fun {lid; x = pat} ->
iter_loc sub lid;
Expand Down
6 changes: 5 additions & 1 deletion compiler/ml/ast_mapper.ml
Original file line number Diff line number Diff line change
Expand Up @@ -389,8 +389,12 @@ module P = struct
| Ppat_construct (l, p) ->
construct ~loc ~attrs (map_loc sub l) (map_opt (sub.pat sub) p)
| Ppat_variant (l, p) -> variant ~loc ~attrs l (map_opt (sub.pat sub) p)
| Ppat_record (lpl, cf) ->
| Ppat_record (lpl, cf, rest) ->
record ~loc ~attrs
?rest:
(match rest with
| None -> None
| Some p -> Some (sub.pat sub p))
(List.map
(fun {lid; x = pat; opt} ->
{lid = map_loc sub lid; x = sub.pat sub pat; opt})
Expand Down
2 changes: 1 addition & 1 deletion compiler/ml/ast_mapper_to0.ml
Original file line number Diff line number Diff line change
Expand Up @@ -559,7 +559,7 @@ module P = struct
| Ppat_construct (l, p) ->
construct ~loc ~attrs (map_loc sub l) (map_opt (sub.pat sub) p)
| Ppat_variant (l, p) -> variant ~loc ~attrs l (map_opt (sub.pat sub) p)
| Ppat_record (lpl, cf) ->
| Ppat_record (lpl, cf, _rest) ->
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure about what should be done here

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good question: it goes to ast0 and then back during ppx, so any use of a ppx would discard this at the moment, and change the code

normally, one tries to encode additional ast information in special annotations, so they can be recovered on the way back (from_0)

record ~loc ~attrs
(Ext_list.map lpl (fun {lid; x = p; opt = optional} ->
let lid1 = map_loc sub lid in
Expand Down
2 changes: 1 addition & 1 deletion compiler/ml/depend.ml
Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ let rec add_pattern bv pat =
| Ppat_construct (c, op) ->
add bv c;
add_opt add_pattern bv op
| Ppat_record (pl, _) ->
| Ppat_record (pl, _, _rest) ->
List.iter
(fun {lid = lbl; x = p} ->
add bv lbl;
Comment on lines +186 to 189
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Track dependencies from record-rest annotations

The dependency walker now matches Ppat_record (pl, _, _rest) but never visits _rest. As a result, module/type paths used only in record-rest annotations (e.g. ...M.t as rest) are omitted from dependency collection, so changing those modules may not trigger recompilation or proper dependency invalidation.

Useful? React with 👍 / 👎.

Expand Down
1 change: 1 addition & 0 deletions compiler/ml/lambda.ml
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ type primitive =
| Pfield of int * field_dbg_info
| Psetfield of int * set_field_dbg_info
| Pduprecord
| Precord_spread_new of string list (* excluded field names *)
(* External call *)
| Pccall of Primitive.description
(* Exceptions *)
Expand Down
1 change: 1 addition & 0 deletions compiler/ml/lambda.mli
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ type primitive =
| Pfield of int * field_dbg_info
| Psetfield of int * set_field_dbg_info
| Pduprecord
| Precord_spread_new of string list (* excluded field names *)
(* External call *)
| Pccall of Primitive.description
(* Exceptions *)
Expand Down
Loading
Loading