diff --git a/src/analysis/locate.ml b/src/analysis/locate.ml index d4d16dd738..dd8fa62a27 100644 --- a/src/analysis/locate.ml +++ b/src/analysis/locate.ml @@ -236,6 +236,8 @@ module Utils = struct || List.exists Predef.builtin_values ~f | _ -> false + let is_ghost_loc { Location. loc_ghost; _ } = loc_ghost + (* Reuse the code of [Misc.find_in_path_uncap] but returns all the files matching, instead of the first one. This is only used when looking for ml files, not cmts. Indeed for cmts we @@ -770,7 +772,7 @@ end = struct Some x end -let locate ~config ~ml_or_mli ~path ~lazy_trie ~pos ~str_ident = +let locate ~config ~ml_or_mli ~path ~lazy_trie ~pos ~str_ident loc = File_switching.reset (); Fallback.reset (); Preferences.set ml_or_mli; @@ -778,6 +780,7 @@ let locate ~config ~ml_or_mli ~path ~lazy_trie ~pos ~str_ident = "present in the environment, walking up the typedtree looking for '%s'" (Namespaced_path.to_unique_string path); try + if not (Utils.is_ghost_loc loc) then Fallback.set loc; let lazy trie = lazy_trie in match locate ~config ~context:(Initial pos) path trie with | Found (loc, doc) -> `Found (loc, doc) @@ -790,21 +793,21 @@ let locate ~config ~ml_or_mli ~path ~lazy_trie ~pos ~str_ident = | Not_found -> `Not_found (str_ident, File_switching.where_am_i ()) (* Only used to retrieve documentation *) -let from_completion_entry ~config ~lazy_trie ~pos (namespace, path, _) = +let from_completion_entry ~config ~lazy_trie ~pos (namespace, path, loc) = let str_ident = Path.name path in let tagged_path = Namespaced_path.of_path ~namespace path in - locate ~config ~ml_or_mli:`MLI ~path:tagged_path ~pos ~str_ident + locate ~config ~ml_or_mli:`MLI ~path:tagged_path ~pos ~str_ident loc ~lazy_trie let from_longident ~config ~env ~lazy_trie ~pos nss ml_or_mli ident = let str_ident = String.concat ~sep:"." (Longident.flatten ident) in match Env_lookup.in_namespaces nss ident env with | None -> `Not_in_env str_ident - | Some (path, tagged_path, _) -> + | Some (path, tagged_path, loc) -> if Utils.is_builtin_path path then `Builtin else - locate ~config ~ml_or_mli ~path:tagged_path ~lazy_trie ~pos ~str_ident + locate ~config ~ml_or_mli ~path:tagged_path ~lazy_trie ~pos ~str_ident loc let from_string ~config ~env ~local_defs ~pos ?namespaces switch path = let browse = Mbrowse.of_typedtree local_defs in diff --git a/src/ocaml/typing/402/env.ml b/src/ocaml/typing/402/env.ml index 249167af52..b8f9d98f50 100644 --- a/src/ocaml/typing/402/env.ml +++ b/src/ocaml/typing/402/env.ml @@ -413,8 +413,9 @@ let read_pers_struct modname filename = let sign = cmi.cmi_sign in let crcs = cmi.cmi_crcs in let flags = cmi.cmi_flags in + let id_subst = Subst.(make_loc_ghost identity) in let comps = - !components_of_module' empty Subst.identity + !components_of_module' empty id_subst (Pident(Ident.create_persistent name)) (Mty_signature sign) in @@ -422,7 +423,7 @@ let read_pers_struct modname filename = | Cmi_cache_store (ps_typemap, ps_sig) -> ps_typemap, ps_sig | _ -> let ps_typemap = ref None in - let ps_sig = lazy (Subst.signature Subst.identity sign) in + let ps_sig = lazy (Subst.signature id_subst sign) in cmi_cache := Cmi_cache_store (ps_typemap, ps_sig); ps_typemap, ps_sig in diff --git a/src/ocaml/typing/402/subst.ml b/src/ocaml/typing/402/subst.ml index a135e8e74d..6c56b15f62 100644 --- a/src/ocaml/typing/402/subst.ml +++ b/src/ocaml/typing/402/subst.ml @@ -23,11 +23,12 @@ type t = { types: (Ident.t, Path.t) Tbl.t; modules: (Ident.t, Path.t) Tbl.t; modtypes: (Ident.t, module_type) Tbl.t; - for_saving: bool } + for_saving: bool; + make_loc_ghost: bool } let identity = { types = Tbl.empty; modules = Tbl.empty; modtypes = Tbl.empty; - for_saving = false } + for_saving = false; make_loc_ghost = false } let add_type id p s = { s with types = Tbl.add id p s.types } @@ -36,9 +37,12 @@ let add_module id p s = { s with modules = Tbl.add id p s.modules } let add_modtype id ty s = { s with modtypes = Tbl.add id ty s.modtypes } let for_saving s = { s with for_saving = true } +let make_loc_ghost s = { s with make_loc_ghost = true } let loc s x = - if s.for_saving && not !Clflags.keep_locs then Location.none else x + if s.for_saving && not !Clflags.keep_locs then Location.none + else if s.make_loc_ghost then { x with loc_ghost = true } + else x let remove_loc = let open Ast_mapper in @@ -320,7 +324,10 @@ let extension_constructor s ext = ext_ret_type = may_map (typexp s) ext.ext_ret_type; ext_private = ext.ext_private; ext_attributes = attrs s ext.ext_attributes; - ext_loc = if s.for_saving then Location.none else ext.ext_loc; } + ext_loc = + if s.for_saving then Location.none + else if s.make_loc_ghost then { ext.ext_loc with loc_ghost = true } + else ext.ext_loc; } in cleanup_types (); ext @@ -413,4 +420,5 @@ let compose s1 s2 = { types = merge_tbls (type_path s2) s1.types s2.types; modules = merge_tbls (module_path s2) s1.modules s2.modules; modtypes = merge_tbls (modtype s2) s1.modtypes s2.modtypes; - for_saving = false } + for_saving = false; + make_loc_ghost = s1.make_loc_ghost || s2.make_loc_ghost } diff --git a/src/ocaml/typing/402/subst.mli b/src/ocaml/typing/402/subst.mli index 7f6870e939..f7bce647a0 100644 --- a/src/ocaml/typing/402/subst.mli +++ b/src/ocaml/typing/402/subst.mli @@ -34,6 +34,7 @@ val add_type: Ident.t -> Path.t -> t -> t val add_module: Ident.t -> Path.t -> t -> t val add_modtype: Ident.t -> module_type -> t -> t val for_saving: t -> t +val make_loc_ghost: t -> t val reset_for_saving: unit -> unit val module_path: t -> Path.t -> Path.t diff --git a/src/ocaml/typing/403/env.ml b/src/ocaml/typing/403/env.ml index 9a7172e52b..01de8fc901 100644 --- a/src/ocaml/typing/403/env.ml +++ b/src/ocaml/typing/403/env.ml @@ -502,8 +502,9 @@ let read_pers_struct check modname filename = List.fold_left (fun acc -> function Deprecated s -> Some s | _ -> acc) None flags in + let id_subst = Subst.(make_loc_ghost identity) in let comps = - !components_of_module' ~deprecated empty Subst.identity + !components_of_module' ~deprecated empty id_subst (Pident(Ident.create_persistent name)) (Mty_signature sign) in @@ -511,7 +512,7 @@ let read_pers_struct check modname filename = | Cmi_cache_store (ps_typemap, ps_sig) -> ps_typemap, ps_sig | _ -> let ps_typemap = ref None in - let ps_sig = lazy (Subst.signature Subst.identity sign) in + let ps_sig = lazy (Subst.signature id_subst sign) in cmi_cache := Cmi_cache_store (ps_typemap, ps_sig); ps_typemap, ps_sig in diff --git a/src/ocaml/typing/403/subst.ml b/src/ocaml/typing/403/subst.ml index 59c54efd80..33cfffcb39 100644 --- a/src/ocaml/typing/403/subst.ml +++ b/src/ocaml/typing/403/subst.ml @@ -25,11 +25,12 @@ type t = modules: (Ident.t, Path.t) Tbl.t; modtypes: (Ident.t, module_type) Tbl.t; for_saving: bool; - nongen_level: int } + nongen_level: int; + make_loc_ghost: bool } let identity = { types = Tbl.empty; modules = Tbl.empty; modtypes = Tbl.empty; - for_saving = false; nongen_level = generic_level } + for_saving = false; nongen_level = generic_level; make_loc_ghost = false } let add_type id p s = { s with types = Tbl.add id p s.types } @@ -41,8 +42,12 @@ let for_saving s = { s with for_saving = true } let set_nongen_level s lev = { s with nongen_level = lev } +let make_loc_ghost s = { s with make_loc_ghost = true } + let loc s x = - if s.for_saving && not !Clflags.keep_locs then Location.none else x + if s.for_saving && not !Clflags.keep_locs then Location.none + else if s.make_loc_ghost then { x with loc_ghost = true } + else x let remove_loc = let open Ast_mapper in @@ -338,7 +343,10 @@ let extension_constructor s ext = ext_ret_type = may_map (typexp s) ext.ext_ret_type; ext_private = ext.ext_private; ext_attributes = attrs s ext.ext_attributes; - ext_loc = if s.for_saving then Location.none else ext.ext_loc; } + ext_loc = + if s.for_saving then Location.none + else if s.make_loc_ghost then { ext.ext_loc with loc_ghost = true } + else ext.ext_loc; } in cleanup_types (); ext @@ -435,4 +443,5 @@ let compose s1 s2 = modules = merge_tbls (module_path s2) s1.modules s2.modules; modtypes = merge_tbls (modtype s2) s1.modtypes s2.modtypes; for_saving = s1.for_saving || s2.for_saving; - nongen_level = min s1.nongen_level s2.nongen_level } + nongen_level = min s1.nongen_level s2.nongen_level; + make_loc_ghost = s1.make_loc_ghost || s2.make_loc_ghost } diff --git a/src/ocaml/typing/403/subst.mli b/src/ocaml/typing/403/subst.mli index 74931ffc7f..2bcb6e3f67 100644 --- a/src/ocaml/typing/403/subst.mli +++ b/src/ocaml/typing/403/subst.mli @@ -38,6 +38,7 @@ val add_module: Ident.t -> Path.t -> t -> t val add_modtype: Ident.t -> module_type -> t -> t val set_nongen_level: t -> int -> t val for_saving: t -> t +val make_loc_ghost: t -> t val reset_for_saving: unit -> unit val module_path: t -> Path.t -> Path.t diff --git a/src/ocaml/typing/404/env.ml b/src/ocaml/typing/404/env.ml index 34300b976c..021c062c53 100644 --- a/src/ocaml/typing/404/env.ml +++ b/src/ocaml/typing/404/env.ml @@ -509,9 +509,10 @@ let acknowledge_pers_struct check modname List.fold_left (fun acc -> function Deprecated s -> Some s | _ -> acc) None flags in + let id_subst = Subst.(make_loc_ghost identity) in let comps = !components_of_module' ~deprecated ~loc:Location.none - empty Subst.identity + empty id_subst (Pident(Ident.create_persistent name)) (Mty_signature sign) in @@ -519,7 +520,7 @@ let acknowledge_pers_struct check modname match !cmi_cache with | Cmi_cache_store ps_sig -> ps_sig | _ -> - let ps_sig = lazy (Subst.signature Subst.identity sign) in + let ps_sig = lazy (Subst.signature id_subst sign) in cmi_cache := Cmi_cache_store ps_sig; ps_sig in diff --git a/src/ocaml/typing/404/subst.ml b/src/ocaml/typing/404/subst.ml index 85da130bf6..ce115f9dcb 100644 --- a/src/ocaml/typing/404/subst.ml +++ b/src/ocaml/typing/404/subst.ml @@ -25,11 +25,12 @@ type t = modules: (Ident.t, Path.t) Tbl.t; modtypes: (Ident.t, module_type) Tbl.t; for_saving: bool; - nongen_level: int } + nongen_level: int; + make_loc_ghost: bool } let identity = { types = Tbl.empty; modules = Tbl.empty; modtypes = Tbl.empty; - for_saving = false; nongen_level = generic_level } + for_saving = false; nongen_level = generic_level; make_loc_ghost = false } let add_type id p s = { s with types = Tbl.add id p s.types } @@ -41,8 +42,12 @@ let for_saving s = { s with for_saving = true } let set_nongen_level s lev = { s with nongen_level = lev } +let make_loc_ghost s = { s with make_loc_ghost = true } + let loc s x = - if s.for_saving && not !Clflags.keep_locs then Location.none else x + if s.for_saving && not !Clflags.keep_locs then Location.none + else if s.make_loc_ghost then { x with loc_ghost = true } + else x let remove_loc = let open Ast_mapper in @@ -339,7 +344,10 @@ let extension_constructor s ext = ext_ret_type = may_map (typexp s) ext.ext_ret_type; ext_private = ext.ext_private; ext_attributes = attrs s ext.ext_attributes; - ext_loc = if s.for_saving then Location.none else ext.ext_loc; } + ext_loc = + if s.for_saving then Location.none + else if s.make_loc_ghost then { ext.ext_loc with loc_ghost = true } + else ext.ext_loc; } in cleanup_types (); ext @@ -436,4 +444,5 @@ let compose s1 s2 = modules = merge_tbls (module_path s2) s1.modules s2.modules; modtypes = merge_tbls (modtype s2) s1.modtypes s2.modtypes; for_saving = s1.for_saving || s2.for_saving; - nongen_level = min s1.nongen_level s2.nongen_level } + nongen_level = min s1.nongen_level s2.nongen_level; + make_loc_ghost = s1.make_loc_ghost || s2.make_loc_ghost } diff --git a/src/ocaml/typing/404/subst.mli b/src/ocaml/typing/404/subst.mli index 74931ffc7f..2bcb6e3f67 100644 --- a/src/ocaml/typing/404/subst.mli +++ b/src/ocaml/typing/404/subst.mli @@ -38,6 +38,7 @@ val add_module: Ident.t -> Path.t -> t -> t val add_modtype: Ident.t -> module_type -> t -> t val set_nongen_level: t -> int -> t val for_saving: t -> t +val make_loc_ghost: t -> t val reset_for_saving: unit -> unit val module_path: t -> Path.t -> Path.t diff --git a/src/ocaml/typing/405/env.ml b/src/ocaml/typing/405/env.ml index 404b190ac2..c496098a43 100644 --- a/src/ocaml/typing/405/env.ml +++ b/src/ocaml/typing/405/env.ml @@ -509,9 +509,10 @@ let acknowledge_pers_struct check modname List.fold_left (fun acc -> function Deprecated s -> Some s | _ -> acc) None flags in + let id_subst = Subst.(make_loc_ghost identity) in let comps = !components_of_module' ~deprecated ~loc:Location.none - empty Subst.identity + empty id_subst (Pident(Ident.create_persistent name)) (Mty_signature sign) in @@ -519,7 +520,7 @@ let acknowledge_pers_struct check modname match !cmi_cache with | Cmi_cache_store ps_sig -> ps_sig | _ -> - let ps_sig = lazy (Subst.signature Subst.identity sign) in + let ps_sig = lazy (Subst.signature id_subst sign) in cmi_cache := Cmi_cache_store ps_sig; ps_sig in diff --git a/src/ocaml/typing/405/subst.ml b/src/ocaml/typing/405/subst.ml index e6fc9e3de0..69769d1ed2 100644 --- a/src/ocaml/typing/405/subst.ml +++ b/src/ocaml/typing/405/subst.ml @@ -24,11 +24,12 @@ type t = { types: (Ident.t, Path.t) Tbl.t; modules: (Ident.t, Path.t) Tbl.t; modtypes: (Ident.t, module_type) Tbl.t; - for_saving: bool } + for_saving: bool; + make_loc_ghost: bool } let identity = { types = Tbl.empty; modules = Tbl.empty; modtypes = Tbl.empty; - for_saving = false } + for_saving = false; make_loc_ghost = false } let add_type id p s = { s with types = Tbl.add id p s.types } @@ -37,9 +38,12 @@ let add_module id p s = { s with modules = Tbl.add id p s.modules } let add_modtype id ty s = { s with modtypes = Tbl.add id ty s.modtypes } let for_saving s = { s with for_saving = true } +let make_loc_ghost s = { s with make_loc_ghost = true } let loc s x = - if s.for_saving && not !Clflags.keep_locs then Location.none else x + if s.for_saving && not !Clflags.keep_locs then Location.none + else if s.make_loc_ghost then { x with loc_ghost = true } + else x let remove_loc = let open Ast_mapper in @@ -341,7 +345,10 @@ let extension_constructor s ext = ext_ret_type = may_map (typexp s) ext.ext_ret_type; ext_private = ext.ext_private; ext_attributes = attrs s ext.ext_attributes; - ext_loc = if s.for_saving then Location.none else ext.ext_loc; } + ext_loc = + if s.for_saving then Location.none + else if s.make_loc_ghost then { ext.ext_loc with loc_ghost = true } + else ext.ext_loc; } in cleanup_types (); ext @@ -437,4 +444,5 @@ let compose s1 s2 = { types = merge_tbls (type_path s2) s1.types s2.types; modules = merge_tbls (module_path s2) s1.modules s2.modules; modtypes = merge_tbls (modtype s2) s1.modtypes s2.modtypes; - for_saving = s1.for_saving || s2.for_saving } + for_saving = s1.for_saving || s2.for_saving; + make_loc_ghost = s1.make_loc_ghost || s2.make_loc_ghost } diff --git a/src/ocaml/typing/405/subst.mli b/src/ocaml/typing/405/subst.mli index 55eee757d7..10f28e336e 100644 --- a/src/ocaml/typing/405/subst.mli +++ b/src/ocaml/typing/405/subst.mli @@ -37,6 +37,7 @@ val add_type: Ident.t -> Path.t -> t -> t val add_module: Ident.t -> Path.t -> t -> t val add_modtype: Ident.t -> module_type -> t -> t val for_saving: t -> t +val make_loc_ghost: t -> t val reset_for_saving: unit -> unit val module_path: t -> Path.t -> Path.t diff --git a/src/ocaml/typing/406/env.ml b/src/ocaml/typing/406/env.ml index 1545b2edfb..2e4c70b061 100644 --- a/src/ocaml/typing/406/env.ml +++ b/src/ocaml/typing/406/env.ml @@ -759,9 +759,10 @@ let acknowledge_pers_struct check modname List.fold_left (fun acc -> function Deprecated s -> Some s | _ -> acc) None flags in + let id_subst = Subst.(make_loc_ghost identity) in let comps = !components_of_module' ~deprecated ~loc:Location.none - empty Subst.identity + empty id_subst (Pident(Ident.create_persistent name)) (Mty_signature sign) in @@ -769,7 +770,7 @@ let acknowledge_pers_struct check modname match !cmi_cache with | Cmi_cache_store ps_sig -> ps_sig | _ -> - let ps_sig = lazy (Subst.signature Subst.identity sign) in + let ps_sig = lazy (Subst.signature id_subst sign) in cmi_cache := Cmi_cache_store ps_sig; ps_sig in diff --git a/src/ocaml/typing/406/subst.ml b/src/ocaml/typing/406/subst.ml index edf3880f01..d81c4b897e 100644 --- a/src/ocaml/typing/406/subst.ml +++ b/src/ocaml/typing/406/subst.ml @@ -31,6 +31,7 @@ type t = modules: Path.t PathMap.t; modtypes: (Ident.t, module_type) Tbl.t; for_saving: bool; + make_loc_ghost: bool; } let identity = @@ -38,6 +39,7 @@ let identity = modules = PathMap.empty; modtypes = Tbl.empty; for_saving = false; + make_loc_ghost = false; } let add_type_path id p s = { s with types = PathMap.add id (Path p) s.types } @@ -52,9 +54,12 @@ let add_module id p s = add_module_path (Pident id) p s let add_modtype id ty s = { s with modtypes = Tbl.add id ty s.modtypes } let for_saving s = { s with for_saving = true } +let make_loc_ghost s = { s with make_loc_ghost = true } let loc s x = - if s.for_saving && not !Clflags.keep_locs then Location.none else x + if s.for_saving && not !Clflags.keep_locs then Location.none + else if s.make_loc_ghost then { x with loc_ghost = true } + else x let remove_loc = let open Ast_mapper in @@ -488,4 +493,5 @@ let compose s1 s2 = modules = merge_path_maps (module_path s2) s1.modules s2.modules; modtypes = merge_tbls (modtype s2) s1.modtypes s2.modtypes; for_saving = s1.for_saving || s2.for_saving; + make_loc_ghost = s1.make_loc_ghost || s2.make_loc_ghost; } diff --git a/src/ocaml/typing/406/subst.mli b/src/ocaml/typing/406/subst.mli index f81cb4da56..39b603409f 100644 --- a/src/ocaml/typing/406/subst.mli +++ b/src/ocaml/typing/406/subst.mli @@ -41,6 +41,7 @@ val add_module: Ident.t -> Path.t -> t -> t val add_module_path: Path.t -> Path.t -> t -> t val add_modtype: Ident.t -> module_type -> t -> t val for_saving: t -> t +val make_loc_ghost: t -> t val reset_for_saving: unit -> unit val module_path: t -> Path.t -> Path.t diff --git a/src/ocaml/typing/407/env.ml b/src/ocaml/typing/407/env.ml index b763d15844..452eefe958 100644 --- a/src/ocaml/typing/407/env.ml +++ b/src/ocaml/typing/407/env.ml @@ -730,9 +730,10 @@ let acknowledge_pers_struct check modname List.fold_left (fun acc -> function Deprecated s -> Some s | _ -> acc) None flags in + let id_subst = Subst.(make_loc_ghost identity) in let comps = !components_of_module' ~deprecated ~loc:Location.none - empty Subst.identity + empty id_subst (Pident(Ident.create_persistent name)) (Mty_signature sign) in @@ -740,7 +741,7 @@ let acknowledge_pers_struct check modname match !cmi_cache with | Cmi_cache_store ps_sig -> ps_sig | _ -> - let ps_sig = lazy (Subst.signature Subst.identity sign) in + let ps_sig = lazy (Subst.signature id_subst sign) in cmi_cache := Cmi_cache_store ps_sig; ps_sig in diff --git a/src/ocaml/typing/407/subst.ml b/src/ocaml/typing/407/subst.ml index 6c7a57c058..4bf78fdf95 100644 --- a/src/ocaml/typing/407/subst.ml +++ b/src/ocaml/typing/407/subst.ml @@ -31,6 +31,7 @@ type t = modules: Path.t PathMap.t; modtypes: (Ident.t, module_type) Tbl.t; for_saving: bool; + make_loc_ghost: bool; } let identity = @@ -38,6 +39,7 @@ let identity = modules = PathMap.empty; modtypes = Tbl.empty; for_saving = false; + make_loc_ghost = false; } let add_type_path id p s = { s with types = PathMap.add id (Path p) s.types } @@ -52,9 +54,12 @@ let add_module id p s = add_module_path (Pident id) p s let add_modtype id ty s = { s with modtypes = Tbl.add id ty s.modtypes } let for_saving s = { s with for_saving = true } +let make_loc_ghost s = { s with make_loc_ghost = true } let loc s x = - if s.for_saving && not !Clflags.keep_locs then Location.none else x + if s.for_saving && not !Clflags.keep_locs then Location.none + else if s.make_loc_ghost then { x with loc_ghost = true } + else x let remove_loc = let open Ast_mapper in @@ -488,4 +493,5 @@ let compose s1 s2 = modules = merge_path_maps (module_path s2) s1.modules s2.modules; modtypes = merge_tbls (modtype s2) s1.modtypes s2.modtypes; for_saving = s1.for_saving || s2.for_saving; + make_loc_ghost = s1.make_loc_ghost || s2.make_loc_ghost; } diff --git a/src/ocaml/typing/407/subst.mli b/src/ocaml/typing/407/subst.mli index f81cb4da56..39b603409f 100644 --- a/src/ocaml/typing/407/subst.mli +++ b/src/ocaml/typing/407/subst.mli @@ -41,6 +41,7 @@ val add_module: Ident.t -> Path.t -> t -> t val add_module_path: Path.t -> Path.t -> t -> t val add_modtype: Ident.t -> module_type -> t -> t val for_saving: t -> t +val make_loc_ghost: t -> t val reset_for_saving: unit -> unit val module_path: t -> Path.t -> Path.t diff --git a/src/ocaml/typing/407_0/env.ml b/src/ocaml/typing/407_0/env.ml index 09f6d4a734..f498efdad6 100644 --- a/src/ocaml/typing/407_0/env.ml +++ b/src/ocaml/typing/407_0/env.ml @@ -730,9 +730,10 @@ let acknowledge_pers_struct check modname List.fold_left (fun acc -> function Deprecated s -> Some s | _ -> acc) None flags in + let id_subst = Subst.(make_loc_ghost identity) in let comps = !components_of_module' ~deprecated ~loc:Location.none - empty Subst.identity + empty id_subst (Pident(Ident.create_persistent name)) (Mty_signature sign) in @@ -740,7 +741,7 @@ let acknowledge_pers_struct check modname match !cmi_cache with | Cmi_cache_store ps_sig -> ps_sig | _ -> - let ps_sig = lazy (Subst.signature Subst.identity sign) in + let ps_sig = lazy (Subst.signature id_subst sign) in cmi_cache := Cmi_cache_store ps_sig; ps_sig in diff --git a/src/ocaml/typing/407_0/subst.ml b/src/ocaml/typing/407_0/subst.ml index 3bb18822ff..9209147f41 100644 --- a/src/ocaml/typing/407_0/subst.ml +++ b/src/ocaml/typing/407_0/subst.ml @@ -31,6 +31,7 @@ type t = modules: Path.t PathMap.t; modtypes: (Ident.t, module_type) Tbl.t; for_saving: bool; + make_loc_ghost: bool; } let identity = @@ -38,6 +39,7 @@ let identity = modules = PathMap.empty; modtypes = Tbl.empty; for_saving = false; + make_loc_ghost = false; } let add_type_path id p s = { s with types = PathMap.add id (Path p) s.types } @@ -52,9 +54,12 @@ let add_module id p s = add_module_path (Pident id) p s let add_modtype id ty s = { s with modtypes = Tbl.add id ty s.modtypes } let for_saving s = { s with for_saving = true } +let make_loc_ghost s = { s with make_loc_ghost = true } let loc s x = - if s.for_saving && not !Clflags.keep_locs then Location.none else x + if s.for_saving && not !Clflags.keep_locs then Location.none + else if s.make_loc_ghost then { x with loc_ghost = true } + else x let remove_loc = let open Ast_mapper in @@ -489,4 +494,5 @@ let compose s1 s2 = modules = merge_path_maps (module_path s2) s1.modules s2.modules; modtypes = merge_tbls (modtype s2) s1.modtypes s2.modtypes; for_saving = s1.for_saving || s2.for_saving; + make_loc_ghost = s1.make_loc_ghost || s2.make_loc_ghost; } diff --git a/src/ocaml/typing/407_0/subst.mli b/src/ocaml/typing/407_0/subst.mli index f81cb4da56..39b603409f 100644 --- a/src/ocaml/typing/407_0/subst.mli +++ b/src/ocaml/typing/407_0/subst.mli @@ -41,6 +41,7 @@ val add_module: Ident.t -> Path.t -> t -> t val add_module_path: Path.t -> Path.t -> t -> t val add_modtype: Ident.t -> module_type -> t -> t val for_saving: t -> t +val make_loc_ghost: t -> t val reset_for_saving: unit -> unit val module_path: t -> Path.t -> Path.t diff --git a/src/ocaml/typing/408/env.ml b/src/ocaml/typing/408/env.ml index ea6437f04c..cd4be3719e 100644 --- a/src/ocaml/typing/408/env.ml +++ b/src/ocaml/typing/408/env.ml @@ -809,16 +809,17 @@ let acknowledge_pers_struct check modname let id = Ident.create_persistent name in let path = Pident id in let addr = EnvLazy.create_forced (Aident id) in + let id_subst = Subst.(make_loc_ghost identity) in let comps = !components_of_module' ~alerts ~loc:Location.none - empty (Some Subst.identity) Subst.identity path addr + empty (Some id_subst) id_subst path addr (Mty_signature sign) in let ps_sig = match !cmi_cache with | Cmi_cache_store ps_sig -> ps_sig | _ -> - let ps_sig = lazy (Subst.signature Make_local Subst.identity sign) in + let ps_sig = lazy (Subst.signature Make_local id_subst sign) in cmi_cache := Cmi_cache_store ps_sig; ps_sig in diff --git a/src/ocaml/typing/408/subst.ml b/src/ocaml/typing/408/subst.ml index bddea430ab..4c66114c0d 100644 --- a/src/ocaml/typing/408/subst.ml +++ b/src/ocaml/typing/408/subst.ml @@ -29,6 +29,7 @@ type t = modules: Path.t Path.Map.t; modtypes: module_type Ident.Map.t; for_saving: bool; + make_loc_ghost: bool; } let identity = @@ -36,6 +37,7 @@ let identity = modules = Path.Map.empty; modtypes = Ident.Map.empty; for_saving = false; + make_loc_ghost = false; } let add_type_path id p s = { s with types = Path.Map.add id (Path p) s.types } @@ -50,9 +52,12 @@ let add_module id p s = add_module_path (Pident id) p s let add_modtype id ty s = { s with modtypes = Ident.Map.add id ty s.modtypes } let for_saving s = { s with for_saving = true } +let make_loc_ghost s = { s with make_loc_ghost = true } let loc s x = - if s.for_saving && not !Clflags.keep_locs then Location.none else x + if s.for_saving && not !Clflags.keep_locs then Location.none + else if s.make_loc_ghost then { x with loc_ghost = true } + else x let remove_loc = let open Ast_mapper in @@ -534,4 +539,5 @@ let compose s1 s2 = modules = merge_path_maps (module_path s2) s1.modules s2.modules; modtypes = merge_tbls (modtype Keep s2) s1.modtypes s2.modtypes; for_saving = s1.for_saving || s2.for_saving; + make_loc_ghost = s1.make_loc_ghost || s2.make_loc_ghost; } diff --git a/src/ocaml/typing/408/subst.mli b/src/ocaml/typing/408/subst.mli index f0b1a8beb0..eb079b19c5 100644 --- a/src/ocaml/typing/408/subst.mli +++ b/src/ocaml/typing/408/subst.mli @@ -41,6 +41,7 @@ val add_module: Ident.t -> Path.t -> t -> t val add_module_path: Path.t -> Path.t -> t -> t val add_modtype: Ident.t -> module_type -> t -> t val for_saving: t -> t +val make_loc_ghost: t -> t val reset_for_saving: unit -> unit val module_path: t -> Path.t -> Path.t diff --git a/tests/locate/mutually-recursive/dune b/tests/locate/mutually-recursive/dune new file mode 100644 index 0000000000..af94ea67d9 --- /dev/null +++ b/tests/locate/mutually-recursive/dune @@ -0,0 +1,8 @@ +(alias + (name runtest) + (deps (:t issue973.t) issue973.ml) + (action + (progn + (setenv MERLIN %{exe:../../merlin-wrapper} + (run %{bin:mdx} test --syntax=cram %{t})) + (diff? %{t} %{t}.corrected)))) diff --git a/tests/locate/mutually-recursive/issue973.ml b/tests/locate/mutually-recursive/issue973.ml new file mode 100644 index 0000000000..a590febc62 --- /dev/null +++ b/tests/locate/mutually-recursive/issue973.ml @@ -0,0 +1,8 @@ +let rec foo x = + 1 + bar x + +and bar x = + if x = 0 then + x + else + foo (x - 1) diff --git a/tests/locate/mutually-recursive/issue973.t b/tests/locate/mutually-recursive/issue973.t new file mode 100644 index 0000000000..f3ffa4ea00 --- /dev/null +++ b/tests/locate/mutually-recursive/issue973.t @@ -0,0 +1,29 @@ +Searching foo from bar works: + + $ $MERLIN single locate -look-for ml -position 8:6 -filename ./issue973.ml < ./issue973.ml + { + "class": "return", + "value": { + "file": "tests/locate/mutually-recursive/issue973.ml", + "pos": { + "line": 1, + "col": 8 + } + }, + "notifications": [] + } + +And so does bar from foo: + + $ $MERLIN single locate -look-for ml -position 2:7 -filename ./issue973.ml < ./issue973.ml + { + "class": "return", + "value": { + "file": "tests/locate/mutually-recursive/issue973.ml", + "pos": { + "line": 4, + "col": 4 + } + }, + "notifications": [] + } diff --git a/tests/locate/non-local/a.ml b/tests/locate/non-local/ignore-kept-locs/a.ml similarity index 100% rename from tests/locate/non-local/a.ml rename to tests/locate/non-local/ignore-kept-locs/a.ml diff --git a/tests/locate/non-local/ignore-kept-locs/b.ml b/tests/locate/non-local/ignore-kept-locs/b.ml new file mode 100644 index 0000000000..fbdfdccfa8 --- /dev/null +++ b/tests/locate/non-local/ignore-kept-locs/b.ml @@ -0,0 +1,5 @@ +let _ = A.value + +include A + +let _ = value diff --git a/tests/locate/non-local/ignore-kept-locs/dune b/tests/locate/non-local/ignore-kept-locs/dune new file mode 100644 index 0000000000..64a7d183a1 --- /dev/null +++ b/tests/locate/non-local/ignore-kept-locs/dune @@ -0,0 +1,9 @@ +(alias + (name runtest) + (deps (:t test.t) a.ml b.ml) + (action + (progn + (run %{ocamlc} -c -bin-annot -keep-locs a.ml) + (setenv MERLIN %{exe:../../../merlin-wrapper} + (run %{bin:mdx} test --syntax=cram %{t})) + (diff? %{t} %{t}.corrected)))) diff --git a/tests/locate/non-local/ignore-kept-locs/test.t b/tests/locate/non-local/ignore-kept-locs/test.t new file mode 100644 index 0000000000..a0f8bcb0a8 --- /dev/null +++ b/tests/locate/non-local/ignore-kept-locs/test.t @@ -0,0 +1,42 @@ +Make sure that we do not use locations coming from the cmi: + + $ $MERLIN single locate -look-for ml -log-section locate -log-file log \ + > -position 1:12 -filename ./b.ml < ./b.ml + { + "class": "return", + "value": { + "file": "tests/locate/non-local/ignore-kept-locs/a.ml", + "pos": { + "line": 1, + "col": 4 + } + }, + "notifications": [] + } + + $ grep -A1 Fallback log | grep -v Fallback + [1] + + $ rm log + + $ $MERLIN single locate -look-for ml -log-section locate -log-file log \ + > -position 5:12 -filename ./b.ml < ./b.ml + { + "class": "return", + "value": { + "file": "tests/locate/non-local/ignore-kept-locs/a.ml", + "pos": { + "line": 1, + "col": 4 + } + }, + "notifications": [] + } + +The fallback here is ok, it points to the local buffer (to the include line +actually), not to a.ml + + $ grep -A1 Fallback log | grep -v Fallback + File "b.ml", line 3, characters 0-9 + + $ rm log diff --git a/tests/locate/non-local/preference/a.ml b/tests/locate/non-local/preference/a.ml new file mode 100644 index 0000000000..e1b898c188 --- /dev/null +++ b/tests/locate/non-local/preference/a.ml @@ -0,0 +1 @@ +let value = 3 diff --git a/tests/locate/non-local/a.mli b/tests/locate/non-local/preference/a.mli similarity index 100% rename from tests/locate/non-local/a.mli rename to tests/locate/non-local/preference/a.mli diff --git a/tests/locate/non-local/b.ml b/tests/locate/non-local/preference/b.ml similarity index 100% rename from tests/locate/non-local/b.ml rename to tests/locate/non-local/preference/b.ml diff --git a/tests/locate/non-local/b.mli b/tests/locate/non-local/preference/b.mli similarity index 100% rename from tests/locate/non-local/b.mli rename to tests/locate/non-local/preference/b.mli diff --git a/tests/locate/non-local/dune b/tests/locate/non-local/preference/dune similarity index 83% rename from tests/locate/non-local/dune rename to tests/locate/non-local/preference/dune index c5e32e0917..900eb2e783 100644 --- a/tests/locate/non-local/dune +++ b/tests/locate/non-local/preference/dune @@ -5,6 +5,6 @@ (progn (run %{ocamlc} -c -bin-annot a.mli a.ml) (run %{ocamlc} -c -bin-annot b.mli b.ml) - (setenv MERLIN %{exe:../../merlin-wrapper} + (setenv MERLIN %{exe:../../../merlin-wrapper} (run %{bin:mdx} test --syntax=cram %{t})) (diff? %{t} %{t}.corrected)))) diff --git a/tests/locate/non-local/test.t b/tests/locate/non-local/preference/test.t similarity index 80% rename from tests/locate/non-local/test.t rename to tests/locate/non-local/preference/test.t index 87ba4e0237..712a9c70c9 100644 --- a/tests/locate/non-local/test.t +++ b/tests/locate/non-local/preference/test.t @@ -4,7 +4,7 @@ Test that Locate.locate and Locate.from_path do their job properly: { "class": "return", "value": { - "file": "tests/locate/non-local/a.ml", + "file": "tests/locate/non-local/preference/a.ml", "pos": { "line": 1, "col": 4 @@ -17,7 +17,7 @@ Test that Locate.locate and Locate.from_path do their job properly: { "class": "return", "value": { - "file": "tests/locate/non-local/a.ml", + "file": "tests/locate/non-local/preference/a.ml", "pos": { "line": 1, "col": 4 @@ -30,7 +30,7 @@ Test that Locate.locate and Locate.from_path do their job properly: { "class": "return", "value": { - "file": "tests/locate/non-local/a.ml", + "file": "tests/locate/non-local/preference/a.ml", "pos": { "line": 1, "col": 4 @@ -43,7 +43,7 @@ Test that Locate.locate and Locate.from_path do their job properly: { "class": "return", "value": { - "file": "tests/locate/non-local/a.mli", + "file": "tests/locate/non-local/preference/a.mli", "pos": { "line": 3, "col": 0 @@ -56,7 +56,7 @@ Test that Locate.locate and Locate.from_path do their job properly: { "class": "return", "value": { - "file": "tests/locate/non-local/a.mli", + "file": "tests/locate/non-local/preference/a.mli", "pos": { "line": 3, "col": 0 @@ -69,7 +69,7 @@ Test that Locate.locate and Locate.from_path do their job properly: { "class": "return", "value": { - "file": "tests/locate/non-local/a.mli", + "file": "tests/locate/non-local/preference/a.mli", "pos": { "line": 3, "col": 0