Skip to content

Commit

Permalink
resurrect half of the Bad_fixed_type error
Browse files Browse the repository at this point in the history
but make the error message much more explicit
about what is happening.
  • Loading branch information
Octachron committed Nov 8, 2019
1 parent 58f76d4 commit 6a3f672
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 4 deletions.
52 changes: 52 additions & 0 deletions testsuite/tests/typing-private/invalid_private_row.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
(* TEST
* expect
*)

(** Error message for trying to make private a row type variable
that only exists syntactically *)

type a = [`A | `C | `D]
type b = [`B | `D | `E]
type c = private [< a | b > `A `B `C `D `E]
[%%expect {|
type a = [ `A | `C | `D ]
type b = [ `B | `D | `E ]
Line 6, characters 0-43:
6 | type c = private [< a | b > `A `B `C `D `E]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This private row type declaration is invalid.
The type expression on the right-hand side reduces to
[ `A | `B | `C | `D | `E ]
which does not have a free row type variable.
Hint: If you intended to define a private type abbreviation,
write explicitly
private [ `A | `B | `C | `D | `E ]
|}]

type u = private < x:int; .. > as 'a constraint 'a = < x: int > ;;
[%%expect {|
Line 1, characters 0-63:
1 | type u = private < x:int; .. > as 'a constraint 'a = < x: int > ;;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This private row type declaration is invalid.
The type expression on the right-hand side reduces to
< x : int >
which does not have a free row type variable.
Hint: If you intended to define a private type abbreviation,
write explicitly
private < x : int >
|}]

type u = private [> `A ] as 'a constraint 'a = [< `A ] ;;
[%%expect {|
Line 1, characters 0-54:
1 | type u = private [> `A ] as 'a constraint 'a = [< `A ] ;;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Error: This private row type declaration is invalid.
The type expression on the right-hand side reduces to
[ `A ]
which does not have a free row type variable.
Hint: If you intended to define a private type abbreviation,
write explicitly
private [ `A ]
|}]
27 changes: 23 additions & 4 deletions typing/typedecl.ml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ type error =
| Wrong_unboxed_type_float
| Boxed_and_unboxed
| Nonrec_gadt
| Invalid_private_row_declaration of type_expr

open Typedtree

Expand Down Expand Up @@ -164,7 +165,7 @@ let is_fixed_type sd =

(* Set the row variable in a fixed type. Require
[is_fixed_type decl] as a precondition *)
let set_fixed_row env p decl =
let set_fixed_row env p loc decl =
let tm =
match decl.type_manifest with
None -> assert false
Expand All @@ -174,10 +175,19 @@ let set_fixed_row env p decl =
match tm.desc with
Tvariant row ->
let row = Btype.row_repr row in
if Btype.static_row row then
(* the syntax hinted to the existence of a row variable,
but there are in fact no row variable to make private, e.g.
[ type t = private [< `A > `A] ] *)
raise (Error(loc, Invalid_private_row_declaration tm));
tm.desc <- Tvariant {row with row_fixed = Some Fixed_private};
row.row_more
| Tobject (ty, _) ->
snd (Ctype.flatten_fields ty)
let r = snd (Ctype.flatten_fields ty) in
if not (Btype.is_Tvar r) then
(* a syntactically open object was closed by a later constraint *)
raise (Error(loc, Invalid_private_row_declaration tm));
r
| _ -> assert false
in
rv.desc <- Tconstr (p, decl.type_params, ref Mnil)
Expand Down Expand Up @@ -516,7 +526,7 @@ let transl_declaration env sdecl id =
(Longident.Lident(Ident.name id ^ "#row")) env
with Not_found -> assert false
in
set_fixed_row env p decl
set_fixed_row env p sdecl.ptype_loc decl
end;
(* Check for cyclic abbreviations *)
begin match decl.type_manifest with None -> ()
Expand Down Expand Up @@ -1507,7 +1517,8 @@ let transl_with_constraint env id ?fixed_row_path orig_decl sdecl =
type_unboxed;
}
in
Option.iter (fun p -> set_fixed_row env p decl) fixed_row_path;
Option.iter (fun p -> set_fixed_row env p sdecl.ptype_loc decl)
fixed_row_path;
begin match Ctype.closed_type_decl decl with None -> ()
| Some ty -> raise(Error(sdecl.ptype_loc, Unbound_type_var(ty,decl)))
end;
Expand Down Expand Up @@ -1856,6 +1867,14 @@ let report_error ppf = function
| Nonrec_gadt ->
fprintf ppf
"@[GADT case syntax cannot be used in a 'nonrec' block.@]"
| Invalid_private_row_declaration ty ->
Format.fprintf ppf
"@[<hv>This private row type declaration is invalid.@ \
The type expression on the right-hand side reduces to@;<1 2>%a@ \
which does not have a free row type variable.@]@,\
@[<hv>@[Hint: If you intended to define a private type abbreviation,@ \
write explicitly@]@;<1 2>private %a@]"
Printtyp.type_expr ty Printtyp.type_expr ty

let () =
Location.register_error_of_exn
Expand Down
1 change: 1 addition & 0 deletions typing/typedecl.mli
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ type error =
| Wrong_unboxed_type_float
| Boxed_and_unboxed
| Nonrec_gadt
| Invalid_private_row_declaration of type_expr

exception Error of Location.t * error

Expand Down

0 comments on commit 6a3f672

Please sign in to comment.