Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
22ab286
migrate wip
zth Aug 24, 2025
a151b5e
wip migrate
zth Aug 25, 2025
f4016a9
pipe chain example
zth Aug 25, 2025
86e2d21
migrations for Js_option
zth Aug 28, 2025
c9bd01c
migrations for Js_null
zth Aug 28, 2025
0d6e631
rename migration template for pipe chains
zth Aug 28, 2025
35eeb19
migrations for Js_null_undefined
zth Aug 28, 2025
11407a1
js_float migrations
zth Aug 28, 2025
7be3461
Js_int migrations
zth Aug 28, 2025
4ca31f7
format
zth Aug 28, 2025
b9c14bf
dict migrations
zth Aug 28, 2025
8b46d23
migrations for Js_date
zth Aug 29, 2025
6f23477
migrations for Js_re
zth Aug 29, 2025
5a35bb9
migrations for Js_math
zth Aug 29, 2025
1955bf8
one more test
zth Aug 29, 2025
865e9e5
migrations for js_undefined
zth Aug 30, 2025
7df7cec
deprecate Js_OO
zth Aug 30, 2025
4511313
migrations for Js_extern
zth Aug 30, 2025
1c9497c
migrations for Js_global
zth Aug 30, 2025
3b89ae1
migrations for Js_obj
zth Aug 30, 2025
6d9c817
make parsing of @deprecated with migration info an experimental feature
zth Aug 30, 2025
74405a7
Revert "make parsing of @deprecated with migration info an experiment…
zth Aug 31, 2025
c811257
typed array migrations
zth Aug 31, 2025
3d1f924
format
zth Aug 31, 2025
c86e3b3
support replacing types
zth Aug 31, 2025
4cf2a73
more type replacement migrations
zth Aug 31, 2025
e076439
support @apply.transforms for applying transforms, and add migrations…
zth Aug 31, 2025
22157ff
refactor a bit and add transform for dropping unit args in apply
zth Aug 31, 2025
3b4a909
refactor
zth Aug 31, 2025
e7c6e1f
finish js_json migration
zth Sep 1, 2025
210f276
more migrations
zth Sep 1, 2025
c22c54b
remove unused Match template
zth Sep 1, 2025
c474077
more migrations
zth Sep 4, 2025
ef53158
update test fixtures
zth Sep 4, 2025
7deb03a
update test fixtures
zth Sep 4, 2025
33e1b29
more fixtures
zth Sep 4, 2025
b7d8f1f
remove
zth Sep 4, 2025
2a8f562
more
zth Sep 4, 2025
fb7bc7f
more
zth Sep 4, 2025
5b7d723
migrate .resi files as well
zth Sep 4, 2025
75ec80d
fix resi
zth Sep 4, 2025
f5d2d8c
migrate-all command
zth Sep 12, 2025
743d636
more migrations
zth Sep 12, 2025
8cc3c0e
migrations for Exn
zth Sep 12, 2025
a6de19d
change migrate summary
zth Sep 12, 2025
a3acab0
oops, test file
zth Sep 12, 2025
42242a4
proper interfaces for Js Promise modules, so they can have migrations
zth Sep 12, 2025
0f54714
format
zth Sep 12, 2025
af7459e
more migration fixes
zth Sep 13, 2025
aaa17dd
more migration fix
zth Sep 13, 2025
9203c68
get rid of some warning output
zth Sep 13, 2025
7674b50
update artifacts list
zth Sep 14, 2025
75554f3
spec
zth Sep 25, 2025
3f74930
more migrations
zth Sep 25, 2025
8ae6340
more migrations
zth Sep 25, 2025
b69aa6c
analysis output
zth Sep 25, 2025
e8331b8
remove redundant stuff in migration templates
zth Sep 25, 2025
8636091
bool migration
zth Sep 25, 2025
94b9a75
more migrations
zth Sep 25, 2025
5b3c6d1
fix changelog
zth Sep 25, 2025
c160a71
remove changelog entry
zth Oct 6, 2025
b71abc1
updates after merge
zth Oct 6, 2025
bd23e6f
message about automatic migrations
zth Oct 6, 2025
2b81e1d
updated analysis output
zth Oct 6, 2025
8ea5696
tweak message
zth Oct 6, 2025
062cc1a
fix subcommand
zth Oct 6, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
14 changes: 14 additions & 0 deletions analysis/src/Cmt.ml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,17 @@ let fullsFromModule ~package ~moduleName =
let loadFullCmtFromPath ~path =
let uri = Uri.fromPath path in
fullFromUri ~uri

