Skip to content

Type spreads of regular variants in patterns #6721

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 18 commits into from
Sep 26, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
change to use Ppat_type as transfer mechanism for variant spreads ins…
…tead of Ppat_var
  • Loading branch information
zth committed Sep 26, 2024
commit 5354e3140fb13bee601d11c2eae1dfa344ff9b79
20 changes: 9 additions & 11 deletions jscomp/ml/typecore.ml
Original file line number Diff line number Diff line change
Expand Up @@ -596,7 +596,7 @@ let build_or_pat env loc lid =
pat pats in
(path, rp { r with pat_loc = loc },ty)

let extract_type_from_pat_variant_spread env loc lid expected_ty =
let extract_type_from_pat_variant_spread env lid expected_ty =
let path, decl = Typetexp.find_type env lid.loc lid.txt in
match decl with
| {type_kind = Type_variant constructors; type_params} -> (
Expand All @@ -606,29 +606,27 @@ let extract_type_from_pat_variant_spread env loc lid expected_ty =
Ctype.subtype env ty expected_ty ()
with
Ctype.Subtype (tr1, tr2) ->
raise(Error(loc, env, Not_subtype(tr1, tr2)))
raise(Error(lid.loc, env, Not_subtype(tr1, tr2)))
);
(path, decl, constructors, ty))
| _ -> raise (Error (lid.loc, env, Not_a_variant_type lid.txt))

let build_ppat_or_for_variant_spread pat env expected_ty =
match pat with
| {ppat_desc = Ppat_var {txt; loc = var_loc}; ppat_attributes}
| {ppat_desc = Ppat_type lident; ppat_attributes}
when Variant_coercion.has_res_pat_variant_spread_attribute ppat_attributes
->
let _, _, constructors, ty =
extract_type_from_pat_variant_spread !env var_loc
(Location.mkloc (Longident.parse txt) var_loc)
expected_ty
extract_type_from_pat_variant_spread !env lident expected_ty
in
let synthetic_or_patterns =
constructors
|> List.map (fun (c : Types.constructor_declaration) ->
Ast_helper.Pat.mk ~attrs:[Variant_type_spread.mk_pat_from_variant_spread_attr ()] ~loc:var_loc
Ast_helper.Pat.mk ~attrs:[Variant_type_spread.mk_pat_from_variant_spread_attr ()] ~loc:lident.loc
(Ppat_construct
( Location.mkloc
(Longident.Lident (Ident.name c.cd_id))
var_loc,
lident.loc,
match c.cd_args with
| Cstr_tuple [] -> None
| _ -> Some (Ast_helper.Pat.any ()) )))
Expand All @@ -645,11 +643,11 @@ let build_ppat_or_for_variant_spread pat env expected_ty =

let maybe_expand_variant_spread_in_pattern pattern env expected_ty =
match pattern.Parsetree.ppat_desc with
| Ppat_var _
| Ppat_type _
when Variant_coercion.has_res_pat_variant_spread_attribute
pattern.ppat_attributes -> (
match build_ppat_or_for_variant_spread pattern env expected_ty with
| None -> assert false
| None -> assert false (* TODO: Fix. *)
| Some (pattern, _) -> pattern)
| _ -> pattern

Expand Down Expand Up @@ -1186,7 +1184,7 @@ and type_pat_aux ~constrs ~labels ~no_existentials ~mode ~explode ~env
| Ppat_alias(sq, name) ->
let as_type, sq =
match sq with
| {ppat_desc = Ppat_var _; ppat_attributes}
| {ppat_desc = Ppat_type _; ppat_attributes}
when Variant_coercion.has_res_pat_variant_spread_attribute ppat_attributes
-> (
match build_ppat_or_for_variant_spread sq env expected_ty with
Expand Down
5 changes: 2 additions & 3 deletions jscomp/syntax/src/res_core.ml
Original file line number Diff line number Diff line change
Expand Up @@ -1082,11 +1082,10 @@ let rec parse_pattern ?(alias = true) ?(or_ = true) p =
| DotDotDot ->
Parser.next p;
let ident = parse_value_path p in
let var_name = ident.txt |> Longident.flatten |> String.concat "." in
let loc = mk_loc start_pos ident.loc.loc_end in
Ast_helper.Pat.var ~loc
Ast_helper.Pat.type_ ~loc
~attrs:(make_pat_variant_spread_attr :: attrs)
(Location.mkloc var_name ident.loc)
ident
| Hash -> (
Parser.next p;
if p.Parser.token == DotDotDot then (
Expand Down
8 changes: 4 additions & 4 deletions jscomp/syntax/src/res_printer.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2203,10 +2203,6 @@ and print_pattern ~state (p : Parsetree.pattern) cmt_tbl =
let pattern_without_attributes =
match p.ppat_desc with
| Ppat_any -> Doc.text "_"
| Ppat_var var
when ParsetreeViewer.has_res_pat_variant_spread_attribute
p.ppat_attributes ->
Doc.concat [Doc.text "..."; print_ident_like var.txt]
| Ppat_var var -> print_ident_like var.txt
| Ppat_constant c ->
let template_literal =
Expand Down Expand Up @@ -2408,6 +2404,10 @@ and print_pattern ~state (p : Parsetree.pattern) cmt_tbl =
]
in
Doc.group (Doc.concat [variant_name; args_doc])
| Ppat_type ident
when ParsetreeViewer.has_res_pat_variant_spread_attribute
p.ppat_attributes ->
Doc.concat [Doc.text "..."; print_ident_path ident cmt_tbl]
| Ppat_type ident ->
Doc.concat [Doc.text "#..."; print_ident_path ident cmt_tbl]
| Ppat_record (rows, open_flag) ->
Expand Down
14 changes: 7 additions & 7 deletions jscomp/test/VariantPatternMatchingSpreads.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading