A None arm written first in a match meets the other arms at their Option.
This commit is contained in:
parent
09f1e4369f
commit
89d54a47f4
20
lib/check.ml
20
lib/check.ml
@ -10367,8 +10367,24 @@ and check_match ctx ?(tail = false) ?(used = false) ?(stmt = false) ?(opt = fals
|
|||||||
let idx = List.mapi (fun i r -> (i, r)) resolved in
|
let idx = List.mapi (fun i r -> (i, r)) resolved in
|
||||||
if !want <> None then idx
|
if !want <> None then idx
|
||||||
else
|
else
|
||||||
List.filter (fun (_, r) -> not (literal_arm r)) idx
|
let typed = List.filter (fun (_, r) -> not (literal_arm r)) idx in
|
||||||
@ List.filter (fun (_, r) -> literal_arm r) idx
|
(* A bare [None] that would be checked first has nothing to take its
|
||||||
|
type from and was always refused; it goes after the others, so it
|
||||||
|
meets their T at T? (decision 138). Only the leading ones move, so
|
||||||
|
no order that checked before changes. *)
|
||||||
|
let none_arm (_, ((a : Ast.arm), _, _)) =
|
||||||
|
match List.rev a.Ast.body with last :: _ -> is_none_lit last | [] -> false
|
||||||
|
in
|
||||||
|
let rec lead acc = function
|
||||||
|
| x :: rest when none_arm x -> lead (x :: acc) rest
|
||||||
|
| rest -> (List.rev acc, rest)
|
||||||
|
in
|
||||||
|
let nones, typed =
|
||||||
|
match lead [] typed with
|
||||||
|
| _ :: _ as nones, rest when List.length nones < List.length idx -> nones, rest
|
||||||
|
| _ -> [], typed
|
||||||
|
in
|
||||||
|
typed @ List.filter (fun (_, r) -> literal_arm r) idx @ nones
|
||||||
in
|
in
|
||||||
let checked =
|
let checked =
|
||||||
map_lr
|
map_lr
|
||||||
|
|||||||
@ -28,6 +28,16 @@ fn first(o: $u?) -> $u = o!
|
|||||||
|
|
||||||
fn wrap(x: $t) -> $t? = x
|
fn wrap(x: $t) -> $t? = x
|
||||||
|
|
||||||
|
;; A generic body's own $t handed to a $u? parameter.
|
||||||
|
fn through(x: $t) -> $t = first(x)
|
||||||
|
|
||||||
|
;; A None arm first takes its type from the arms after it.
|
||||||
|
fn arms(k: i32, x: i32) -> i32?
|
||||||
|
match k
|
||||||
|
5 -> None
|
||||||
|
4 -> x
|
||||||
|
_ -> 0
|
||||||
|
|
||||||
fn chain(a: bool, b: bool, opt: i32?) -> Option(i32?)
|
fn chain(a: bool, b: bool, opt: i32?) -> Option(i32?)
|
||||||
if a
|
if a
|
||||||
1
|
1
|
||||||
@ -50,9 +60,13 @@ fn main()
|
|||||||
;; a struct field
|
;; a struct field
|
||||||
let p = P{.a 3 .b x}
|
let p = P{.a 3 .b x}
|
||||||
println(p.a ?? 0, p.b ?? 0)
|
println(p.a ?? 0, p.b ?? 0)
|
||||||
|
p.b = 7
|
||||||
|
println(p.b ?? 0)
|
||||||
;; an array and a Vec element
|
;; an array and a Vec element
|
||||||
let xs: [3 i32?] = [1, None, x]
|
let xs: [3 i32?] = [1, None, x]
|
||||||
println(xs[0] ?? 0, xs[1] ?? 0, xs[2] ?? 0)
|
println(xs[0] ?? 0, xs[1] ?? 0, xs[2] ?? 0)
|
||||||
|
xs[1] = 5
|
||||||
|
println(xs[1] ?? 0)
|
||||||
let v: Vec(i32?) = vec-new(i32?)
|
let v: Vec(i32?) = vec-new(i32?)
|
||||||
push(v, 6)
|
push(v, 6)
|
||||||
push(v, None)
|
push(v, None)
|
||||||
@ -63,6 +77,7 @@ fn main()
|
|||||||
4 -> x
|
4 -> x
|
||||||
_ -> None
|
_ -> None
|
||||||
println(m ?? 0)
|
println(m ?? 0)
|
||||||
|
println(arms(5, 3) ?? -1, arms(4, 3) ?? -1, arms(1, 3) ?? -1)
|
||||||
;; nested: a T into a T?? is Some(Some(t)), a T? is Some of it
|
;; nested: a T into a T?? is Some(Some(t)), a T? is Some of it
|
||||||
let nn: Option(i32?) = 5
|
let nn: Option(i32?) = 5
|
||||||
let none: i32? = None
|
let none: i32? = None
|
||||||
@ -77,7 +92,7 @@ fn main()
|
|||||||
1
|
1
|
||||||
println(two(kk))
|
println(two(kk))
|
||||||
;; generics
|
;; generics
|
||||||
println(first(9), first(Some(8)), wrap(3) ?? 0)
|
println(first(9), first(Some(8)), wrap(3) ?? 0, through(5))
|
||||||
;; a narrowed name still takes a payload value
|
;; a narrowed name still takes a payload value
|
||||||
let o: i32? = Some(1)
|
let o: i32? = Some(1)
|
||||||
if o?
|
if o?
|
||||||
|
|||||||
@ -2276,8 +2276,8 @@ let () =
|
|||||||
[ ("optionals.fln", optionals_out); ("optionals-dyn.fln", optionals_dyn_out);
|
[ ("optionals.fln", optionals_out); ("optionals-dyn.fln", optionals_dyn_out);
|
||||||
(* A T where a T? is wanted is Some of it (decision 138). *)
|
(* A T where a T? is wanted is Some of it (decision 138). *)
|
||||||
("autowrap.fln",
|
("autowrap.fln",
|
||||||
"-1\n5 4 2\n7 8 -1\n3 4\n1 0 4\n2 6 0\n2 -1 -1 2\n4\nsome some some none\n\
|
"-1\n5 4 2\n7 8 -1\n3 4\n7\n1 0 4\n5\n2 6 0\n2 -1 -1 2\n4\n-1 3 0\n\
|
||||||
some some some none none\nsome some\n9 8 3\n10\n");
|
some some some none\nsome some some none none\nsome some\n9 8 3 5\n10\n");
|
||||||
(* x? tests and narrows, e? as g names what it found (decision 133). *)
|
(* x? tests and narrows, e? as g names what it found (decision 133). *)
|
||||||
("presence.fln", "true false true\n6\n-1\n3\n101 209 0\n11\n42\n2\nabsent\n6\nfalse true\n3\n6\n15\n"); ("presence-dyn.fln", "true false\n103 209 0\nno pet\nann\n3 2\n") ];
|
("presence.fln", "true false true\n6\n-1\n3\n101 209 0\n11\n42\n2\nabsent\n6\nfalse true\n3\n6\n15\n"); ("presence-dyn.fln", "true false\n103 209 0\nno pet\nann\n3 2\n") ];
|
||||||
(* x! over nothing traps at its site and names the expression. *)
|
(* x! over nothing traps at its site and names the expression. *)
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user