The unpac monorepo manager self-hosting as a monorepo using unpac
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge pull request #14388 from johnyob/ajob410@remove-let-rec-module

feat(typing)!: remove support for `let rec (module ...)`

authored by

Gabriel Scherer and committed by
GitHub
ba256b02 86f5df23

+224 -53
+3
Changes
··· 418 418 - #14331: Enforce current_level <= generic_level, and explain create_scope 419 419 (Jacques Garrigue and Takafumi Saikawa, review by Gabriel Scherer) 420 420 421 + * #14388: Remove support for `let rec (module M : S) = e1 in e2`. 422 + (Alistair O'Brien, review by Vincent Laviron and Gabriel Scherer) 423 + 421 424 ### Build system: 422 425 423 426 - #13810: Support build of cross compilers to native freestanding targets
+30 -17
testsuite/tests/typing-fstclassmod/scope_escape.ml
··· 7 7 type t 8 8 end;; 9 9 10 - let rec (module M : S) = 10 + let rec (m : (module S)) = 11 + let (module M) = m in 11 12 (module struct 12 13 type t = M.t 13 14 end : S ··· 16 17 ();; 17 18 [%%expect{| 18 19 module type S = sig type t end 19 - Lines 6-9, characters 2-22: 20 - 6 | ..(module struct 21 - 7 | type t = M.t 22 - 8 | end : S 23 - 9 | with type t = M.t) 20 + Lines 7-10, characters 2-22: 21 + 7 | ..(module struct 22 + 8 | type t = M.t 23 + 9 | end : S 24 + 10 | with type t = M.t) 25 + Error: This expression has type "(module S with type t = M.t)" 26 + but an expression was expected of type "(module S)" 27 + The type constructor "M.t" would escape its scope 28 + |}, Principal{| 29 + module type S = sig type t end 30 + Lines 7-10, characters 2-22: 31 + 7 | ..(module struct 32 + 8 | type t = M.t 33 + 9 | end : S 34 + 10 | with type t = M.t) 24 35 Error: This expression has type "(module S with type t = M.t)" 25 36 but an expression was expected of type "(module S)" 26 37 |}];; 27 38 28 39 let rec k = 40 + let (module A) = a in 29 41 let (module K : S with type t = A.t) = k in 30 42 (module struct 31 43 type t = K.t 32 44 end : S 33 45 with type t = K.t) 34 - and (module A : S) = 46 + and (a : (module S)) = 35 47 (module struct 36 48 type t = unit 37 49 ··· 40 52 in 41 53 ();; 42 54 [%%expect{| 43 - Lines 2-6, characters 2-22: 44 - 2 | ..let (module K : S with type t = A.t) = k in 45 - 3 | (module struct 46 - 4 | type t = K.t 47 - 5 | end : S 48 - 6 | with type t = K.t) 49 - Error: This expression has type "(module S with type t = A.t)" 50 - but an expression was expected of type "'a" 55 + Line 3, characters 41-42: 56 + 3 | let (module K : S with type t = A.t) = k in 57 + ^ 58 + Error: The value "k" has type "'a" but an expression was expected of type 59 + "(module S with type t = A.t)" 51 60 The type constructor "A.t" would escape its scope 52 61 |}];; 53 62 54 63 (* The locally abstract type lets us check the module's type 55 64 without scope escape. *) 56 65 let f (type a) () = 57 - let rec (module M : S with type t = a) = 66 + let rec (m : (module S with type t = a)) = 67 + let (module M) = m in 58 68 (module struct 59 69 type t = M.t 60 70 end : S with type t = M.t) 61 71 in 72 + ignore m; 62 73 () 63 74 ;; 64 75 [%%expect{| ··· 66 77 |}];; 67 78 68 79 let f (type a) () = 69 - let rec (module M : S with type t = a) = 80 + let rec (m : (module S with type t = a)) = 81 + let (module M) = m in 70 82 (module struct 71 83 type t = M.t 72 84 end : S with type t = a) 73 85 in 86 + ignore m; 74 87 ();; 75 88 [%%expect{| 76 89 val f : unit -> unit = <fun>
-25
testsuite/tests/typing-gadts/unexpected_existentials.ml
··· 30 30 31 31 32 32 let () = 33 - let rec Any x = Any () in 34 - () 35 - [%%expect {| 36 - Line 2, characters 10-15: 37 - 2 | let rec Any x = Any () in 38 - ^^^^^ 39 - Error: Existential types are not allowed in recursive bindings, 40 - but the constructor "Any" introduces existential types. 41 - |}] 42 - 43 - 44 - let () = 45 33 let[@attribute] Any x = Any () in 46 34 () 47 35 [%%expect {| ··· 105 93 Error: Existential types are not allowed in grouped ("let ... and ...") bindings, 106 94 but the constructor "Any" introduces existential types. 107 95 |}] 108 - 109 - 110 - let () = 111 - let rec Any x = Any () in 112 - () 113 - [%%expect {| 114 - Line 2, characters 10-15: 115 - 2 | let rec Any x = Any () in 116 - ^^^^^ 117 - Error: Existential types are not allowed in recursive bindings, 118 - but the constructor "Any" introduces existential types. 119 - |}] 120 - 121 96 122 97 let () = 123 98 let[@attribute] Any x = Any () in
+9 -4
testsuite/tests/typing-implicit_unpack/implicit_unpack.ml
··· 169 169 |}];; 170 170 171 171 (* Even works with recursion, but must be fully explicit *) 172 - let rec (module M : S') = 173 - (module struct let f n = if n <= 0 then 1 else n * M.f (n-1) end : S') 174 - in M.f 3;; 172 + let rec (m : (module S')) = 173 + let (module M) = m in 174 + (module struct 175 + let f n = if n <= 0 then 1 else n * M.f (n - 1) 176 + end : S') 177 + in 178 + let (module M) = m in 179 + M.f 3 175 180 [%%expect{| 176 181 - : int = 6 177 - |}];; 182 + |}] 178 183 179 184 (* Subtyping *) 180 185
+150
testsuite/tests/typing-misc/let_rec_pat.ml
··· 1 + (* TEST 2 + expect; 3 + *) 4 + 5 + (* This series of tests checks the pattern validation for [let rec] bindings. 6 + Only "variable-like" patterns are allowed. See [is_var_pat] for details. *) 7 + 8 + (* Valid patterns *) 9 + 10 + let rec x = 1 in x 11 + [%%expect{| 12 + - : int = 1 13 + |}];; 14 + 15 + let rec (x : int) = 1 in x 16 + [%%expect{| 17 + - : int = 1 18 + |}];; 19 + 20 + let rec ((x : int) : int) = 1 in x 21 + [%%expect{| 22 + - : int = 1 23 + |}];; 24 + 25 + module M = struct type t = int end;; 26 + let rec M.((x : t)) = 1 in x 27 + [%%expect{| 28 + module M : sig type t = int end 29 + - : M.t = 1 30 + |}];; 31 + 32 + (* Invalid patterns *) 33 + 34 + let rec _ = 1 in () 35 + [%%expect{| 36 + Line 1, characters 8-9: 37 + 1 | let rec _ = 1 in () 38 + ^ 39 + Error: Only variables are allowed as left-hand side of "let rec" 40 + |}];; 41 + 42 + let rec (x as y) = 1 in x 43 + [%%expect{| 44 + Line 1, characters 8-16: 45 + 1 | let rec (x as y) = 1 in x 46 + ^^^^^^^^ 47 + Error: Only variables are allowed as left-hand side of "let rec" 48 + |}];; 49 + 50 + let rec 42 = 42 in () 51 + [%%expect{| 52 + Line 1, characters 8-10: 53 + 1 | let rec 42 = 42 in () 54 + ^^ 55 + Error: Only variables are allowed as left-hand side of "let rec" 56 + |}];; 57 + 58 + let rec (x, y) = (1, 2) in x 59 + [%%expect{| 60 + Line 1, characters 8-14: 61 + 1 | let rec (x, y) = (1, 2) in x 62 + ^^^^^^ 63 + Error: Only variables are allowed as left-hand side of "let rec" 64 + |}];; 65 + 66 + let rec Some x = Some 1 in x 67 + [%%expect{| 68 + Line 1, characters 8-14: 69 + 1 | let rec Some x = Some 1 in x 70 + ^^^^^^ 71 + Error: Only variables are allowed as left-hand side of "let rec" 72 + |}];; 73 + 74 + type r = { a : int; b : int };; 75 + let rec { a; b } = { a = 1; b = 2 } in a 76 + [%%expect{| 77 + type r = { a : int; b : int; } 78 + Line 2, characters 8-16: 79 + 2 | let rec { a; b } = { a = 1; b = 2 } in a 80 + ^^^^^^^^ 81 + Error: Only variables are allowed as left-hand side of "let rec" 82 + |}];; 83 + 84 + let rec [| x |] = [| 1 |] in x 85 + [%%expect{| 86 + Line 1, characters 8-15: 87 + 1 | let rec [| x |] = [| 1 |] in x 88 + ^^^^^^^ 89 + Error: Only variables are allowed as left-hand side of "let rec" 90 + |}];; 91 + 92 + let rec (Some x | None as x) = None in () 93 + [%%expect{| 94 + Line 1, characters 8-28: 95 + 1 | let rec (Some x | None as x) = None in () 96 + ^^^^^^^^^^^^^^^^^^^^ 97 + Error: Only variables are allowed as left-hand side of "let rec" 98 + |}];; 99 + 100 + let rec lazy x = lazy 1 in x 101 + [%%expect{| 102 + Line 1, characters 8-14: 103 + 1 | let rec lazy x = lazy 1 in x 104 + ^^^^^^ 105 + Error: Only variables are allowed as left-hand side of "let rec" 106 + |}];; 107 + 108 + module type S = sig val f : int -> int end;; 109 + let rec (module M : S) = (module struct let f n = if n <= 0 then 1 else n * M.f (n - 1) end : S) in M.f 5 110 + [%%expect{| 111 + module type S = sig val f : int -> int end 112 + Line 2, characters 8-22: 113 + 2 | let rec (module M : S) = (module struct let f n = if n <= 0 then 1 else n * M.f (n - 1) end : S) in M.f 5 114 + ^^^^^^^^^^^^^^ 115 + Error: Only variables are allowed as left-hand side of "let rec" 116 + |}];; 117 + 118 + type t = [ `A ];; 119 + let rec #t = `A in () 120 + [%%expect{| 121 + type t = [ `A ] 122 + Line 2, characters 8-10: 123 + 2 | let rec #t = `A in () 124 + ^^ 125 + Error: Only variables are allowed as left-hand side of "let rec" 126 + |}];; 127 + 128 + let rec ((x, y) : int * int) = (1, 2) in x 129 + [%%expect{| 130 + Line 1, characters 8-28: 131 + 1 | let rec ((x, y) : int * int) = (1, 2) in x 132 + ^^^^^^^^^^^^^^^^^^^^ 133 + Error: Only variables are allowed as left-hand side of "let rec" 134 + |}];; 135 + 136 + let rec M.(Some (x : t)) = Some 1 in x 137 + [%%expect{| 138 + Line 1, characters 8-24: 139 + 1 | let rec M.(Some (x : t)) = Some 1 in x 140 + ^^^^^^^^^^^^^^^^ 141 + Error: Only variables are allowed as left-hand side of "let rec" 142 + |}];; 143 + 144 + let rec x = a and (a, b) = (1, 2) in x 145 + [%%expect{| 146 + Line 1, characters 18-24: 147 + 1 | let rec x = a and (a, b) = (1, 2) in x 148 + ^^^^^^ 149 + Error: Only variables are allowed as left-hand side of "let rec" 150 + |}];;
+32 -7
typing/typecore.ml
··· 3668 3668 | Tpat_construct (_, cd, _, _) when cd.cstr_generalized -> true 3669 3669 | _ -> false } p 3670 3670 3671 + 3672 + (* When typing [let rec p = e ...], we require [p] to be "variable-like": 3673 + it must consists of a single variable [x], optionally wrapped in 3674 + erasable pattern constructs (e.g. annotations, local opens) *) 3675 + let rec is_var_pat p = 3676 + match p.ppat_desc with 3677 + | Ppat_var _ -> true 3678 + | Ppat_constraint (p, _) 3679 + | Ppat_open (_, p) -> is_var_pat p 3680 + | Ppat_any 3681 + | Ppat_alias _ 3682 + | Ppat_constant _ 3683 + | Ppat_interval _ 3684 + | Ppat_tuple _ 3685 + | Ppat_construct _ 3686 + | Ppat_variant _ 3687 + | Ppat_record _ 3688 + | Ppat_array _ 3689 + | Ppat_or _ 3690 + | Ppat_type _ 3691 + | Ppat_lazy _ 3692 + | Ppat_unpack _ 3693 + | Ppat_exception _ 3694 + | Ppat_effect _ 3695 + | Ppat_extension _ -> false 3696 + 3671 3697 (* There are various things that we need to do in presence of GADT constructors 3672 3698 that aren't required if there are none. 3673 3699 However, because of disambiguation, we can't know for sure whether the ··· 6578 6604 let spatl = List.map vb_pat_constraint spat_sexp_list in 6579 6605 let attrs_list = List.map fst spatl in 6580 6606 let is_recursive = (rec_flag = Recursive) in 6581 - 6607 + if is_recursive then 6608 + List.iter 6609 + (fun { pvb_pat = pat; _ } -> 6610 + if not (is_var_pat pat) 6611 + then raise (Error (pat.ppat_loc, env, Illegal_letrec_pat))) 6612 + spat_sexp_list; 6582 6613 let (pat_list, exp_list, new_env, mvs) = 6583 6614 with_local_level_generalize begin fun () -> 6584 6615 if existential_context = At_toplevel then Typetexp.TyVarEnv.reset (); ··· 6702 6733 }) 6703 6734 l spat_sexp_list 6704 6735 in 6705 - if is_recursive then 6706 - List.iter 6707 - (fun {vb_pat=pat} -> match pat.pat_desc with 6708 - Tpat_var _ -> () 6709 - | _ -> raise(Error(pat.pat_loc, env, Illegal_letrec_pat))) 6710 - l; 6711 6736 List.iter (fun vb -> 6712 6737 if pattern_needs_partial_application_check vb.vb_pat then 6713 6738 check_partial_application ~statement:false vb.vb_expr