let loadCmtInfosFromPath ~path =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are infos new here?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, since we don't need to process the CMT as we do in analysis, this just loads the CMT and accesses the new prop.

let uri = Uri.fromPath path in
match Packages.getPackage ~uri with
| None -> None
| Some package -> (
let moduleName =
BuildSystem.namespacedName package.namespace (FindFiles.getName path)
in
match Hashtbl.find_opt package.pathsForModule moduleName with
| Some paths ->
let cmt = getCmtPath ~uri paths in
Shared.tryReadCmt cmt
| None -> None)
2 changes: 1 addition & 1 deletion compiler/bsb/bsb_package_specs.ml
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ let supported_format (x : string) loc : Ext_module_system.t =
{loc with Lexing.pos_cnum = loc.Lexing.pos_cnum + String.length x}
in
let loc = {Warnings.loc_start = loc; loc_end; loc_ghost = false} in
Location.deprecated loc
Location.deprecated ~can_be_automigrated:false loc
(Printf.sprintf "Option \"%s\" is deprecated. Use \"%s\" instead." x
Literals.esmodule)
in
Expand Down
4 changes: 4 additions & 0 deletions compiler/ext/ext_list.ml
Original file line number Diff line number Diff line change
Expand Up @@ -774,3 +774,7 @@ let filter lst p =
| x :: l -> if p x then find (x :: accu) l ~p else find accu l ~p
in
find [] lst ~p

let is_empty = function
| [] -> true
| _ :: _ -> false
2 changes: 2 additions & 0 deletions compiler/ext/ext_list.mli
Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,5 @@ val filter : 'a list -> ('a -> bool) -> 'a list

