summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorwiktorkuchta <35867657+wiktorkuchta@users.noreply.github.com>2023-01-23 09:05:44 +0100
committerGitHub <noreply@github.com>2023-01-23 09:05:44 +0100
commitfdcbdce2cd4a369251b6ab00af6697e6e40c9e2a (patch)
treeb264748a71ea95c97b6a149e1e87cc28dcf89bc2
parentf1550145d4ebe8ee22853d13f97fca288aaef51f (diff)
downloadocaml-fdcbdce2cd4a369251b6ab00af6697e6e40c9e2a.tar.gz
toplevel: show hints for the "undefined global" error (#10647)
-rw-r--r--.depend2
-rw-r--r--Changes3
-rw-r--r--toplevel/topcommon.ml36
3 files changed, 41 insertions, 0 deletions
diff --git a/.depend b/.depend
index 6f49bd4755..422aab3479 100644
--- a/.depend
+++ b/.depend
@@ -6305,6 +6305,7 @@ toplevel/genprintval.cmi : \
typing/env.cmi
toplevel/topcommon.cmo : \
typing/typedtree.cmi \
+ bytecomp/symtable.cmi \
parsing/printast.cmi \
typing/predef.cmi \
parsing/pprintast.cmi \
@@ -6332,6 +6333,7 @@ toplevel/topcommon.cmo : \
toplevel/topcommon.cmi
toplevel/topcommon.cmx : \
typing/typedtree.cmx \
+ bytecomp/symtable.cmx \
parsing/printast.cmx \
typing/predef.cmx \
parsing/pprintast.cmx \
diff --git a/Changes b/Changes
index a60c88a612..66a4d127d3 100644
--- a/Changes
+++ b/Changes
@@ -244,6 +244,9 @@ Working version
- #11774: ocamlyacc: fail if there is an I/O error
(Demi Marie Obenour)
+- #10647: Show hints for the "undefined global" error in the toplevel
+ (Wiktor Kuchta, review by Gabriel Scherer)
+
### Manual and documentation:
- #9430, #11291: Document the general desugaring rules for binding operators.
diff --git a/toplevel/topcommon.ml b/toplevel/topcommon.ml
index fc2336e8d3..dcee7bbff5 100644
--- a/toplevel/topcommon.ml
+++ b/toplevel/topcommon.ml
@@ -380,3 +380,39 @@ let try_run_directive ppf dir_name pdir_arg =
dir_name dir_type arg_type;
false
end
+
+(* Overriding exception printers with toplevel-specific ones *)
+
+let loading_hint_printer ppf s =
+ Symtable.report_error ppf (Symtable.Undefined_global s);
+ let find_with_ext ext =
+ try Some (Load_path.find_uncap (s ^ ext)) with Not_found -> None
+ in
+ fprintf ppf
+ "@.Hint: @[\
+ This means that the interface of a module is loaded, \
+ but its implementation is not.@,";
+ (* Filenames don't have to correspond to module names,
+ especially for archives (cmas), which bundle multiple modules.
+ But very often they do. *)
+ begin match List.find_map find_with_ext [".cma"; ".cmo"] with
+ | Some path ->
+ fprintf ppf
+ "Found %s @,in the load paths. \
+ @,Did you mean to load it using @,#load \"%s\" \
+ @,or by passing it as an argument to the toplevel?"
+ path (Filename.basename path)
+ | None ->
+ fprintf ppf
+ "Did you mean to load a compiled implementation of the module \
+ @,using #load or by passing it as an argument to the toplevel?"
+ end;
+ fprintf ppf "@]"
+
+let () =
+ Location.register_error_of_exn
+ (function
+ | Symtable.Error (Symtable.Undefined_global s) ->
+ Some (Location.error_of_printer_file loading_hint_printer s)
+ | _ -> None
+ )