Skip to content

Commit b274d31

Browse files
authored
Fix #1661 field-erasure for destruct punning field (#1734)
from xvw/1661-destructing-punned-record-field-breaks-syntax
2 parents 3488e07 + 943c885 commit b274d31

3 files changed

Lines changed: 71 additions & 4 deletions

File tree

CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ merlin NEXT_VERSION
33

44
+ merlin binary
55
- destruct: Removal of residual patterns (#1737, fixes #1560)
6+
- Do not erase fields' names when destructing punned record fields (#1734,
7+
fixes #1661)
68

79
merlin 4.14
810
===========

src/analysis/destruct.ml

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,25 @@ let find_branch patterns sub =
481481
in
482482
aux [] patterns
483483

484+
(* In the presence of record punning fields, the definition must be reconstructed
485+
with the label. ie: [{a; b}] with destruction on [a] becomes *)
486+
(* [{a = destruct_result; b}]. *)
487+
let find_field_name_for_punned_field patt = function
488+
| Pattern {pat_desc = Tpat_record (fields, _); _} :: _ ->
489+
List.find_opt ~f:(fun (_, _, opat) ->
490+
let ppat_loc = patt.Typedtree.pat_loc
491+
and opat_loc = opat.Typedtree.pat_loc in
492+
Int.equal (Location_aux.compare ppat_loc opat_loc) 0
493+
) fields |> Option.map ~f:(fun (_, label, _) -> label)
494+
| _ -> None
495+
496+
let print_pretty ?punned_field config source subject =
497+
let result = Mreader.print_pretty config source subject in
498+
match punned_field with
499+
| None -> result
500+
| Some label ->
501+
label.Types.lbl_name ^ " = " ^ result
502+
484503
let rec node config source selected_node parents =
485504
let open Extend_protocol.Reader in
486505
let loc = Mbrowse.node_loc selected_node in
@@ -571,9 +590,9 @@ let rec node config source selected_node parents =
571590
| [ more_precise ] ->
572591
(* If only one pattern is generated, then we're only refining the
573592
current pattern, not generating new branches. *)
593+
let punned_field = find_field_name_for_punned_field patt parents in
574594
let ppat = filter_pat_attr (Untypeast.untype_pattern more_precise) in
575-
let str = Mreader.print_pretty
576-
config source (Pretty_pattern ppat) in
595+
let str = print_pretty ?punned_field config source (Pretty_pattern ppat) in
577596
patt.Typedtree.pat_loc, str
578597
| sub_patterns ->
579598
let rev_before, after, top_patt =
@@ -609,9 +628,9 @@ let rec node config source selected_node parents =
609628
in
610629
(* Format.eprintf "por %a \n%!" (Printtyped.pattern 0) p; *)
611630
let ppat = filter_pat_attr (Untypeast.untype_pattern p) in
631+
612632
(* Format.eprintf "ppor %a \n%!" (Pprintast.pattern) ppat; *)
613-
let str = Mreader.print_pretty
614-
config source (Pretty_pattern ppat) in
633+
let str = Mreader.print_pretty config source (Pretty_pattern ppat) in
615634
(* Format.eprintf "STR: %s \n %!" str; *)
616635
top_patt.Typedtree.pat_loc, str
617636
end
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
$ $MERLIN single case-analysis -start 2:9 -end 2:9 \
2+
> -filename main.ml <<EOF
3+
> type t = {a: int * int; b: string}
4+
> let f ({a; b} : t) = assert false
5+
> EOF
6+
{
7+
"class": "return",
8+
"value": [
9+
{
10+
"start": {
11+
"line": 2,
12+
"col": 8
13+
},
14+
"end": {
15+
"line": 2,
16+
"col": 9
17+
}
18+
},
19+
"a = (_, _)"
20+
],
21+
"notifications": []
22+
}
23+
24+
25+
$ $MERLIN single case-analysis -start 2:9 -end 2:9 \
26+
> -filename main.ml <<EOF
27+
> type t = {a: int option; b: string}
28+
> let f ({a; b} : t) = assert false
29+
> EOF
30+
{
31+
"class": "return",
32+
"value": [
33+
{
34+
"start": {
35+
"line": 2,
36+
"col": 7
37+
},
38+
"end": {
39+
"line": 2,
40+
"col": 13
41+
}
42+
},
43+
"({ a = None; b } : t) | ({ a = Some _; b } : t)"
44+
],
45+
"notifications": []
46+
}

0 commit comments

Comments
 (0)