val array_list_filter_map :
'a array -> 'b list -> ('a -> 'b -> 'c option) -> 'c list

val is_empty : 'a list -> bool
14 changes: 11 additions & 3 deletions compiler/ext/warnings.ml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ type top_level_unit_help = FunctionCall | Other
type t =
| Comment_start (* 1 *)
| Comment_not_end (* 2 *)
| Deprecated of string * loc * loc (* 3 *)
| Deprecated of string * loc * loc * bool (* 3 *)
| Fragile_match of string (* 4 *)
| Partial_application (* 5 *)
| Method_override of string list (* 7 *)
Expand Down Expand Up @@ -299,14 +299,22 @@ let () = reset ()
let message = function
| Comment_start -> "this is the start of a comment."
| Comment_not_end -> "this is not the end of a comment."
| Deprecated (s, _, _) ->
| Deprecated (s, _, _, can_be_automigrated) ->
(* Reduce \r\n to \n:
- Prevents any \r characters being printed on Unix when processing
Windows sources
- Prevents \r\r\n being generated on Windows, which affects the
testsuite
*)
"deprecated: " ^ Misc.normalise_eol s
^
if can_be_automigrated then
"\n\n\
\ This can be automatically migrated by the ReScript migration tool. \
Run `rescript-tools migrate-all <project-root>` to run all automatic \
migrations available in your project, or `rescript-tools migrate \
<file>` to migrate a single file."
else ""
| Fragile_match "" -> "this pattern-matching is fragile."
| Fragile_match s ->
"this pattern-matching is fragile.\n\
Expand Down Expand Up @@ -533,7 +541,7 @@ let message = function
you implement this before running the code."

let sub_locs = function
| Deprecated (_, def, use) ->
| Deprecated (_, def, use, _) ->
[(def, "Definition"); (use, "Expected signature")]
| _ -> []

Expand Down
2 changes: 1 addition & 1 deletion compiler/ext/warnings.mli
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ type top_level_unit_help = FunctionCall | Other
type t =
| Comment_start (* 1 *)
| Comment_not_end (* 2 *)
| Deprecated of string * loc * loc (* 3 *)
| Deprecated of string * loc * loc * bool (* 3 *)
| Fragile_match of string (* 4 *)
| Partial_application (* 5 *)
| Method_override of string list (* 7 *)
Expand Down
60 changes: 57 additions & 3 deletions compiler/ml/builtin_attributes.ml
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,64 @@ let rec deprecated_of_attrs = function
Some (string_of_opt_payload p)
| _ :: tl -> deprecated_of_attrs tl

let check_deprecated loc attrs s =
match deprecated_of_attrs attrs with
let rec deprecated_of_attrs_with_migrate = function
| [] -> None
| ( {txt = "deprecated"; _},
PStr [{pstr_desc = Pstr_eval ({pexp_desc = Pexp_record (fields, _)}, _)}]
)
:: _ -> (
let reason =
fields
|> List.find_map (fun field ->
match field with
| {
lid = {txt = Lident "reason"};
x = {pexp_desc = Pexp_constant (Pconst_string (reason, _))};
} ->
Some reason
| _ -> None)
in
let migration_template =
fields
|> List.find_map (fun field ->
match field with
| {lid = {txt = Lident "migrate"}; x = migration_template} ->
Some migration_template
| _ -> None)
in
let migration_in_pipe_chain_template =
fields
|> List.find_map (fun field ->
match field with
| {
lid = {txt = Lident "migrateInPipeChain"};
x = migration_in_pipe_chain_template;
} ->
Some migration_in_pipe_chain_template
| _ -> None)
in

(* TODO: Validate and error if expected shape mismatches *)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll leave this in for now, and do proper errors and validations if/when we decide this should be a first class feature in the language itself. For now it's just an internal migration tool for the library (although anyone can use it of course, at their own risk).

match reason with
| Some reason ->
Some (reason, migration_template, migration_in_pipe_chain_template)
| None -> None)
| ({txt = "ocaml.deprecated" | "deprecated"; _}, p) :: _ ->
Some (string_of_opt_payload p, None, None)
| _ :: tl -> deprecated_of_attrs_with_migrate tl

let check_deprecated ?deprecated_context loc attrs s =
match deprecated_of_attrs_with_migrate attrs with
| None -> ()
| Some txt -> Location.deprecated loc (cat s txt)
| Some (txt, migration_template, migration_in_pipe_chain_template) ->
!Cmt_utils.record_deprecated_used
?deprecated_context ?migration_template ?migration_in_pipe_chain_template
loc txt;
Location.deprecated
~can_be_automigrated:
(Option.is_some migration_template
|| Option.is_some migration_in_pipe_chain_template)
loc (cat s txt)

let check_deprecated_inclusion ~def ~use loc attrs1 attrs2 s =
match (deprecated_of_attrs attrs1, deprecated_of_attrs attrs2) with
Expand Down
7 changes: 6 additions & 1 deletion compiler/ml/builtin_attributes.mli
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,12 @@
ocaml.boxed / ocaml.unboxed
*)

val check_deprecated : Location.t -> Parsetree.attributes -> string -> unit
val check_deprecated :
?deprecated_context:Cmt_utils.deprecated_used_context ->
Location.t ->
Parsetree.attributes ->
string ->
unit
val check_deprecated_inclusion :
def:Location.t ->
use:Location.t ->
Expand Down
21 changes: 19 additions & 2 deletions compiler/ml/cmt_format.ml
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ type cmt_infos = {
cmt_imports : (string * Digest.t option) list;
cmt_interface_digest : Digest.t option;
cmt_use_summaries : bool;
cmt_extra_info: Cmt_utils.cmt_extra_info;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK yes they are new

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Eventually I think I want to move this to a separate sidecar file, probably the one I've added in the Actions PR. But for now (and maybe always) it can live in here, since it has minimal impact.

}

type error =
Expand Down Expand Up @@ -154,15 +155,30 @@ let read_cmi filename =

let saved_types = ref []
let value_deps = ref []
let deprecated_used = ref []

let clear () =
saved_types := [];
value_deps := []
value_deps := [];
deprecated_used := []

