Skip to content

Commit 574d4ac

Browse files
authored
Fix nested variant type spreads (#7080)
* add failing tests for nested variant type spreads * add fix, but that changes list parsing slightly * add a few more good to have tests * changelog
1 parent b035602 commit 574d4ac

File tree

7 files changed

+214
-4
lines changed

7 files changed

+214
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
- Fix attribute printing. https://github.com/rescript-lang/rescript-compiler/pull/7025
3232
- Fix "rescript format" with many files. https://github.com/rescript-lang/rescript-compiler/pull/7081
3333
- Fix bigint max, min https://github.com/rescript-lang/rescript-compiler/pull/7088
34+
- Fix parsing issue with nested variant pattern type spreads. https://github.com/rescript-lang/rescript-compiler/pull/7080
3435

3536
#### :nail_care: Polish
3637

compiler/syntax/src/res_grammar.ml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ let is_structure_item_start = function
171171
let is_pattern_start = function
172172
| Token.Int _ | Float _ | String _ | Codepoint _ | Backtick | True | False
173173
| Minus | Plus | Lparen | Lbracket | Lbrace | List | Dict | Underscore
174-
| Lident _ | Uident _ | Hash | Exception | Percent | Module | At ->
174+
| DotDotDot | Lident _ | Uident _ | Hash | Exception | Percent | Module | At
175+
->
175176
true
176177
| _ -> false
177178

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
type nonrec a =
2+
| One
3+
| Two
4+
| Three
5+
type nonrec b =
6+
| ... of a
7+
| Four
8+
| Five
9+
type nonrec c =
10+
| Six
11+
| Seven
12+
type nonrec d =
13+
| ... of b
14+
| ... of c
15+
let doWithA =
16+
((Function$
17+
(fun (a : a) ->
18+
((match a with
19+
| One -> Js.log {js|aaa|js}
20+
| Two -> Js.log {js|twwwoooo|js}
21+
| Three -> Js.log {js|threeeee|js})
22+
[@res.braces ])))
23+
[@res.arity 1])
24+
let doWithB =
25+
((Function$
26+
(fun (b : b) ->
27+
((match b with
28+
| One -> Js.log {js|aaa|js}
29+
| _ -> Js.log {js|twwwoooo|js})
30+
[@res.braces ])))
31+
[@res.arity 1])
32+
let lookup =
33+
((Function$
34+
(fun (b : b) ->
35+
match b with
36+
| ((#a)[@res.patVariantSpread ]) as a -> doWithA a
37+
| Four -> Js.log {js|four|js}
38+
| Five -> Js.log {js|five|js}))
39+
[@res.arity 1])
40+
let lookup2 =
41+
((Function$
42+
(fun (d : d) ->
43+
match d with
44+
| ((#a)[@res.patVariantSpread ]) as a -> doWithA a
45+
| ((#b)[@res.patVariantSpread ]) as b -> doWithB b
46+
| Six|Seven -> Js.log {js|Got rest of d|js}))
47+
[@res.arity 1])
48+
let lookupOpt =
49+
((Function$
50+
(fun (b : b option) ->
51+
match b with
52+
| Some (((#a)[@res.patVariantSpread ]) as a) -> doWithA a
53+
| Some (Four) -> Js.log {js|four|js}
54+
| Some (Five) -> Js.log {js|five|js}
55+
| None -> Js.log {js|None|js}))
56+
[@res.arity 1])
57+
module Foo =
58+
struct
59+
type nonrec zz =
60+
| First
61+
| Second
62+
type nonrec xx =
63+
| ... of zz
64+
| Third
65+
end
66+
let doWithZ =
67+
((Function$
68+
(fun (z : Foo.zz) ->
69+
match z with
70+
| First -> Js.log {js|First|js}
71+
| Second -> Js.log {js|Second|js}))
72+
[@res.arity 1])
73+
let lookup3 =
74+
((Function$
75+
(fun (d : Foo.xx) ->
76+
match d with
77+
| ((#Foo.zz)[@res.patVariantSpread ]) as z -> Js.log z
78+
| Third -> Js.log {js|Third|js}))
79+
[@res.arity 1])
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
type a = One | Two | Three
2+
type b = | ...a | Four | Five
3+
type c = Six | Seven
4+
type d = | ...b | ...c
5+
6+
let doWithA = (a: a) => {
7+
switch a {
8+
| One => Js.log("aaa")
9+
| Two => Js.log("twwwoooo")
10+
| Three => Js.log("threeeee")
11+
}
12+
}
13+
14+
let doWithB = (b: b) => {
15+
switch b {
16+
| One => Js.log("aaa")
17+
| _ => Js.log("twwwoooo")
18+
}
19+
}
20+
21+
let lookup = (b: b) =>
22+
switch b {
23+
| ...a as a => doWithA(a)
24+
| Four => Js.log("four")
25+
| Five => Js.log("five")
26+
}
27+
28+
let lookup2 = (d: d) =>
29+
switch d {
30+
| ...a as a => doWithA(a)
31+
| ...b as b => doWithB(b)
32+
| Six | Seven => Js.log("Got rest of d")
33+
}
34+
35+
let lookupOpt = (b: option<b>) =>
36+
switch b {
37+
| Some(...a as a) => doWithA(a)
38+
| Some(Four) => Js.log("four")
39+
| Some(Five) => Js.log("five")
40+
| None => Js.log("None")
41+
}
42+
43+
44+
module Foo = {
45+
type zz = First | Second
46+
type xx = | ...zz | Third
47+
}
48+
49+
let doWithZ = (z: Foo.zz) =>
50+
switch z {
51+
| First => Js.log("First")
52+
| Second => Js.log("Second")
53+
}
54+
55+
let lookup3 = (d: Foo.xx) =>
56+
switch d {
57+
| ...Foo.zz as z => Js.log(z)
58+
| Third => Js.log("Third")
59+
}

compiler/syntax/tests/parsing/recovery/pattern/expected/list.res.txt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,17 @@
2424

2525

2626
Syntax error!
27-
tests/parsing/recovery/pattern/list.res:4:13
27+
tests/parsing/recovery/pattern/list.res:4:9-11
2828

2929
2 │ | list{} => ()
3030
3 │ | list{1, list{} => ()
3131
4 │ | list{}...1, ...list{3, 4} => ()
3232
5 │ }
3333
6 │
3434

35-
I'm not sure what to parse here when looking at ",".
35+
Did you forget a `}` here?
3636

37-
;;match x with | [] -> () | 1::[]::[] -> () | [] -> 1
37+
;;match x with | [] -> () | 1::[]::[] -> () | [] -> [%rescript.exprhole ]
38+
;;1
3839
;;[3; 4]
3940
;;()

tests/tests/src/VariantPatternMatchingSpreads.js

Lines changed: 44 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

tests/tests/src/VariantPatternMatchingSpreads.res

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,28 @@ let lookup2 = (d: d) =>
3131
| ...b as b => doWithB(b)
3232
| Six | Seven => Js.log("Got rest of d")
3333
}
34+
35+
let lookupOpt = (b: option<b>) =>
36+
switch b {
37+
| Some(...a as a) => doWithA(a)
38+
| Some(Four) => Js.log("four")
39+
| Some(Five) => Js.log("five")
40+
| None => Js.log("None")
41+
}
42+
43+
module Foo = {
44+
type zz = First | Second
45+
type xx = | ...zz | Third
46+
}
47+
48+
let doWithZ = (z: Foo.zz) =>
49+
switch z {
50+
| First => Js.log("First")
51+
| Second => Js.log("Second")
52+
}
53+
54+
let lookup3 = (d: Foo.xx) =>
55+
switch d {
56+
| ...Foo.zz as z => Js.log(z)
57+
| Third => Js.log("Third")
58+
}

0 commit comments

Comments
 (0)