---
name: "Location"
section: "3o"
platform: "linux"
package: "ocaml"
version: "5.5.0-1"
release: "Arch Linux 2026-11-01"
platforms: ["linux"]
url: "https://new.carta.tech/Location"
---

# Location(3o)

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

## NAME

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

## Module

Module   Location

## 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 -\> 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 -\> x", since  **Parser.expression (Lexing.from\_string "x = x")** would fail to parse. By contrast, in \`let f = fun x -\> 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 -\> bool**

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

*val in\_file* :  **string -\> t**

Return an empty ghost range located in a given file.

*val init* :  **Lexing.lexbuf -\> string -\> unit**

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

*val curr* :  **Lexing.lexbuf -\> t**

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

*val symbol\_rloc* :  **unit -\> t**

*val symbol\_gloc* :  **unit -\> t**

*val rhs\_loc* :  **int -\> 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 -\> int -\> t**

*val get\_pos\_info* :  **Lexing.position -\> string \* int \* int**

file, line, char

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

*val mknoloc* :  **'a -\> 'a loc**

*val mkloc* :  **'a -\> t -\> 'a loc**

*val map* :  **('a -\> 'b) -\> 'a loc -\> 'b loc**

### 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

*val echo\_eof* :  **unit -\> unit**

*val reset* :  **unit -\> unit**

### Rewriting path

*val rewrite\_absolute\_path* :  **string -\> 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 -\> 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 -\> 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 -\> 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

*val show\_filename* :  **string -\> string**

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

*val print\_filename* :  **Format.formatter -\> string -\> unit**

*val print\_loc* :  **Format.formatter -\> t -\> unit**

*val print\_locs* :  **Format.formatter -\> t list -\> unit**

*val separate\_new\_message* :  **Format.formatter -\> unit**

*module Doc :* **sig end**

### Toplevel-specific location highlighting

*val highlight\_terminfo* :  **Lexing.lexbuf -\> Format.formatter -\> t list -\> unit**

### Reporting errors and warnings

### The type of reports and report printers

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

*val msg* :  **?loc:t -\>** **('a, Format\_doc.formatter, unit, msg) format4 -\> '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 -\> Format.formatter -\> report -\> unit** ;\
  pp\_report\_kind :  **report\_printer -\>** **report -\> Format.formatter -\> report\_kind -\> unit** ;\
  pp\_main\_loc :  **report\_printer -\>** **report -\> Format.formatter -\> t -\> unit** ;\
  pp\_main\_txt :  **report\_printer -\>** **report -\> Format.formatter -\> Format\_doc.t -\> unit** ;\
  pp\_submsgs :  **report\_printer -\>** **report -\> Format.formatter -\> msg list -\> unit** ;\
  pp\_submsg :  **report\_printer -\>** **report -\> Format.formatter -\> msg -\> unit** ;\
  pp\_submsg\_loc :  **report\_printer -\>** **report -\> Format.formatter -\> t -\> unit** ;\
  pp\_submsg\_txt :  **report\_printer -\>** **report -\> Format.formatter -\> Format\_doc.t -\> 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

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

*val terminfo\_toplevel\_printer* :  **Lexing.lexbuf -\> report\_printer**

*val best\_toplevel\_printer* :  **unit -\> report\_printer**

Detects the terminal capabilities and selects an adequate printer

### Printing a report

*val print\_report* :  **Format.formatter -\> report -\> unit**

Display an error or warning report.

*val report\_printer* :  **(unit -\> report\_printer) ref**

Hook for redefining the printer of reports.

The hook is a  **unit -\> 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 -\> report\_printer**

Original report printer for use in hooks.

### Reporting warnings

### Converting a Warnings.t into a report

*val report\_warning* :  **t -\> Warnings.t -\> 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 -\> Warnings.t -\> report option) ref**

Hook for intercepting warnings.

*val default\_warning\_reporter* :  **t -\> Warnings.t -\> report option**

Original warning reporter for use in hooks.

### Printing warnings

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

*val print\_warning* :  **t -\> Format.formatter -\> Warnings.t -\> unit**

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

*val prerr\_warning* :  **t -\> Warnings.t -\> unit**

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

### Reporting alerts

### Converting an Alert.t into a report

*val report\_alert* :  **t -\> Warnings.alert -\> 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 -\> Warnings.alert -\> report option) ref**

Hook for intercepting alerts.

*val default\_alert\_reporter* :  **t -\> Warnings.alert -\> report option**

Original alert reporter for use in hooks.

### Printing alerts

*val print\_alert* :  **t -\> Format.formatter -\> Warnings.alert -\> unit**

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

*val prerr\_alert* :  **t -\> Warnings.alert -\> unit**

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

*val deprecated* :  **?def:t -\> ?use:t -\> t -\> string -\> unit**

Prints a deprecation alert.

*val alert* :  **?def:t -\>** **?use:t -\> kind:string -\> t -\> string -\> unit**

Prints an arbitrary alert.

*val auto\_include\_alert* :  **string -\> unit**

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

*val deprecated\_script\_alert* :  **string -\> unit**

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

### Reporting errors

*type error* =  **report**

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

*type delayed\_msg* =  **unit -\> Format\_doc.t option**

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

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

*val aligned\_error\_hint* :  **?loc:t -\>** **?sub:msg list -\>** **?footnote:delayed\_msg -\>** **('a, Format\_doc.formatter, unit, Format\_doc.t option -\> error)** **format4 -\> '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 -\>** **?sub:msg list -\>** **?footnote:delayed\_msg -\>** **(Format\_doc.formatter -\> 'a -\> unit) -\> 'a -\> error**

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

### Automatically reporting errors for raised exceptions

*val register\_error\_of\_exn* :  **(exn -\> error option) -\> 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 -\> \[ \`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 -\>** **?sub:msg list -\>** **?footnote:delayed\_msg -\>** **('a, Format\_doc.formatter, unit, 'b) format4 -\> 'a**

*val report\_exception* :  **Format.formatter -\> exn -\> unit**

Reraise the exception if it is unknown.