let add_saved_type b = saved_types := b :: !saved_types
let get_saved_types () = !saved_types
let set_saved_types l = saved_types := l

let record_deprecated_used ?deprecated_context ?migration_template ?migration_in_pipe_chain_template source_loc deprecated_text =
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

are these going to be reversed at some point?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reversed?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reversed?

It's constructed backwards

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I still don't follow 😄

deprecated_used :=
{
Cmt_utils.source_loc;
deprecated_text;
migration_template;
migration_in_pipe_chain_template;
context = deprecated_context;
}
:: !deprecated_used

let _ = Cmt_utils.record_deprecated_used := record_deprecated_used

let record_value_dependency vd1 vd2 =
if vd1.Types.val_loc <> vd2.Types.val_loc then
value_deps := (vd1, vd2) :: !value_deps
Expand Down Expand Up @@ -197,8 +213,9 @@ let save_cmt filename modname binary_annots sourcefile initial_env cmi =
cmt_imports = List.sort compare (Env.imports ());
cmt_interface_digest = this_crc;
cmt_use_summaries = need_to_clear_env;
cmt_extra_info = {deprecated_used = !deprecated_used};
} in
output_cmt oc cmt)
end;
clear ()
#endif
#endif
9 changes: 9 additions & 0 deletions compiler/ml/cmt_format.mli
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ type cmt_infos = {
cmt_imports: (string * Digest.t option) list;
cmt_interface_digest: Digest.t option;
cmt_use_summaries: bool;
cmt_extra_info: Cmt_utils.cmt_extra_info;
}

type error = Not_a_typedtree of string
Expand Down Expand Up @@ -111,6 +112,14 @@ val set_saved_types : binary_part list -> unit
val record_value_dependency :
Types.value_description -> Types.value_description -> unit

val record_deprecated_used :
?deprecated_context:Cmt_utils.deprecated_used_context ->
?migration_template:Parsetree.expression ->
?migration_in_pipe_chain_template:Parsetree.expression ->
Location.t ->
string ->
unit

