ocaml/testsuite/tests/letrec-check/basic.ml

326 lines
6.9 KiB
OCaml

(* TEST
* expect
*)
let rec x = (x; ());;
[%%expect{|
val x : unit = ()
|}];;
let rec x = "x";;
[%%expect{|
val x : string = "x"
|}];;
let rec x = let x = () in x;;
[%%expect{|
val x : unit = ()
|}];;
let rec x = let y = (x; ()) in y;;
[%%expect{|
val x : unit = ()
|}];;
let rec x = let y = () in x;;
[%%expect{|
Line 1, characters 12-27:
let rec x = let y = () in x;;
^^^^^^^^^^^^^^^
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
let rec x = [y]
and y = let x = () in x;;
[%%expect{|
val x : unit list = [()]
val y : unit = ()
|}];;
let rec x = [y]
and y = let rec x = () in x;;
[%%expect{|
val x : unit list = [()]
val y : unit = ()
|}];;
let rec x =
let a = x in
fun () -> a ()
and y =
[x];;
[%%expect{|
val x : unit -> 'a = <fun>
val y : (unit -> 'a) list = [<fun>]
|}];;
let rec x = [|y|] and y = 0;;
[%%expect{|
val x : int array = [|0|]
val y : int = 0
|}];;
let rec x = (y, y)
and y = fun () -> ignore x;;
[%%expect{|
val x : (unit -> unit) * (unit -> unit) = (<fun>, <fun>)
val y : unit -> unit = <fun>
|}];;
let rec x = Some y
and y = fun () -> ignore x
;;
[%%expect{|
val x : (unit -> unit) option = Some <fun>
val y : unit -> unit = <fun>
|}];;
let rec x = ignore x;;
[%%expect{|
Line 1, characters 12-20:
let rec x = ignore x;;
^^^^^^^^
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
let rec x = y 0 and y _ = ();;
[%%expect{|
Line 1, characters 12-15:
let rec x = y 0 and y _ = ();;
^^^
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
let rec b = if b then true else false;;
[%%expect{|
Line 1, characters 12-37:
let rec b = if b then true else false;;
^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
let rec x = function
Some _ -> ignore (y [])
| None -> ignore (y [])
and y = function
[] -> ignore (x None)
| _ :: _ -> ignore (x None)
;;
[%%expect{|
val x : 'a option -> unit = <fun>
val y : 'a list -> unit = <fun>
|}];;
let rec x = { x with contents = 3 } [@ocaml.warning "-23"];;
[%%expect{|
val x : int ref = {contents = 3}
|}];;
let rec c = { c with Complex.re = 1.0 };;
[%%expect{|
Line 1, characters 12-39:
let rec c = { c with Complex.re = 1.0 };;
^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
let rec x = `A y
and y = fun () -> ignore x
;;
[%%expect{|
val x : [> `A of unit -> unit ] = `A <fun>
val y : unit -> unit = <fun>
|}];;
let rec x = { contents = y }
and y = fun () -> ignore x;;
[%%expect{|
val x : (unit -> unit) ref = {contents = <fun>}
val y : unit -> unit = <fun>
|}];;
let r = ref (fun () -> ())
let rec x = fun () -> r := x;;
[%%expect{|
val r : (unit -> unit) ref = {contents = <fun>}
val x : unit -> unit = <fun>
|}];;
let rec x = fun () -> y.contents and y = { contents = 3 };;
[%%expect{|
val x : unit -> int = <fun>
val y : int ref = {contents = 3}
|}];;
let r = ref ()
let rec x = r := x;;
[%%expect{|
val r : unit ref = {contents = ()}
Line 2, characters 12-18:
let rec x = r := x;;
^^^^^^
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
let rec x =
for i = 0 to 1 do
let z = y in ignore z
done
and y = x; ();;
[%%expect{|
Line 2, characters 2-52:
..for i = 0 to 1 do
let z = y in ignore z
done
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
let rec x =
for i = 0 to y do
()
done
and y = 10;;
[%%expect{|
Line 2, characters 2-33:
..for i = 0 to y do
()
done
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
let rec x =
for i = y to 10 do
()
done
and y = 0;;
[%%expect{|
Line 2, characters 2-34:
..for i = y to 10 do
()
done
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
let rec x =
while false do
let y = x in ignore y
done
and y = x; ();;
[%%expect{|
Line 2, characters 2-49:
..while false do
let y = x in ignore y
done
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
let rec x =
while y do
()
done
and y = false;;
[%%expect{|
Line 2, characters 2-26:
..while y do
()
done
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
let rec x =
while y do
let y = x in ignore y
done
and y = false;;
[%%expect{|
Line 2, characters 2-45:
..while y do
let y = x in ignore y
done
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
let rec x = y.contents and y = { contents = 3 };;
[%%expect{|
Line 1, characters 12-22:
let rec x = y.contents and y = { contents = 3 };;
^^^^^^^^^^
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
let rec x = assert y and y = true;;
[%%expect{|
Line 1, characters 12-20:
let rec x = assert y and y = true;;
^^^^^^^^
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
(* Recursively constructing arrays of known non-float type is permitted *)
let rec deep_cycle : [`Tuple of [`Shared of 'a] array] as 'a
= `Tuple [| `Shared deep_cycle |];;
[%%expect{|
val deep_cycle : [ `Tuple of [ `Shared of 'a ] array ] as 'a =
`Tuple [|`Shared <cycle>|]
|}];;
(* Constructing float arrays was disallowed altogether at one point
by an overzealous check. Constructing float arrays in recursive
bindings is fine when they don't partake in the recursion. *)
let rec _x = let _ = [| 1.0 |] in 1. in ();;
[%%expect{|
- : unit = ()
|}];;
(* The builtin Stdlib.ref is currently treated as a constructor.
Other functions of the same name should not be so treated. *)
let _ =
let module Stdlib =
struct
let ref _ = assert false
end in
let rec x = Stdlib.ref y
and y = fun () -> ignore x
in (x, y)
;;
[%%expect{|
Line 6, characters 14-26:
let rec x = Stdlib.ref y
^^^^^^^^^^^^
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
(* An example, from Leo White, of let rec bindings that allocate
values of unknown size *)
let foo p x =
let rec f =
if p then (fun y -> x + g y) else (fun y -> g y)
and g =
if not p then (fun y -> x - f y) else (fun y -> f y)
in
(f, g)
;;
[%%expect{|
Line 3, characters 4-52:
if p then (fun y -> x + g y) else (fun y -> g y)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;
let rec x =
match let _ = y in raise Not_found with
_ -> "x"
| exception Not_found -> "z"
and y = match x with
z -> ("y", z);;
[%%expect{|
Line 2, characters 2-85:
..match let _ = y in raise Not_found with
_ -> "x"
| exception Not_found -> "z"
Error: This kind of expression is not allowed as right-hand side of `let rec'
|}];;