Location(3) OCaml library Location(3)

# [NAME](#NAME)

Location - Source code locations (ranges of positions), used in parsetree.

# [Module](#Module)

Module Location

# [Documentation](#Documentation)

Module **Location**  
: **sig end**

Source code locations (ranges of positions), used in parsetree.

Warning: this module is unstable and part of **Compiler\_libs** .

*type t* = **Warnings.loc** = {  
loc\_start : **Lexing.position** ;  
loc\_end : **Lexing.position** ;  
loc\_ghost : **bool** ;  
}

**t** represents a range of characters in the source code.

loc\_ghost=false whenever the AST described by the location can be parsed from the location. In all other cases, loc\_ghost must be true. Most locations produced by the parser have loc\_ghost=false. When loc\_ghost=true, the location is usually a best effort approximation.

This info is used by tools like merlin that want to relate source code with parsetrees or later asts. ocamlprof skips instrumentation of ghost nodes.

Example: in \`let f x = x\`, we have:

-a structure item at location "let f x = x"

-a pattern "f" at location "f"

-an expression "fun x -&gt; x" at location "x = x" with loc\_ghost=true

-a pattern "x" at location "x"

-an expression "x" at location "x" In this case, every node has loc\_ghost=false, except the node "fun x -&gt; x", since **Parser.expression (Lexing.from\_string "x = x")** would fail to parse. By contrast, in \`let f = fun x -&gt; x\`, every node has loc\_ghost=false.

Line directives can modify the filenames and line numbers arbitrarily, which is orthogonal to loc\_ghost, which describes the range of characters from loc\_start.pos\_cnum to loc\_end.pos\_cnum in the parsed string.

Note on the use of Lexing.position in this module. If **pos\_fname = ""** , then use **!input\_name** instead. If **pos\_lnum = -1** , then **pos\_bol = 0** . Use **pos\_cnum** and re-parse the file to get the line and character numbers. Else all fields are correct.

*val none* : **t**

An arbitrary value of type **t** ; describes an empty ghost range.

*val is\_none* : **t -&gt; bool**

True for **Location.none** , false any other location

*val in\_file* : **string -&gt; t**

Return an empty ghost range located in a given file.

*val init* : **Lexing.lexbuf -&gt; string -&gt; unit**

Set the file name and line number of the **lexbuf** to be the start of the named file.

*val curr* : **Lexing.lexbuf -&gt; t**

Get the location of the current token from the **lexbuf** .

*val symbol\_rloc* : **unit -&gt; t**

*val symbol\_gloc* : **unit -&gt; t**

*val rhs\_loc* : **int -&gt; t**

**rhs\_loc n** returns the location of the symbol at position **n** , starting at 1, in the current parser rule.

*val rhs\_interval* : **int -&gt; int -&gt; t**

*val get\_pos\_info* : **Lexing.position -&gt; string * int * int**

file, line, char

*type* **'a** *loc* = {  
txt : **'a** ;  
loc : **t** ;  
}

*val mknoloc* : **'a -&gt; 'a loc**

*val mkloc* : **'a -&gt; t -&gt; 'a loc**

*val map* : **('a -&gt; 'b) -&gt; 'a loc -&gt; 'b loc**

## [Input info](#Input_info)

*val input\_name* : **string ref**

*val input\_lexbuf* : **Lexing.lexbuf option ref**

*val input\_phrase\_buffer* : **Buffer.t option ref**

## [Toplevel-specific functions](#Toplevel-specific_functions)

*val echo\_eof* : **unit -&gt; unit**

*val reset* : **unit -&gt; unit**

## [Rewriting path](#Rewriting_path)

*val rewrite\_absolute\_path* : **string -&gt; string**

**rewrite\_absolute\_path path** rewrites **path** to honor the BUILD\_PATH\_PREFIX\_MAP variable if it is set. It does not check whether **path** is absolute or not. The result is as follows:

-If BUILD\_PATH\_PREFIX\_MAP is not set, just return **path** .

-otherwise, rewrite using the mapping (and if there are no matching prefixes that will just return **path** ).

See the BUILD\_PATH\_PREFIX\_MAP spec

*val rewrite\_find\_first\_existing* : **string -&gt; string option**

**rewrite\_find\_first\_existing path** uses a BUILD\_PATH\_PREFIX\_MAP mapping and tries to find a source in mapping that maps to a result that exists in the file system. There are the following return values:

\- **None** , means either

-BUILD\_PATH\_PREFIX\_MAP is not set and **path** does not exists, or

-no source prefixes of **path** in the mapping were found,

\- **Some target** , means **target** exists and either

-BUILD\_PATH\_PREFIX\_MAP is not set and **target** = **path** , or

\- **target** is the first file (in priority order) that **path** mapped to that exists in the file system.

\- **Not\_found** raised, means some source prefixes in the map were found that matched **path** , but none of them existed in the file system. The caller should catch this and issue an appropriate error message.

See the BUILD\_PATH\_PREFIX\_MAP spec

*val rewrite\_find\_all\_existing\_dirs* : **string -&gt; string list**

**rewrite\_find\_all\_existing\_dirs dir** accumulates a list of existing directories, **dirs** , that are the result of mapping a potentially abstract directory, **dir** , over all the mapping pairs in the BUILD\_PATH\_PREFIX\_MAP environment variable, if any. The list **dirs** will be in priority order (head as highest priority).

The possible results are:

\- **\[]** , means either

-BUILD\_PATH\_PREFIX\_MAP is not set and **dir** is not an existing directory, or

-if set, then there were no matching prefixes of **dir** .

\- **Some dirs** , means dirs are the directories found. Either

-BUILD\_PATH\_PREFIX\_MAP is not set and **dirs = \[dir]** , or

-it was set and **dirs** are the mapped existing directories.

-Not\_found raised, means some source prefixes in the map were found that matched **dir** , but none of mapping results were existing directories (possibly due to misconfiguration). The caller should catch this and issue an appropriate error message.

See the BUILD\_PATH\_PREFIX\_MAP spec

*val absolute\_path* : **string -&gt; string**

**absolute\_path path** first makes an absolute path, **s** from **path** , prepending the current working directory if **path** was relative. Then **s** is rewritten using **rewrite\_absolute\_path** . Finally the result is normalized by eliminating instances of **'.'** or **'..'** .

## [Printing locations](#Printing_locations)

*val show\_filename* : **string -&gt; string**

In -absname mode, return the absolute path for this filename. Otherwise, returns the filename unchanged.

*val print\_filename* : **Format.formatter -&gt; string -&gt; unit**

*val print\_loc* : **Format.formatter -&gt; t -&gt; unit**

*val print\_locs* : **Format.formatter -&gt; t list -&gt; unit**

*val separate\_new\_message* : **Format.formatter -&gt; unit**

*module Doc :* **sig end**

## [Toplevel-specific location highlighting](#Toplevel-specific_location_highlighting)

*val highlight\_terminfo* : **Lexing.lexbuf -&gt; Format.formatter -&gt; t list -&gt; unit**

## [Reporting errors and warnings](#Reporting_errors_and_warnings)

## [The type of reports and report printers](#The_type_of_reports_and_report_printers)

*type msg* = **Format\_doc.t loc**

*val msg* : **?loc:t -&gt;** **('a, Format\_doc.formatter, unit, msg) format4 -&gt; 'a**

*type report\_kind* =  
| Report\_error  
| Report\_warning **of** **string**  
| Report\_warning\_as\_error **of** **string**  
| Report\_alert **of** **string**  
| Report\_alert\_as\_error **of** **string**

*type report* = {  
kind : **report\_kind** ;  
main : **msg** ;  
sub : **msg list** ;  
footnote : **Format\_doc.t option** ;  
}

*type report\_printer* = {  
pp : **report\_printer -&gt; Format.formatter -&gt; report -&gt; unit** ;  
pp\_report\_kind : **report\_printer -&gt;** **report -&gt; Format.formatter -&gt; report\_kind -&gt; unit** ;  
pp\_main\_loc : **report\_printer -&gt;** **report -&gt; Format.formatter -&gt; t -&gt; unit** ;  
pp\_main\_txt : **report\_printer -&gt;** **report -&gt; Format.formatter -&gt; Format\_doc.t -&gt; unit** ;  
pp\_submsgs : **report\_printer -&gt;** **report -&gt; Format.formatter -&gt; msg list -&gt; unit** ;  
pp\_submsg : **report\_printer -&gt;** **report -&gt; Format.formatter -&gt; msg -&gt; unit** ;  
pp\_submsg\_loc : **report\_printer -&gt;** **report -&gt; Format.formatter -&gt; t -&gt; unit** ;  
pp\_submsg\_txt : **report\_printer -&gt;** **report -&gt; Format.formatter -&gt; Format\_doc.t -&gt; unit** ;  
}

A printer for **report** s, defined using open-recursion. The goal is to make it easy to define new printers by reusing code from existing ones.

## [Report printers used in the compiler](#Report_printers_used_in_the_compiler)

*val batch\_mode\_printer* : **report\_printer**

*val terminfo\_toplevel\_printer* : **Lexing.lexbuf -&gt; report\_printer**

*val best\_toplevel\_printer* : **unit -&gt; report\_printer**

Detects the terminal capabilities and selects an adequate printer

## [Printing a report](#Printing_a_report)

*val print\_report* : **Format.formatter -&gt; report -&gt; unit**

Display an error or warning report.

*val report\_printer* : **(unit -&gt; report\_printer) ref**

Hook for redefining the printer of reports.

The hook is a **unit -&gt; report\_printer** and not simply a **report\_printer** : this is useful so that it can detect the type of the output (a file, a terminal, ...) and select a printer accordingly.

*val default\_report\_printer* : **unit -&gt; report\_printer**

Original report printer for use in hooks.

## [Reporting warnings](#Reporting_warnings)

## [Converting a Warnings.t into a report](#Converting_a_Warnings.t_into_a_report)

*val report\_warning* : **t -&gt; Warnings.t -&gt; report option**

**report\_warning loc w** produces a report for the given warning **w** , or **None** if the warning is not to be printed.

*val warning\_reporter* : **(t -&gt; Warnings.t -&gt; report option) ref**

Hook for intercepting warnings.

*val default\_warning\_reporter* : **t -&gt; Warnings.t -&gt; report option**

Original warning reporter for use in hooks.

## [Printing warnings](#Printing_warnings)

*val formatter\_for\_warnings* : **Format.formatter ref**

*val print\_warning* : **t -&gt; Format.formatter -&gt; Warnings.t -&gt; unit**

Prints a warning. This is simply the composition of **report\_warning** and **print\_report** .

*val prerr\_warning* : **t -&gt; Warnings.t -&gt; unit**

Same as **print\_warning** , but uses **!formatter\_for\_warnings** as output formatter.

## [Reporting alerts](#Reporting_alerts)

## [Converting an Alert.t into a report](#Converting_an_Alert.t_into_a_report)

*val report\_alert* : **t -&gt; Warnings.alert -&gt; report option**

**report\_alert loc w** produces a report for the given alert **w** , or **None** if the alert is not to be printed.

*val alert\_reporter* : **(t -&gt; Warnings.alert -&gt; report option) ref**

Hook for intercepting alerts.

*val default\_alert\_reporter* : **t -&gt; Warnings.alert -&gt; report option**

Original alert reporter for use in hooks.

## [Printing alerts](#Printing_alerts)

*val print\_alert* : **t -&gt; Format.formatter -&gt; Warnings.alert -&gt; unit**

Prints an alert. This is simply the composition of **report\_alert** and **print\_report** .

*val prerr\_alert* : **t -&gt; Warnings.alert -&gt; unit**

Same as **print\_alert** , but uses **!formatter\_for\_warnings** as output formatter.

*val deprecated* : **?def:t -&gt; ?use:t -&gt; t -&gt; string -&gt; unit**

Prints a deprecation alert.

*val alert* : **?def:t -&gt;** **?use:t -&gt; kind:string -&gt; t -&gt; string -&gt; unit**

Prints an arbitrary alert.

*val auto\_include\_alert* : **string -&gt; unit**

Prints an alert that -I +lib has been automatically added to the load path

*val deprecated\_script\_alert* : **string -&gt; unit**

**deprecated\_script\_alert command** prints an alert that **command foo** has been deprecated in favour of **command ./foo**

## [Reporting errors](#Reporting_errors)

*type error* = **report**

An **error** is a **report** which **report\_kind** must be **Report\_error** .

*type delayed\_msg* = **unit -&gt; Format\_doc.t option**

*val error* : **?loc:t -&gt;** **?sub:msg list -&gt;** **?footnote:delayed\_msg -&gt; string -&gt; error**

*val errorf* : **?loc:t -&gt;** **?sub:msg list -&gt;** **?footnote:delayed\_msg -&gt;** **('a, Format\_doc.formatter, unit, error) format4 -&gt; 'a**

*val aligned\_error\_hint* : **?loc:t -&gt;** **?sub:msg list -&gt;** **?footnote:delayed\_msg -&gt;** **('a, Format\_doc.formatter, unit, Format\_doc.t option -&gt; error)** **format4 -&gt; 'a**

**aligned\_error\_hint ?loc ?sub ?footnote fmt ... aligned\_hint** produces an error report where the potential **aligned\_hint** message has been aligned with the main error message before being added to the list of submessages.

*val error\_of\_printer* : **?loc:t -&gt;** **?sub:msg list -&gt;** **?footnote:delayed\_msg -&gt;** **(Format\_doc.formatter -&gt; 'a -&gt; unit) -&gt; 'a -&gt; error**

*val error\_of\_printer\_file* : **(Format\_doc.formatter -&gt; 'a -&gt; unit) -&gt; 'a -&gt; error**

## [Automatically reporting errors for raised exceptions](#Automatically_reporting_errors_for_raised_exceptions)

*val register\_error\_of\_exn* : **(exn -&gt; error option) -&gt; unit**

Each compiler module which defines a custom type of exception which can surface as a user-visible error should register a "printer" for this exception using **register\_error\_of\_exn** . The result of the printer is an **error** value containing a location, a message, and optionally sub-messages (each of them being located as well).

*val error\_of\_exn* : **exn -&gt; \[ \`Already\_displayed | \`Ok of error ] option**

*exception Error* **of** **error**

Raising **Error e** signals an error **e** ; the exception will be caught and the error will be printed.

*exception Already\_displayed\_error*

Raising **Already\_displayed\_error** signals an error which has already been printed. The exception will be caught, but nothing will be printed

*val raise\_errorf* : **?loc:t -&gt;** **?sub:msg list -&gt;** **?footnote:delayed\_msg -&gt;** **('a, Format\_doc.formatter, unit, 'b) format4 -&gt; 'a**

*val report\_exception* : **Format.formatter -&gt; exn -&gt; unit**

Reraise the exception if it is unknown.

2026-10-01 OCamldoc

---

Document: Location(3o) from ocaml 5.5.1-r1 (Chainguard OS)
Source: https://github.com/ocaml/ocaml