(*

val is_magic_number : string -> bool
Expand Down
31 changes: 31 additions & 0 deletions compiler/ml/cmt_utils.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
type deprecated_used_context = FunctionCall | Reference

type deprecated_used = {
source_loc: Location.t;
deprecated_text: string;
migration_template: Parsetree.expression option;
migration_in_pipe_chain_template: Parsetree.expression option;
context: deprecated_used_context option;
}

type cmt_extra_info = {deprecated_used: deprecated_used list}

let record_deprecated_used :
(?deprecated_context:deprecated_used_context ->
?migration_template:Parsetree.expression ->
?migration_in_pipe_chain_template:Parsetree.expression ->
Location.t ->
string ->
unit)
ref =
ref
(fun
?deprecated_context
?migration_template
?migration_in_pipe_chain_template
_
_
->
ignore deprecated_context;
ignore migration_template;
ignore migration_in_pipe_chain_template)
5 changes: 3 additions & 2 deletions compiler/ml/location.ml
Original file line number Diff line number Diff line change
Expand Up @@ -298,7 +298,8 @@ let raise_errorf ?(loc = none) ?(sub = []) ?(if_highlight = "") =
pp_ksprintf ~before:print_phanton_error_prefix (fun msg ->
raise (Error {loc; msg; sub; if_highlight}))

let deprecated ?(def = none) ?(use = none) loc msg =
prerr_warning loc (Warnings.Deprecated (msg, def, use))
let deprecated ?(can_be_automigrated = false) ?(def = none) ?(use = none) loc
msg =
prerr_warning loc (Warnings.Deprecated (msg, def, use, can_be_automigrated))

let map_loc f {txt; loc} = {txt = f txt; loc}
3 changes: 2 additions & 1 deletion compiler/ml/location.mli
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ val default_error_reporter :
val report_exception : formatter -> exn -> unit
(** Reraise the exception if it is unknown. *)

val deprecated : ?def:t -> ?use:t -> t -> string -> unit
val deprecated :
?can_be_automigrated:bool -> ?def:t -> ?use:t -> t -> string -> unit

val map_loc : ('a -> 'b) -> 'a loc -> 'b loc
27 changes: 19 additions & 8 deletions compiler/ml/typecore.ml
Original file line number Diff line number Diff line change
Expand Up @@ -2243,17 +2243,18 @@ type lazy_args =
(Asttypes.arg_label * (unit -> Typedtree.expression) option) list

type targs = (Asttypes.arg_label * Typedtree.expression option) list
let rec type_exp ~context ?recarg env sexp =
let rec type_exp ?deprecated_context ~context ?recarg env sexp =
(* We now delegate everything to type_expect *)
type_expect ~context ?recarg env sexp (newvar ())
type_expect ?deprecated_context ~context ?recarg env sexp (newvar ())

(* Typing of an expression with an expected type.
This provide better error messages, and allows controlled
propagation of return type information.
In the principal case, [type_expected'] may be at generic_level.
*)

and type_expect ~context ?in_function ?recarg env sexp ty_expected =
and type_expect ~context ?deprecated_context ?in_function ?recarg env sexp
ty_expected =
(* Special errors for braced identifiers passed to records *)
let context =
match sexp.pexp_desc with
Expand All @@ -2268,14 +2269,15 @@ and type_expect ~context ?in_function ?recarg env sexp ty_expected =
let previous_saved_types = Cmt_format.get_saved_types () in
let exp =
Builtin_attributes.warning_scope sexp.pexp_attributes (fun () ->
type_expect_ ~context ?in_function ?recarg env sexp ty_expected)
type_expect_ ?deprecated_context ~context ?in_function ?recarg env sexp
ty_expected)
in
Cmt_format.set_saved_types
(Cmt_format.Partial_expression exp :: previous_saved_types);
exp

and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected
=
and type_expect_ ?deprecated_context ~context ?in_function ?(recarg = Rejected)
env sexp ty_expected =
let loc = sexp.pexp_loc in
(* Record the expression type before unifying it with the expected type *)
let rue exp =
Expand All @@ -2292,7 +2294,14 @@ and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected
in
match sexp.pexp_desc with
| Pexp_ident lid ->
let path, desc = Typetexp.find_value env lid.loc lid.txt in
let path, desc =
Typetexp.find_value
?deprecated_context:
(match deprecated_context with
| None -> Some Reference
| v -> v)
env lid.loc lid.txt
in
(if !Clflags.annotations then
let dloc = desc.Types.val_loc in
let annot =
Expand Down Expand Up @@ -2428,7 +2437,9 @@ and type_expect_ ~context ?in_function ?(recarg = Rejected) env sexp ty_expected
assert (sargs <> []);
begin_def ();
(* one more level for non-returning functions *)
let funct = type_exp ~context:None env sfunct in
let funct =
type_exp ~deprecated_context:FunctionCall ~context:None env sfunct
in
let ty = instance env funct.exp_type in
end_def ();
wrap_trace_gadt_instances env (lower_args env []) ty;
Expand Down
8 changes: 5 additions & 3 deletions compiler/ml/typetexp.ml
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ let find_type env loc lid =
env loc lid
in
let decl = Env.find_type path env in
Builtin_attributes.check_deprecated loc decl.type_attributes (Path.name path);
Builtin_attributes.check_deprecated ~deprecated_context:Cmt_utils.Reference
loc decl.type_attributes (Path.name path);
(path, decl)

let find_constructor =
Expand All @@ -131,12 +132,13 @@ let find_all_constructors =
let find_all_labels =
find_component Env.lookup_all_labels (fun lid -> Unbound_label (lid, None))

let find_value env loc lid =
let find_value ?deprecated_context env loc lid =
Env.check_value_name (Longident.last lid) loc;
let ((path, decl) as r) =
find_component Env.lookup_value (fun lid -> Unbound_value lid) env loc lid
in
Builtin_attributes.check_deprecated loc decl.val_attributes (Path.name path);
Builtin_attributes.check_deprecated ?deprecated_context loc
decl.val_attributes (Path.name path);
r

let lookup_module ?(load = false) env loc lid =
Expand Down
Loading
Loading