this repo has no description

Resolution#

Resolution is the process by which we take a value of type Lang.t and look up details of the internal cross references and make sure we know exactly which component is being referred to. Much of the work has been done by the compiler but we need to do a little more. For example, given

module M : sig
  type t
end
type u = M.t 

in the definition of u, the compiler tells us precisely which M is on the right hand side but doesn't say to which t it is referring to; the representation of this is simply the string "t". Resolution is the process of finding precise identifiers that will allow us to construct links.

We'll start with a little preamble, constructing the execution environment in which we can run through some tests and describe the resolution process.

(* Prelude *)
#require "odoc.xref_test";;
open Odoc_xref2;;
open Odoc_xref_test;;
open Odoc_model.Names;;
#install_printer Common.root_pp;;
#install_printer Odoc_model.Names.ValueName.fmt;;
#install_printer Odoc_model.Names.ModuleName.fmt;;
#install_printer Odoc_model.Names.ModuleTypeName.fmt;;
#install_printer Odoc_model.Names.TypeName.fmt;;
#install_printer Odoc_model.Names.ExceptionName.fmt;;
#install_printer Odoc_model.Names.FieldName.fmt;;
#install_printer Odoc_model.Names.PageName.fmt;;
#print_length 65536;;
Odoc_xref2.Component.Delayed.eager := true;;
Odoc_xref2.Tools.disable_all_caches ();;
let id = Common.id;;
let _ = Odoc_model.Names.set_unique_ident "XXXX";;

Simple resolution#

We'll start by examining the simple case - how we deal with module hierarchies, and build up later to the more advanced uses of the module system.

No modules at all#

The simplest possible resolution it simply checking that a resolved path exists. We'll use a helper function Common.signature_of_mli_string to go straight from a text representation of an mli file to the type we would ordinarily read from a compiled cmti file.

let test_data = {|
  type x
  type u = x
|};;
let sg = Common.signature_of_mli_string test_data;;

The type of sg is:

# #show_val sg;;
val sg : Odoc_model.Lang.Signature.t

This Signature.t is a representation of the entire cmti file, and resolution essentially proceeds as map function over this data type: Signature.t -> Signature.t, with the end result having precise identifiers for all elements in the signature.

The first thing we do is to construct an environment from the signature. The environment is simply a mapping from identifiers to items representing each element in the signature. The representations are types declared in the module Component, and follow quite closely those in module Lang, the main difference being in the types of paths. The environment constructed from the above signature is as follows:

# Env.open_signature sg Env.empty;;
- : Env.t = <abstr>

here we can see there are two types in the environment and nothing else. u has identifier `Type (`Root (Common.root, "Root"), "u"), and has an internal identifier of ("u",17). t is abstract and therefore has no manifest, but u has a manifest that points to the `Identifier path that has already been `Resolved to `Identifier `Type (`Root (Common.root, "Root"), "u"). So there won't be much for us to do.

The resolution process proceeds starting from the Lang.Signature.t going down until it finds values that are subtypes of Path.t - for example, a Module.decl is defined as

type decl =
  | Alias of Path.Module.t
  | ModuleType of ModuleType.expr

This type Path.Module.t is a polymorphic variant:

type any = [
  | `Resolved of Resolved_path.module_
  | `Root of string
  | `Forward of string
  | `Dot of module_ * string
  | `Apply of module_ * module_
]

and Resolved_path.module_ is:

type module_ = [
  | `Identifier of Identifier.path_module
  | `Subst of module_type * module_
  | `Alias of module_ * module_
  | `Hidden of module_
  | `Module of module_ * ModuleName.t
  | `Canonical of module_ * Path.module_
  | `Apply of module_ * Path.module_
  | `Alias of module_ * module_
  ]

Once it gets to a Path.t (or a Path.Module.t, Path.Type.t etc.), and looks down the path to find the element. The aim is to have every path start with `Resolved.

In our example above, the first instance of a Path.t is the right hand side of the type u. For the purposes of examining that value, we can define a Lens that extracts just that out of the Signature.t:

let type_manifest name =
  let open Common.LangUtils.Lens in
  Signature.type_ name |-- TypeDecl.equation |-- TypeDecl.Equation.manifest
let u_manifest = type_manifest "u"
let t_manifest = type_manifest "t"
let s_manifest = type_manifest "s"

and using this lens on our original signature we obtain:

# Common.LangUtils.Lens.get u_manifest sg ;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Identifier
      ({Odoc_model__Paths_types.iv =
         `Type
           ({Odoc_model__Paths_types.iv =
              `Root
                (Some
                  {Odoc_model__Paths_types.iv = `Page (None, None);
                   ihash = 236059787; ikey = "p_None"},
                 Root);
             ihash = 818126955; ikey = "r_Root.p_None"},
            x);
        ihash = 622581103; ikey = "t_x.r_Root.p_None"},
       false),
   []))

This path clearly already begins with `Resolved, so we don't expect to change it, but we are going to check it exists. We convert the path into a Cpath.t and call Tools.resolve_type. This function starts approximately:

    | `Resolved r as unresolved ->
        of_result ~unresolved (lookup_type env r) >>=
        fun t -> return (r, t)

and lookup_type starts:


    | `Identifier (`Type _ as i) ->
        of_option ~error:(`Lookup_failure i) (Env.lookup_type i env)
        >>= fun t -> Ok (Find.Found (`T t))

and so we simply look up the type in the environment, giving a Component.Type.t that represents the type.

# Common.compile_signature sg;;
- : Odoc_model.Lang.Signature.t =
{Odoc_model.Lang.Signature.items =
  [Odoc_model.Lang.Signature.Type (Odoc_model.Lang.Signature.Ordinary,
    {Odoc_model.Lang.TypeDecl.id =
      {Odoc_model__Paths_types.iv =
        `Type
          ({Odoc_model__Paths_types.iv =
             `Root
               (Some
                 {Odoc_model__Paths_types.iv = `Page (None, None);
                  ihash = 236059787; ikey = "p_None"},
                Root);
            ihash = 818126955; ikey = "r_Root.p_None"},
           x);
       ihash = 622581103; ikey = "t_x.r_Root.p_None"};
     source_loc = None;
     doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
     canonical = None;
     equation =
      {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false;
       manifest = None; constraints = []};
     representation = None});
   Odoc_model.Lang.Signature.Type (Odoc_model.Lang.Signature.Ordinary,
    {Odoc_model.Lang.TypeDecl.id =
      {Odoc_model__Paths_types.iv =
        `Type
          ({Odoc_model__Paths_types.iv =
             `Root
               (Some
                 {Odoc_model__Paths_types.iv = `Page (None, None);
                  ihash = 236059787; ikey = "p_None"},
                Root);
            ihash = 818126955; ikey = "r_Root.p_None"},
           u);
       ihash = 15973539; ikey = "t_u.r_Root.p_None"};
     source_loc = None;
     doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
     canonical = None;
     equation =
      {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false;
       manifest =
        Some
         (Odoc_model.Lang.TypeExpr.Constr
           (`Resolved
              (`Identifier
                 {Odoc_model__Paths_types.iv =
                   `Type
                     ({Odoc_model__Paths_types.iv =
                        `Root
                          (Some
                            {Odoc_model__Paths_types.iv = `Page (None, None);
                             ihash = 236059787; ikey = "p_None"},
                           Root);
                       ihash = 818126955; ikey = "r_Root.p_None"},
                      x);
                  ihash = 622581103; ikey = "t_x.r_Root.p_None"}),
           []));
       constraints = []};
     representation = None})];
 compiled = true; removed = [];
 doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}}

One module#

Now let's look at a marginally more complicated example. In this case, our type [t] is now inside a module:

let test_data = {|
module M : sig
    type t
end
type u = M.t
|};;
let sg = Common.signature_of_mli_string test_data;;
let env = Env.open_signature sg Env.empty;;

The OCaml compiler find the module M exactly, but everything after that is left to us to identify precisely. So the manifest of u is now:

# Common.LangUtils.Lens.get u_manifest sg ;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`DotT
      (`Identifier
         ({Odoc_model__Paths_types.iv =
            `Module
              ({Odoc_model__Paths_types.iv =
                 `Root
                   (Some
                     {Odoc_model__Paths_types.iv = `Page (None, None);
                      ihash = 236059787; ikey = "p_None"},
                    Root);
                ihash = 818126955; ikey = "r_Root.p_None"},
               M);
           ihash = 716453475; ikey = "m_M.r_Root.p_None"},
          false),
       t),
   []))

Here we can see that the path is not completely resolved. The M bit is resolved, but the t bit is not. So we have to do a bit more work when we look up the type in Tools.resolve_type.

Let's look in more detail at that process. The first thing that happens is that the path is matched the [`Dot] is found:

   | `Dot (parent, id) ->
        resolve_module env parent
        >>= fun (p, m) ->

This implies that the thing before the dot is a module, so we call Tools.resolve_module. This is a resolved identifier so we can simply look this up from the environment. This gets us back the path and a Component.Module.t representing the module M, which are:

# let get_ok = function
    | Ok x -> x
    | Error _ -> failwith "Found error";;
val get_ok : ('a, 'b) result -> 'a = <fun>
# let (path, module_) = get_ok @@ Tools.resolve_module env (`Resolved (`Gpath (`Identifier (Common.root_module "M"))));;
val path : Cpath.Resolved.module_ =
  `Gpath
    (`Identifier
       {Odoc_model__Paths_types.iv =
         `Module
           ({Odoc_model__Paths_types.iv =
              `Root
                (Some
                  {Odoc_model__Paths_types.iv = `Page (None, None);
                   ihash = 236059787; ikey = "p_None"},
                 Root);
             ihash = 818126955; ikey = "r_Root.p_None"},
            M);
        ihash = 716453475; ikey = "m_M.r_Root.p_None"})
val module_ : Component.Module.t Component.Delayed.t =
  {Odoc_xref2.Component.Delayed.v =
    Some
     {Odoc_xref2.Component.Module.source_loc = None;
      doc =
       {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None};
      type_ =
       Odoc_xref2.Component.Module.ModuleType
        (Odoc_xref2.Component.ModuleType.Signature
          {Odoc_xref2.Component.Signature.items =
            [Odoc_xref2.Component.Signature.Type (`LType (t, 0),
              Odoc_model.Lang.Signature.Ordinary,
              {Odoc_xref2.Component.Delayed.v =
                Some
                 {Odoc_xref2.Component.TypeDecl.source_loc = None;
                  doc =
                   {Odoc_xref2.Component.CComment.elements = [];
                    warnings_tag = None};
                  canonical = None;
                  equation =
                   {Odoc_xref2.Component.TypeDecl.Equation.params = [];
                    private_ = false; manifest = None; constraints = []};
                  representation = None};
               get = None})];
           compiled = false; removed = [];
           doc =
            {Odoc_xref2.Component.CComment.elements = [];
             warnings_tag = None}});
      canonical = None; hidden = false};
   get = None}

The values returned are the resolved path to the module, and a representation of the module itself. We then turn the module into a signature via expansion_of_module, which in this case is quite simple since the module contains an explicit signature:

# get_ok @@ Tools.expansion_of_module env (Component.Delayed.get module_);;
- : Tools.expansion =
Odoc_xref2.Tools.Signature
 {Odoc_xref2.Component.Signature.items =
   [Odoc_xref2.Component.Signature.Type (`LType (t, 0),
     Odoc_model.Lang.Signature.Ordinary,
     {Odoc_xref2.Component.Delayed.v =
       Some
        {Odoc_xref2.Component.TypeDecl.source_loc = None;
         doc =
          {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None};
         canonical = None;
         equation =
          {Odoc_xref2.Component.TypeDecl.Equation.params = [];
           private_ = false; manifest = None; constraints = []};
         representation = None};
      get = None})];
  compiled = false; removed = [];
  doc = {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None}}

We're now in a position to verify the existence of the type t we're looking up - and indeed it is there. We therefore construct the new resolved path to this type : `Type (path, "t"), and return this and the definition of the type, which in this case is uninteresting.

Indirection#

Let's now examine the case when a module's signature has to be found from the environment.

let test_data = {|
module type M = sig
    type t
end
module N : M
type u = N.t
|};;
let sg = Common.signature_of_mli_string test_data;;
let env = Env.open_signature sg Env.empty;;

It proceeds much as the previous example until we get the result of looking up the module N:

# let (path, module_) = get_ok @@ Tools.resolve_module env (`Resolved (`Gpath (`Identifier (Common.root_module "N"))));;
val path : Cpath.Resolved.module_ =
  `Gpath
    (`Identifier
       {Odoc_model__Paths_types.iv =
         `Module
           ({Odoc_model__Paths_types.iv =
              `Root
                (Some
                  {Odoc_model__Paths_types.iv = `Page (None, None);
                   ihash = 236059787; ikey = "p_None"},
                 Root);
             ihash = 818126955; ikey = "r_Root.p_None"},
            N);
        ihash = 502470005; ikey = "m_N.r_Root.p_None"})
val module_ : Component.Module.t Component.Delayed.t =
  {Odoc_xref2.Component.Delayed.v =
    Some
     {Odoc_xref2.Component.Module.source_loc = None;
      doc =
       {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None};
      type_ =
       Odoc_xref2.Component.Module.ModuleType
        (Odoc_xref2.Component.ModuleType.Path
          {Odoc_xref2.Component.ModuleType.p_expansion = None;
           p_path =
            `Identifier
              ({Odoc_model__Paths_types.iv =
                 `ModuleType
                   ({Odoc_model__Paths_types.iv =
                      `Root
                        (Some
                          {Odoc_model__Paths_types.iv = `Page (None, None);
                           ihash = 236059787; ikey = "p_None"},
                         Root);
                     ihash = 818126955; ikey = "r_Root.p_None"},
                    M);
                ihash = 459143770; ikey = "mt_M.r_Root.p_None"},
               false)});
      canonical = None; hidden = false};
   get = None}

This time turning the module into a signature demonstrates why the function expansion_of_module requires the environment. We need to lookup the module type M from the environment to determine the signature of the module. After this though the resolution is as before.

Local paths#

We now look at an example involving local paths. These paths happen when a path refers to something that isn't in the toplevel environment. We'll use the following example to explain the idea:

let test_data = {|
module type M = sig
    module type N = sig
        type t
    end
    module B : N
end
module A : M
type u = A.B.t
|};;
let sg = Common.signature_of_mli_string test_data;;
let env = Env.open_signature sg Env.empty;;

The definition of module B constrains it to have a signature given by the module type N. However, N is not defined at the top level here, so it has a local identifier. We can see this by looking up module M from the environment:

# let m = Env.(lookup_by_id s_module_type) (Odoc_model.Paths.Identifier.Mk.module_type (Common.id, Odoc_model.Names.ModuleTypeName.make_std "M")) env;;
val m : Component.Element.module_type option =
  Some
   (`ModuleType
      ({Odoc_model__Paths_types.iv =
         `ModuleType
           ({Odoc_model__Paths_types.iv =
              `Root
                (Some
                  {Odoc_model__Paths_types.iv = `Page (None, None);
                   ihash = 236059787; ikey = "p_None"},
                 Root);
             ihash = 818126955; ikey = "r_Root.p_None"},
            M);
        ihash = 459143770; ikey = "mt_M.r_Root.p_None"},
       {Odoc_xref2.Component.ModuleType.source_loc = None;
        doc =
         {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None};
        canonical = None;
        expr =
         Some
          (Odoc_xref2.Component.ModuleType.Signature
            {Odoc_xref2.Component.Signature.items =
              [Odoc_xref2.Component.Signature.ModuleType
                (`LModuleType (N, 1),
                {Odoc_xref2.Component.Delayed.v =
                  Some
                   {Odoc_xref2.Component.ModuleType.source_loc = None;
                    doc =
                     {Odoc_xref2.Component.CComment.elements = [];
                      warnings_tag = None};
                    canonical = None;
                    expr =
                     Some
                      (Odoc_xref2.Component.ModuleType.Signature
                        {Odoc_xref2.Component.Signature.items =
                          [Odoc_xref2.Component.Signature.Type
                            (`LType (t, 2),
                            Odoc_model.Lang.Signature.Ordinary,
                            {Odoc_xref2.Component.Delayed.v =
                              Some
                               {Odoc_xref2.Component.TypeDecl.source_loc =
                                 None;
                                doc =
                                 {Odoc_xref2.Component.CComment.elements = [];
                                  warnings_tag = None};
                                canonical = None;
                                equation =
                                 {Odoc_xref2.Component.TypeDecl.Equation.params
                                   = [];
                                  private_ = false; manifest = None;
                                  constraints = []};
                                representation = None};
                             get = None})];
                         compiled = false; removed = [];
                         doc =
                          {Odoc_xref2.Component.CComment.elements = [];
                           warnings_tag = None}})};
                 get = None});
               Odoc_xref2.Component.Signature.Module (`LModule (B, 0),
                Odoc_model.Lang.Signature.Ordinary,
                {Odoc_xref2.Component.Delayed.v =
                  Some
                   {Odoc_xref2.Component.Module.source_loc = None;
                    doc =
                     {Odoc_xref2.Component.CComment.elements = [];
                      warnings_tag = None};
                    type_ =
                     Odoc_xref2.Component.Module.ModuleType
                      (Odoc_xref2.Component.ModuleType.Path
                        {Odoc_xref2.Component.ModuleType.p_expansion = None;
                         p_path = `Local (`LModuleType (N, 1), false)});
                    canonical = None; hidden = false};
                 get = None})];
             compiled = false; removed = [];
             doc =
              {Odoc_xref2.Component.CComment.elements = [];
               warnings_tag = None}})}))

We can see here that module B has type Path (`Resolved (`Local (`LModuleType (N, 1)))) which refers to the module type defined just above it.

To look up we need to have fully qualified paths for all items so this needs some work. The way this is handled is that when we want to look up an element within a module, we don't just convert it blindly to a signature. Since we have the fully qualified path to the module, we prefix all the identifiers bound in that signature with that path to turn them into global identifiers.

Concretely, we start here wanting to resolve the path for type u, which is A.B.t. The compiler has started us off by resolving the A:

# Common.LangUtils.Lens.get u_manifest sg ;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`DotT
      (`Dot
         (`Identifier
            ({Odoc_model__Paths_types.iv =
               `Module
                 ({Odoc_model__Paths_types.iv =
                    `Root
                      (Some
                        {Odoc_model__Paths_types.iv = `Page (None, None);
                         ihash = 236059787; ikey = "p_None"},
                       Root);
                   ihash = 818126955; ikey = "r_Root.p_None"},
                  A);
              ihash = 353272258; ikey = "m_A.r_Root.p_None"},
             false),
          B),
       t),
   []))

we look up A from the environment:

# let p = `Gpath (`Identifier (Common.root_module "A")) in
  let m = get_ok @@ Tools.lookup_module env p in
  let sg = get_ok @@ Tools.expansion_of_module env (Component.Delayed.get m) in
  Tools.prefix_signature (`Module p, sg);;
Line 4, characters 38-40:
Error: The value sg has type Tools.expansion
       but an expression was expected of type Component.Signature.t

So before the prefixing operation we had that the type of the module was

   type_ =
      Odoc_xref2.Component.Module.ModuleType
      (Odoc_xref2.Component.ModuleType.Path
         (`Resolved (`Local (`LModuleType (N, 1)))));

and afterwards it is

   type_ =
   Odoc_xref2.Component.Module.ModuleType
      (Odoc_xref2.Component.ModuleType.Path
      (`Resolved
         (`ModuleType
            (`Module
               (`Identifier (`Module (`Root (Common.root, Root), A))),
               N))));

We now look up module B from this signature, which once again we need to convert to a signature to find t. We find the type above, which we can then convert in turn into a signature. Once again, we go down the path until we find the identifier (A in this case), look that up from the environment, then look up the module type N. We can then turn this into the signature for B, prefixing local paths with the resolved path A.B (though in this case there are now no local identifiers.) Finally we can now look up t, which we then return along with the fully resolved identifier.

# fst @@ get_ok @@ Tools.resolve_type env
    (`DotT
      (`Dot
         (`Resolved
            (`Gpath (`Identifier (Common.root_module "A"))),
          ModuleName.make_std "B"),
       TypeName.make_std "t"));;
- : Cpath.Resolved.type_ =
`Type
  (`Module
     (`Module
        (`Module
           (`Gpath
              (`Identifier
                 {Odoc_model__Paths_types.iv =
                   `Module
                     ({Odoc_model__Paths_types.iv =
                        `Root
                          (Some
                            {Odoc_model__Paths_types.iv = `Page (None, None);
                             ihash = 236059787; ikey = "p_None"},
                           Root);
                       ihash = 818126955; ikey = "r_Root.p_None"},
                      A);
                  ihash = 353272258; ikey = "m_A.r_Root.p_None"})),
         B)),
   t)

Module aliases#

let test_data = {|
module A : sig
  module M : sig type t end
  module N = M
end

type t = A.N.t
|}
let sg = Common.signature_of_mli_string test_data;;
let resolved = Common.compile_signature sg;;

Let's look at t's manifest:

# Common.LangUtils.Lens.get t_manifest resolved ;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Alias
            (`Module
               (`Identifier
                  {Odoc_model__Paths_types.iv =
                    `Module
                      ({Odoc_model__Paths_types.iv =
                         `Root
                           (Some
                             {Odoc_model__Paths_types.iv = `Page (None, None);
                              ihash = 236059787; ikey = "p_None"},
                            Root);
                        ihash = 818126955; ikey = "r_Root.p_None"},
                       A);
                   ihash = 353272258; ikey = "m_A.r_Root.p_None"},
                M),
             `Dot
               (`Identifier
                  ({Odoc_model__Paths_types.iv =
                     `Module
                       ({Odoc_model__Paths_types.iv =
                          `Root
                            (Some
                              {Odoc_model__Paths_types.iv =
                                `Page (None, None);
                               ihash = 236059787; ikey = "p_None"},
                             Root);
                         ihash = 818126955; ikey = "r_Root.p_None"},
                        A);
                    ihash = 353272258; ikey = "m_A.r_Root.p_None"},
                   false),
                N)),
          t)),
   []))

When we turn A.N.t into a link, we need to render A.N.t as the link text (going down the right-hand side of the Alias constructor), but link to A.M.t since A.N will not have an expansion.

let test_data = {|
module A : sig
  module M : sig type t end
  module N = M
  module O = N
end

type t = A.O.t
|}
let sg = Common.signature_of_mli_string test_data;;
let resolved = Common.compile_signature sg;;
# Common.LangUtils.Lens.get t_manifest resolved ;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Alias
            (`Alias
               (`Module
                  (`Identifier
                     {Odoc_model__Paths_types.iv =
                       `Module
                         ({Odoc_model__Paths_types.iv =
                            `Root
                              (Some
                                {Odoc_model__Paths_types.iv =
                                  `Page (None, None);
                                 ihash = 236059787; ikey = "p_None"},
                               Root);
                           ihash = 818126955; ikey = "r_Root.p_None"},
                          A);
                      ihash = 353272258; ikey = "m_A.r_Root.p_None"},
                   M),
                `Dot
                  (`Identifier
                     ({Odoc_model__Paths_types.iv =
                        `Module
                          ({Odoc_model__Paths_types.iv =
                             `Root
                               (Some
                                 {Odoc_model__Paths_types.iv =
                                   `Page (None, None);
                                  ihash = 236059787; ikey = "p_None"},
                                Root);
                            ihash = 818126955; ikey = "r_Root.p_None"},
                           A);
                       ihash = 353272258; ikey = "m_A.r_Root.p_None"},
                      false),
                   N)),
             `Dot
               (`Identifier
                  ({Odoc_model__Paths_types.iv =
                     `Module
                       ({Odoc_model__Paths_types.iv =
                          `Root
                            (Some
                              {Odoc_model__Paths_types.iv =
                                `Page (None, None);
                               ihash = 236059787; ikey = "p_None"},
                             Root);
                         ihash = 818126955; ikey = "r_Root.p_None"},
                        A);
                    ihash = 353272258; ikey = "m_A.r_Root.p_None"},
                   false),
                O)),
          t)),
   []))

Module substitution#

We'll now look at a case where we perform a module substitution on a signature.

In the following example we have an interesting case where we have a module with a module type in it, and we make a substitution of this module.

let test_data = {|
module type A = sig
module M : sig module type S end
module N : M.S
end

module B : sig module type S = sig type t end end

module C : A with module M = B

type t = C.N.t
|};;
let sg = Common.signature_of_mli_string test_data;;
let resolved = Common.compile_signature sg;;
let env = Env.open_signature sg Env.empty;;

So in module type A, module N has type M.S, which does not contain a declaration for type t. When we make the substitution, although we're substituting M, because the signature of N is M.S, we also change N. So in module C, N should now contain a type t.

Once again, we look at the resolution of type t = C.N.t. When we look up the module C we find that the type_ field look as follows:

# let module_C_lens =
  let open Common.LangUtils.Lens in
  Signature.module_ "C";;
val module_C_lens :
  (Odoc_model.Lang.Signature.t, Odoc_model.Lang.Module.t)
  Common.LangUtils.Lens.lens =
  {Odoc_xref_test.Common.LangUtils.Lens.get = <fun>; set = <fun>}
# Common.LangUtils.Lens.get module_C_lens sg;;
- : Odoc_model.Lang.Module.t =
{Odoc_model.Lang.Module.id =
  {Odoc_model__Paths_types.iv =
    `Module
      ({Odoc_model__Paths_types.iv =
         `Root
           (Some
             {Odoc_model__Paths_types.iv = `Page (None, None);
              ihash = 236059787; ikey = "p_None"},
            Root);
        ihash = 818126955; ikey = "r_Root.p_None"},
       C);
   ihash = 43786577; ikey = "m_C.r_Root.p_None"};
 source_loc = None;
 doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
 type_ =
  Odoc_model.Lang.Module.ModuleType
   (Odoc_model.Lang.ModuleType.With
     {Odoc_model.Lang.ModuleType.w_substitutions =
       [Odoc_model.Lang.ModuleType.ModuleEq (`Dot (`Root, "M"),
         Odoc_model.Lang.Module.Alias
          (`Identifier
             ({Odoc_model__Paths_types.iv =
                `Module
                  ({Odoc_model__Paths_types.iv =
                     `Root
                       (Some
                         {Odoc_model__Paths_types.iv = `Page (None, None);
                          ihash = 236059787; ikey = "p_None"},
                        Root);
                    ihash = 818126955; ikey = "r_Root.p_None"},
                   B);
               ihash = 814134997; ikey = "m_B.r_Root.p_None"},
              false),
           None))];
      w_expansion = None;
      w_expr =
       Odoc_model.Lang.ModuleType.U.Path
        (`Identifier
           ({Odoc_model__Paths_types.iv =
              `ModuleType
                ({Odoc_model__Paths_types.iv =
                   `Root
                     (Some
                       {Odoc_model__Paths_types.iv = `Page (None, None);
                        ihash = 236059787; ikey = "p_None"},
                      Root);
                  ihash = 818126955; ikey = "r_Root.p_None"},
                 A);
             ihash = 231492881; ikey = "mt_A.r_Root.p_None"},
            false))});
 canonical = None; hidden = false}

Clearly there is no type t declared in here. Let's get the representation of module C we see the following:

# let m = get_ok @@ Tools.lookup_module env (`Gpath (`Identifier (Common.root_module "C")));;
val m : Component.Module.t Component.Delayed.t =
  {Odoc_xref2.Component.Delayed.v =
    Some
     {Odoc_xref2.Component.Module.source_loc = None;
      doc =
       {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None};
      type_ =
       Odoc_xref2.Component.Module.ModuleType
        (Odoc_xref2.Component.ModuleType.With
          {Odoc_xref2.Component.ModuleType.w_substitutions =
            [Odoc_xref2.Component.ModuleType.ModuleEq (`Dot (`Root, "M"),
              Odoc_xref2.Component.Module.Alias
               (`Identifier
                  ({Odoc_model__Paths_types.iv =
                     `Module
                       ({Odoc_model__Paths_types.iv =
                          `Root
                            (Some
                              {Odoc_model__Paths_types.iv =
                                `Page (None, None);
                               ihash = 236059787; ikey = "p_None"},
                             Root);
                         ihash = 818126955; ikey = "r_Root.p_None"},
                        B);
                    ihash = 814134997; ikey = "m_B.r_Root.p_None"},
                   false),
               None))];
           w_expansion = None;
           w_expr =
            Odoc_xref2.Component.ModuleType.U.Path
             (`Identifier
                ({Odoc_model__Paths_types.iv =
                   `ModuleType
                     ({Odoc_model__Paths_types.iv =
                        `Root
                          (Some
                            {Odoc_model__Paths_types.iv = `Page (None, None);
                             ihash = 236059787; ikey = "p_None"},
                           Root);
                       ihash = 818126955; ikey = "r_Root.p_None"},
                      A);
                  ihash = 231492881; ikey = "mt_A.r_Root.p_None"},
                 false))});
      canonical = None; hidden = false};
   get = None}

now we can ask for the signature of this module:

# let sg = get_ok @@ Tools.expansion_of_module env (Component.Delayed.get m);;
val sg : Tools.expansion =
  Odoc_xref2.Tools.Signature
   {Odoc_xref2.Component.Signature.items =
     [Odoc_xref2.Component.Signature.Module (`LModule (M, 31),
       Odoc_model.Lang.Signature.Ordinary,
       {Odoc_xref2.Component.Delayed.v =
         Some
          {Odoc_xref2.Component.Module.source_loc = None;
           doc =
            {Odoc_xref2.Component.CComment.elements = [];
             warnings_tag = None};
           type_ =
            Odoc_xref2.Component.Module.Alias
             (`Identifier
                ({Odoc_model__Paths_types.iv =
                   `Module
                     ({Odoc_model__Paths_types.iv =
                        `Root
                          (Some
                            {Odoc_model__Paths_types.iv = `Page (None, None);
                             ihash = 236059787; ikey = "p_None"},
                           Root);
                       ihash = 818126955; ikey = "r_Root.p_None"},
                      B);
                  ihash = 814134997; ikey = "m_B.r_Root.p_None"},
                 false),
             None);
           canonical = None; hidden = false};
        get = None});
      Odoc_xref2.Component.Signature.Module (`LModule (N, 32),
       Odoc_model.Lang.Signature.Ordinary,
       {Odoc_xref2.Component.Delayed.v =
         Some
          {Odoc_xref2.Component.Module.source_loc = None;
           doc =
            {Odoc_xref2.Component.CComment.elements = [];
             warnings_tag = None};
           type_ =
            Odoc_xref2.Component.Module.ModuleType
             (Odoc_xref2.Component.ModuleType.Path
               {Odoc_xref2.Component.ModuleType.p_expansion = None;
                p_path =
                 `DotMT (`Substituted (`Local (`LModule (M, 31), false)), S)});
           canonical = None; hidden = false};
        get = None})];
    compiled = false; removed = [];
    doc = {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None}}

and we can see the module M is now an alias of the root module B. We can now look up module N from within this and find its signature:

# let m = get_ok @@ Tools.lookup_module env
      (`Module (`Module (`Gpath (`Identifier (Common.root_module "C"))), ModuleName.make_std "N"));;
val m : Component.Module.t Component.Delayed.t =
  {Odoc_xref2.Component.Delayed.v =
    Some
     {Odoc_xref2.Component.Module.source_loc = None;
      doc =
       {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None};
      type_ =
       Odoc_xref2.Component.Module.ModuleType
        (Odoc_xref2.Component.ModuleType.Path
          {Odoc_xref2.Component.ModuleType.p_expansion = None;
           p_path =
            `DotMT
              (`Substituted
                 (`Module
                    (`Module
                       (`Gpath
                          (`Identifier
                             {Odoc_model__Paths_types.iv =
                               `Module
                                 ({Odoc_model__Paths_types.iv =
                                    `Root
                                      (Some
                                        {Odoc_model__Paths_types.iv =
                                          `Page (None, None);
                                         ihash = 236059787; ikey = "p_None"},
                                       Root);
                                   ihash = 818126955; ikey = "r_Root.p_None"},
                                  C);
                              ihash = 43786577; ikey = "m_C.r_Root.p_None"})),
                     M)),
               S)});
      canonical = None; hidden = false};
   get = None}
# get_ok @@ Tools.expansion_of_module env (Component.Delayed.get m);;
- : Tools.expansion =
Odoc_xref2.Tools.Signature
 {Odoc_xref2.Component.Signature.items =
   [Odoc_xref2.Component.Signature.Type (`LType (t, 41),
     Odoc_model.Lang.Signature.Ordinary,
     {Odoc_xref2.Component.Delayed.v =
       Some
        {Odoc_xref2.Component.TypeDecl.source_loc = None;
         doc =
          {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None};
         canonical = None;
         equation =
          {Odoc_xref2.Component.TypeDecl.Equation.params = [];
           private_ = false; manifest = None; constraints = []};
         representation = None};
      get = None})];
  compiled = false; removed = [];
  doc = {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None}}

where we've correctly identified that a type t exists in the signature. The path in type t is resolved as:

# Common.LangUtils.Lens.get t_manifest resolved;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Module
            (`Identifier
               {Odoc_model__Paths_types.iv =
                 `Module
                   ({Odoc_model__Paths_types.iv =
                      `Root
                        (Some
                          {Odoc_model__Paths_types.iv = `Page (None, None);
                           ihash = 236059787; ikey = "p_None"},
                         Root);
                     ihash = 818126955; ikey = "r_Root.p_None"},
                    C);
                ihash = 43786577; ikey = "m_C.r_Root.p_None"},
             N),
          t)),
   []))

Interesting functor#

let test_data = {|
module M : sig
  module F(X : sig module type S end) : sig
    module type S = X.S
    module N : X.S
  end
  module T : sig
    module type S = sig type t end
  end
  module O : F(T).S
end
type t = M.O.t
type s = M.F(M.T).N.t
|};;
let sg = Common.signature_of_mli_string test_data;;
let t_manifest = type_manifest "t";;
let s_manifest = type_manifest "s";;
let resolved = Common.compile_signature sg;;

The interesting thing here is the difference between type t and type s. The module M.O has a concrete representation in the file and the expansion of this will contain a declaration of type t - hence the path representing M.O.t does not need a Subst constructor in it. However, the path to M.F(M.T).N.t can't point directly at a type within a module as there isn't one - in some sense F(M.T) is making a brand new module on the fly without binding it anywhere, and the type within this is not within the body of the functor itself.

# Common.LangUtils.Lens.get (type_manifest "t") resolved;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Subst
            (`AliasModuleType
               (`ModuleType
                  (`Substituted
                     (`Module
                        (`Identifier
                           {Odoc_model__Paths_types.iv =
                             `Module
                               ({Odoc_model__Paths_types.iv =
                                  `Root
                                    (Some
                                      {Odoc_model__Paths_types.iv =
                                        `Page (None, None);
                                       ihash = 236059787; ikey = "p_None"},
                                     Root);
                                 ihash = 818126955; ikey = "r_Root.p_None"},
                                M);
                            ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                         T)),
                   S),
                `SubstT
                  (`ModuleType
                     (`Substituted
                        (`Module
                           (`Identifier
                              {Odoc_model__Paths_types.iv =
                                `Module
                                  ({Odoc_model__Paths_types.iv =
                                     `Root
                                       (Some
                                         {Odoc_model__Paths_types.iv =
                                           `Page (None, None);
                                          ihash = 236059787; ikey = "p_None"},
                                        Root);
                                    ihash = 818126955;
                                    ikey = "r_Root.p_None"},
                                   M);
                               ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                            T)),
                      S),
                   `ModuleType
                     (`Apply
                        (`Module
                           (`Identifier
                              {Odoc_model__Paths_types.iv =
                                `Module
                                  ({Odoc_model__Paths_types.iv =
                                     `Root
                                       (Some
                                         {Odoc_model__Paths_types.iv =
                                           `Page (None, None);
                                          ihash = 236059787; ikey = "p_None"},
                                        Root);
                                    ihash = 818126955;
                                    ikey = "r_Root.p_None"},
                                   M);
                               ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                            F),
                         `Module
                           (`Identifier
                              {Odoc_model__Paths_types.iv =
                                `Module
                                  ({Odoc_model__Paths_types.iv =
                                     `Root
                                       (Some
                                         {Odoc_model__Paths_types.iv =
                                           `Page (None, None);
                                          ihash = 236059787; ikey = "p_None"},
                                        Root);
                                    ihash = 818126955;
                                    ikey = "r_Root.p_None"},
                                   M);
                               ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                            T)),
                      S))),
             `Module
               (`Identifier
                  {Odoc_model__Paths_types.iv =
                    `Module
                      ({Odoc_model__Paths_types.iv =
                         `Root
                           (Some
                             {Odoc_model__Paths_types.iv = `Page (None, None);
                              ihash = 236059787; ikey = "p_None"},
                            Root);
                        ihash = 818126955; ikey = "r_Root.p_None"},
                       M);
                   ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                O)),
          t)),
   []))
# Common.LangUtils.Lens.get (type_manifest "s") resolved;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Subst
            (`ModuleType
               (`Substituted
                  (`Module
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             M);
                         ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                      T)),
                S),
             `Module
               (`Apply
                  (`Module
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             M);
                         ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                      F),
                   `Module
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             M);
                         ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                      T)),
                N)),
          t)),
   []))

In the following example, type t does not require a Subst constructor since although the pattern is the same as above -- that a new type t appears in module O despite not being present in the definition of the functor -- because the module O is bound it will be expanded in the expansion phase of odoc's work, and hence we can simply point right inside the module.

We distinguish between the two cases via the is_resolve parameter, which is true when we are directly resolving a path, but false when we simply wish to look up the signature of a module.

let test_data = {|
module M : sig
  module F(X : sig module type S end) : sig
    module type S = sig
      module N : X.S
    end
  end
  module T : sig
    module type S = sig type t end
  end
  module O : F(T).S
end
type t = M.O.N.t
|}
let sg = Common.signature_of_mli_string test_data;;
let env = Env.open_signature sg Env.empty;;
let resolved = Common.compile_signature sg;;
# Common.LangUtils.Lens.get t_manifest resolved;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Subst
            (`ModuleType
               (`Substituted
                  (`Module
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             M);
                         ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                      T)),
                S),
             `Module
               (`Module
                  (`Identifier
                     {Odoc_model__Paths_types.iv =
                       `Module
                         ({Odoc_model__Paths_types.iv =
                            `Root
                              (Some
                                {Odoc_model__Paths_types.iv =
                                  `Page (None, None);
                                 ihash = 236059787; ikey = "p_None"},
                               Root);
                           ihash = 818126955; ikey = "r_Root.p_None"},
                          M);
                      ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                   O),
                N)),
          t)),
   []))

This following example also shouldn't have a Subst, since although as before we're effectively constructing a new module M.O(M) on the fly here, the subsequent path .N.t is actually present in the body of the functor and is independent of the argument (in fact, the argument in this case is totally ignored). Consequently the resolution proceeds without encountering a Substituted node and we therefore don't end up putting a Subst node in the returned path.

let test_data = {|
module M : sig
  module F(X : sig module type S end) : sig
    module type S = sig
      module N : X.S
    end
  end
  module T : sig
    module type S = sig type t end
  end
  module O : functor (X : sig end) -> F(T).S
end
type t = M.O(M.T).N.t
|}
let sg = Common.signature_of_mli_string test_data;;
let env = Env.open_signature sg Env.empty;;
let resolved = Common.compile_signature sg;;
# Common.LangUtils.Lens.get t_manifest resolved;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Subst
            (`ModuleType
               (`Substituted
                  (`Module
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             M);
                         ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                      T)),
                S),
             `Module
               (`Apply
                  (`Module
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             M);
                         ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                      O),
                   `Module
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             M);
                         ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                      T)),
                N)),
          t)),
   []))

Higher order functors#

Functors may take other functors as arguments. In the following example we have a complex functor where type of the 3rd argument is dependent on the first two:

let test_data = {|
module type Type = sig module type T end
module App : functor (T : Type) (F : Type -> Type) (M : F(T).T) -> F(T).T
module Bar : sig module type T = sig type bar end end
module Foo :
  functor (T : Type) -> sig module type T = sig module Foo : T.T end end
module FooBarInt : sig module Foo : sig type bar = int end end
type t = App(Bar)(Foo)(FooBarInt).Foo.bar
|}
let sg = Common.signature_of_mli_string test_data;;
let env = Env.open_signature sg Env.empty;;

The type path we're trying to look up is:

# Common.LangUtils.Lens.get (type_manifest "t") sg;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`DotT
      (`Dot
         (`Apply
            (`Apply
               (`Apply
                  (`Identifier
                     ({Odoc_model__Paths_types.iv =
                        `Module
                          ({Odoc_model__Paths_types.iv =
                             `Root
                               (Some
                                 {Odoc_model__Paths_types.iv =
                                   `Page (None, None);
                                  ihash = 236059787; ikey = "p_None"},
                                Root);
                            ihash = 818126955; ikey = "r_Root.p_None"},
                           App);
                       ihash = 855073208; ikey = "m_App.r_Root.p_None"},
                      false),
                   `Identifier
                     ({Odoc_model__Paths_types.iv =
                        `Module
                          ({Odoc_model__Paths_types.iv =
                             `Root
                               (Some
                                 {Odoc_model__Paths_types.iv =
                                   `Page (None, None);
                                  ihash = 236059787; ikey = "p_None"},
                                Root);
                            ihash = 818126955; ikey = "r_Root.p_None"},
                           Bar);
                       ihash = 608577; ikey = "m_Bar.r_Root.p_None"},
                      false)),
                `Identifier
                  ({Odoc_model__Paths_types.iv =
                     `Module
                       ({Odoc_model__Paths_types.iv =
                          `Root
                            (Some
                              {Odoc_model__Paths_types.iv =
                                `Page (None, None);
                               ihash = 236059787; ikey = "p_None"},
                             Root);
                         ihash = 818126955; ikey = "r_Root.p_None"},
                        Foo);
                    ihash = 249248993; ikey = "m_Foo.r_Root.p_None"},
                   false)),
             `Identifier
               ({Odoc_model__Paths_types.iv =
                  `Module
                    ({Odoc_model__Paths_types.iv =
                       `Root
                         (Some
                           {Odoc_model__Paths_types.iv = `Page (None, None);
                            ihash = 236059787; ikey = "p_None"},
                          Root);
                      ihash = 818126955; ikey = "r_Root.p_None"},
                     FooBarInt);
                 ihash = 706684202; ikey = "m_FooBarInt.r_Root.p_None"},
                false)),
          Foo),
       bar),
   []))

Extract the path to the Apply (so App(Bar)(Foo)(FooBarInt))

let test_path =
  `Apply
    (`Apply
        (`Apply
          (`Resolved
              (`Identifier
                (Common.root_module "App")),
            `Resolved
              (`Identifier
                (Common.root_module "Bar"))),
        `Resolved
          (`Identifier (Common.root_module "Foo"))),
      `Resolved
        (`Identifier
          (Common.root_module "FooBarInt")));;
let cp = Component.Of_Lang.(module_path (empty ()) test_path);;

Now let's lookup that module:

# let (p,m) = get_ok @@ Tools.resolve_module env cp;;
val p : Cpath.Resolved.module_ =
  `Apply
    (`Apply
       (`Apply
          (`Gpath
             (`Identifier
                {Odoc_model__Paths_types.iv =
                  `Module
                    ({Odoc_model__Paths_types.iv =
                       `Root
                         (Some
                           {Odoc_model__Paths_types.iv = `Page (None, None);
                            ihash = 236059787; ikey = "p_None"},
                          Root);
                      ihash = 818126955; ikey = "r_Root.p_None"},
                     App);
                 ihash = 855073208; ikey = "m_App.r_Root.p_None"}),
           `Gpath
             (`Identifier
                {Odoc_model__Paths_types.iv =
                  `Module
                    ({Odoc_model__Paths_types.iv =
                       `Root
                         (Some
                           {Odoc_model__Paths_types.iv = `Page (None, None);
                            ihash = 236059787; ikey = "p_None"},
                          Root);
                      ihash = 818126955; ikey = "r_Root.p_None"},
                     Bar);
                 ihash = 608577; ikey = "m_Bar.r_Root.p_None"})),
        `Gpath
          (`Identifier
             {Odoc_model__Paths_types.iv =
               `Module
                 ({Odoc_model__Paths_types.iv =
                    `Root
                      (Some
                        {Odoc_model__Paths_types.iv = `Page (None, None);
                         ihash = 236059787; ikey = "p_None"},
                       Root);
                   ihash = 818126955; ikey = "r_Root.p_None"},
                  Foo);
              ihash = 249248993; ikey = "m_Foo.r_Root.p_None"})),
     `Gpath
       (`Identifier
          {Odoc_model__Paths_types.iv =
            `Module
              ({Odoc_model__Paths_types.iv =
                 `Root
                   (Some
                     {Odoc_model__Paths_types.iv = `Page (None, None);
                      ihash = 236059787; ikey = "p_None"},
                    Root);
                ihash = 818126955; ikey = "r_Root.p_None"},
               FooBarInt);
           ihash = 706684202; ikey = "m_FooBarInt.r_Root.p_None"}))
val m : Component.Module.t Component.Delayed.t =
  {Odoc_xref2.Component.Delayed.v =
    Some
     {Odoc_xref2.Component.Module.source_loc = None;
      doc =
       {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None};
      type_ =
       Odoc_xref2.Component.Module.ModuleType
        (Odoc_xref2.Component.ModuleType.Path
          {Odoc_xref2.Component.ModuleType.p_expansion = None;
           p_path =
            `DotMT
              (`Apply
                 (`Resolved
                    (`Substituted
                       (`Gpath
                          (`Identifier
                             {Odoc_model__Paths_types.iv =
                               `Module
                                 ({Odoc_model__Paths_types.iv =
                                    `Root
                                      (Some
                                        {Odoc_model__Paths_types.iv =
                                          `Page (None, None);
                                         ihash = 236059787; ikey = "p_None"},
                                       Root);
                                   ihash = 818126955; ikey = "r_Root.p_None"},
                                  Foo);
                              ihash = 249248993;
                              ikey = "m_Foo.r_Root.p_None"}))),
                  `Resolved
                    (`Substituted
                       (`Gpath
                          (`Identifier
                             {Odoc_model__Paths_types.iv =
                               `Module
                                 ({Odoc_model__Paths_types.iv =
                                    `Root
                                      (Some
                                        {Odoc_model__Paths_types.iv =
                                          `Page (None, None);
                                         ihash = 236059787; ikey = "p_None"},
                                       Root);
                                   ihash = 818126955; ikey = "r_Root.p_None"},
                                  Bar);
                              ihash = 608577; ikey = "m_Bar.r_Root.p_None"})))),
               T)});
      canonical = None; hidden = false};
   get = None}
# let sg' = get_ok @@ Tools.expansion_of_module env (Component.Delayed.get m);;
val sg' : Tools.expansion =
  Odoc_xref2.Tools.Signature
   {Odoc_xref2.Component.Signature.items =
     [Odoc_xref2.Component.Signature.Module (`LModule (Foo, 16),
       Odoc_model.Lang.Signature.Ordinary,
       {Odoc_xref2.Component.Delayed.v =
         Some
          {Odoc_xref2.Component.Module.source_loc = None;
           doc =
            {Odoc_xref2.Component.CComment.elements = [];
             warnings_tag = None};
           type_ =
            Odoc_xref2.Component.Module.ModuleType
             (Odoc_xref2.Component.ModuleType.Path
               {Odoc_xref2.Component.ModuleType.p_expansion = None;
                p_path =
                 `DotMT
                   (`Resolved
                      (`Substituted
                         (`Substituted
                            (`Gpath
                               (`Identifier
                                  {Odoc_model__Paths_types.iv =
                                    `Module
                                      ({Odoc_model__Paths_types.iv =
                                         `Root
                                           (Some
                                             {Odoc_model__Paths_types.iv =
                                               `Page (None, None);
                                              ihash = 236059787;
                                              ikey = "p_None"},
                                            Root);
                                        ihash = 818126955;
                                        ikey = "r_Root.p_None"},
                                       Bar);
                                   ihash = 608577;
                                   ikey = "m_Bar.r_Root.p_None"})))),
                    T)});
           canonical = None; hidden = false};
        get = None})];
    compiled = false; removed = [];
    doc = {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None}}
# let sg' = get_ok @@ Tools.expansion_of_module env (Component.Delayed.get m);;
val sg' : Tools.expansion =
  Odoc_xref2.Tools.Signature
   {Odoc_xref2.Component.Signature.items =
     [Odoc_xref2.Component.Signature.Module (`LModule (Foo, 21),
       Odoc_model.Lang.Signature.Ordinary,
       {Odoc_xref2.Component.Delayed.v =
         Some
          {Odoc_xref2.Component.Module.source_loc = None;
           doc =
            {Odoc_xref2.Component.CComment.elements = [];
             warnings_tag = None};
           type_ =
            Odoc_xref2.Component.Module.ModuleType
             (Odoc_xref2.Component.ModuleType.Path
               {Odoc_xref2.Component.ModuleType.p_expansion = None;
                p_path =
                 `DotMT
                   (`Resolved
                      (`Substituted
                         (`Substituted
                            (`Gpath
                               (`Identifier
                                  {Odoc_model__Paths_types.iv =
                                    `Module
                                      ({Odoc_model__Paths_types.iv =
                                         `Root
                                           (Some
                                             {Odoc_model__Paths_types.iv =
                                               `Page (None, None);
                                              ihash = 236059787;
                                              ikey = "p_None"},
                                            Root);
                                        ihash = 818126955;
                                        ikey = "r_Root.p_None"},
                                       Bar);
                                   ihash = 608577;
                                   ikey = "m_Bar.r_Root.p_None"})))),
                    T)});
           canonical = None; hidden = false};
        get = None})];
    compiled = false; removed = [];
    doc = {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None}}
# let sg' = get_ok @@ Tools.expansion_of_module env (Component.Delayed.get m);;
val sg' : Tools.expansion =
  Odoc_xref2.Tools.Signature
   {Odoc_xref2.Component.Signature.items =
     [Odoc_xref2.Component.Signature.Module (`LModule (Foo, 26),
       Odoc_model.Lang.Signature.Ordinary,
       {Odoc_xref2.Component.Delayed.v =
         Some
          {Odoc_xref2.Component.Module.source_loc = None;
           doc =
            {Odoc_xref2.Component.CComment.elements = [];
             warnings_tag = None};
           type_ =
            Odoc_xref2.Component.Module.ModuleType
             (Odoc_xref2.Component.ModuleType.Path
               {Odoc_xref2.Component.ModuleType.p_expansion = None;
                p_path =
                 `DotMT
                   (`Resolved
                      (`Substituted
                         (`Substituted
                            (`Gpath
                               (`Identifier
                                  {Odoc_model__Paths_types.iv =
                                    `Module
                                      ({Odoc_model__Paths_types.iv =
                                         `Root
                                           (Some
                                             {Odoc_model__Paths_types.iv =
                                               `Page (None, None);
                                              ihash = 236059787;
                                              ikey = "p_None"},
                                            Root);
                                        ihash = 818126955;
                                        ikey = "r_Root.p_None"},
                                       Bar);
                                   ihash = 608577;
                                   ikey = "m_Bar.r_Root.p_None"})))),
                    T)});
           canonical = None; hidden = false};
        get = None})];
    compiled = false; removed = [];
    doc = {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None}}
# let sg' = get_ok @@ Tools.expansion_of_module env (Component.Delayed.get m);;
val sg' : Tools.expansion =
  Odoc_xref2.Tools.Signature
   {Odoc_xref2.Component.Signature.items =
     [Odoc_xref2.Component.Signature.Module (`LModule (Foo, 31),
       Odoc_model.Lang.Signature.Ordinary,
       {Odoc_xref2.Component.Delayed.v =
         Some
          {Odoc_xref2.Component.Module.source_loc = None;
           doc =
            {Odoc_xref2.Component.CComment.elements = [];
             warnings_tag = None};
           type_ =
            Odoc_xref2.Component.Module.ModuleType
             (Odoc_xref2.Component.ModuleType.Path
               {Odoc_xref2.Component.ModuleType.p_expansion = None;
                p_path =
                 `DotMT
                   (`Resolved
                      (`Substituted
                         (`Substituted
                            (`Gpath
                               (`Identifier
                                  {Odoc_model__Paths_types.iv =
                                    `Module
                                      ({Odoc_model__Paths_types.iv =
                                         `Root
                                           (Some
                                             {Odoc_model__Paths_types.iv =
                                               `Page (None, None);
                                              ihash = 236059787;
                                              ikey = "p_None"},
                                            Root);
                                        ihash = 818126955;
                                        ikey = "r_Root.p_None"},
                                       Bar);
                                   ihash = 608577;
                                   ikey = "m_Bar.r_Root.p_None"})))),
                    T)});
           canonical = None; hidden = false};
        get = None})];
    compiled = false; removed = [];
    doc = {Odoc_xref2.Component.CComment.elements = []; warnings_tag = None}}
let resolved = Common.compile_signature sg;;

The resolved path of t is:

# Common.LangUtils.Lens.get t_manifest resolved;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Subst
            (`ModuleType
               (`Substituted
                  (`Substituted
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             Bar);
                         ihash = 608577; ikey = "m_Bar.r_Root.p_None"})),
                T),
             `Module
               (`Apply
                  (`Apply
                     (`Apply
                        (`Identifier
                           {Odoc_model__Paths_types.iv =
                             `Module
                               ({Odoc_model__Paths_types.iv =
                                  `Root
                                    (Some
                                      {Odoc_model__Paths_types.iv =
                                        `Page (None, None);
                                       ihash = 236059787; ikey = "p_None"},
                                     Root);
                                 ihash = 818126955; ikey = "r_Root.p_None"},
                                App);
                            ihash = 855073208; ikey = "m_App.r_Root.p_None"},
                         `Identifier
                           {Odoc_model__Paths_types.iv =
                             `Module
                               ({Odoc_model__Paths_types.iv =
                                  `Root
                                    (Some
                                      {Odoc_model__Paths_types.iv =
                                        `Page (None, None);
                                       ihash = 236059787; ikey = "p_None"},
                                     Root);
                                 ihash = 818126955; ikey = "r_Root.p_None"},
                                Bar);
                            ihash = 608577; ikey = "m_Bar.r_Root.p_None"}),
                      `Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             Foo);
                         ihash = 249248993; ikey = "m_Foo.r_Root.p_None"}),
                   `Identifier
                     {Odoc_model__Paths_types.iv =
                       `Module
                         ({Odoc_model__Paths_types.iv =
                            `Root
                              (Some
                                {Odoc_model__Paths_types.iv =
                                  `Page (None, None);
                                 ihash = 236059787; ikey = "p_None"},
                               Root);
                           ihash = 818126955; ikey = "r_Root.p_None"},
                          FooBarInt);
                      ihash = 706684202; ikey = "m_FooBarInt.r_Root.p_None"}),
                Foo)),
          bar)),
   []))

Yet another nasty one#

let test_data = {|
module M : sig
  module F(X : sig module type S end) : sig
    module type S = sig
      module N : X.S
    end
  end
  module T : sig
    module type S = sig type t end
  end
  module O : functor (X : sig end) -> F(T).S
end
type t = M.O(M).N.t
|}
let sg = Common.signature_of_mli_string test_data;;
let resolved = Common.compile_signature sg;;
# Common.LangUtils.Lens.get t_manifest resolved;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Subst
            (`ModuleType
               (`Substituted
                  (`Module
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             M);
                         ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                      T)),
                S),
             `Module
               (`Apply
                  (`Module
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             M);
                         ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                      O),
                   `Identifier
                     {Odoc_model__Paths_types.iv =
                       `Module
                         ({Odoc_model__Paths_types.iv =
                            `Root
                              (Some
                                {Odoc_model__Paths_types.iv =
                                  `Page (None, None);
                                 ihash = 236059787; ikey = "p_None"},
                               Root);
                           ihash = 818126955; ikey = "r_Root.p_None"},
                          M);
                      ihash = 716453475; ikey = "m_M.r_Root.p_None"}),
                N)),
          t)),
   []))

More dependently typed modules#

let test_data = {|
module Dep1 : sig
  module type S = sig
    type c = int
  end
  module X : sig
    module Y : S
  end
end 
module Dep2 :
  functor (Arg : sig module type S module X : sig module Y : S end end) ->
    sig
      module A : sig
        module Y : Arg.S
      end
      module B = A.Y
    end
type dep1 = Dep2(Dep1).B.c
|};;

let sg = Common.signature_of_mli_string test_data;;
let resolved = Common.compile_signature sg;;
# Common.LangUtils.Lens.get (type_manifest "dep1") resolved;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Alias
            (`Subst
               (`ModuleType
                  (`Substituted
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             Dep1);
                         ihash = 393430064; ikey = "m_Dep1.r_Root.p_None"}),
                   S),
                `Module
                  (`Module
                     (`Apply
                        (`Identifier
                           {Odoc_model__Paths_types.iv =
                             `Module
                               ({Odoc_model__Paths_types.iv =
                                  `Root
                                    (Some
                                      {Odoc_model__Paths_types.iv =
                                        `Page (None, None);
                                       ihash = 236059787; ikey = "p_None"},
                                     Root);
                                 ihash = 818126955; ikey = "r_Root.p_None"},
                                Dep2);
                            ihash = 739333691; ikey = "m_Dep2.r_Root.p_None"},
                         `Identifier
                           {Odoc_model__Paths_types.iv =
                             `Module
                               ({Odoc_model__Paths_types.iv =
                                  `Root
                                    (Some
                                      {Odoc_model__Paths_types.iv =
                                        `Page (None, None);
                                       ihash = 236059787; ikey = "p_None"},
                                     Root);
                                 ihash = 818126955; ikey = "r_Root.p_None"},
                                Dep1);
                            ihash = 393430064; ikey = "m_Dep1.r_Root.p_None"}),
                      A),
                   Y)),
             `Dot
               (`Apply
                  (`Identifier
                     ({Odoc_model__Paths_types.iv =
                        `Module
                          ({Odoc_model__Paths_types.iv =
                             `Root
                               (Some
                                 {Odoc_model__Paths_types.iv =
                                   `Page (None, None);
                                  ihash = 236059787; ikey = "p_None"},
                                Root);
                            ihash = 818126955; ikey = "r_Root.p_None"},
                           Dep2);
                       ihash = 739333691; ikey = "m_Dep2.r_Root.p_None"},
                      false),
                   `Identifier
                     ({Odoc_model__Paths_types.iv =
                        `Module
                          ({Odoc_model__Paths_types.iv =
                             `Root
                               (Some
                                 {Odoc_model__Paths_types.iv =
                                   `Page (None, None);
                                  ihash = 236059787; ikey = "p_None"},
                                Root);
                            ihash = 818126955; ikey = "r_Root.p_None"},
                           Dep1);
                       ihash = 393430064; ikey = "m_Dep1.r_Root.p_None"},
                      false)),
                B)),
          c)),
   []))
let test_data = {|
module Dep3 : sig type a end
module Dep4 : sig
  module type T = sig type b end
  module type S = sig
    module X : T
    module Y : sig end
  end
  module X : T
end
module Dep5 :
  functor (Arg : sig
                   module type T
                   module type S = sig
                     module X : T
                     module Y : sig end
                   end
                   module X : T
            end) ->
    sig
      module Z : Arg.S with module Y = Dep3
    end 
type dep2 = Dep5(Dep4).Z.X.b
type dep3 = Dep5(Dep4).Z.Y.a
|};;
let sg = Common.signature_of_mli_string test_data;;
let resolved = Common.compile_signature sg;;
# Common.LangUtils.Lens.get (type_manifest "dep2") resolved;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Subst
            (`ModuleType
               (`Substituted
                  (`Identifier
                     {Odoc_model__Paths_types.iv =
                       `Module
                         ({Odoc_model__Paths_types.iv =
                            `Root
                              (Some
                                {Odoc_model__Paths_types.iv =
                                  `Page (None, None);
                                 ihash = 236059787; ikey = "p_None"},
                               Root);
                           ihash = 818126955; ikey = "r_Root.p_None"},
                          Dep4);
                      ihash = 1019199703; ikey = "m_Dep4.r_Root.p_None"}),
                T),
             `Module
               (`Module
                  (`Apply
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             Dep5);
                         ihash = 592809356; ikey = "m_Dep5.r_Root.p_None"},
                      `Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             Dep4);
                         ihash = 1019199703; ikey = "m_Dep4.r_Root.p_None"}),
                   Z),
                X)),
          b)),
   []))
# Common.LangUtils.Lens.get (type_manifest "dep3") resolved;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Alias
            (`Identifier
               {Odoc_model__Paths_types.iv =
                 `Module
                   ({Odoc_model__Paths_types.iv =
                      `Root
                        (Some
                          {Odoc_model__Paths_types.iv = `Page (None, None);
                           ihash = 236059787; ikey = "p_None"},
                         Root);
                     ihash = 818126955; ikey = "r_Root.p_None"},
                    Dep3);
                ihash = 403763666; ikey = "m_Dep3.r_Root.p_None"},
             `Dot
               (`Dot
                  (`Apply
                     (`Identifier
                        ({Odoc_model__Paths_types.iv =
                           `Module
                             ({Odoc_model__Paths_types.iv =
                                `Root
                                  (Some
                                    {Odoc_model__Paths_types.iv =
                                      `Page (None, None);
                                     ihash = 236059787; ikey = "p_None"},
                                   Root);
                               ihash = 818126955; ikey = "r_Root.p_None"},
                              Dep5);
                          ihash = 592809356; ikey = "m_Dep5.r_Root.p_None"},
                         false),
                      `Identifier
                        ({Odoc_model__Paths_types.iv =
                           `Module
                             ({Odoc_model__Paths_types.iv =
                                `Root
                                  (Some
                                    {Odoc_model__Paths_types.iv =
                                      `Page (None, None);
                                     ihash = 236059787; ikey = "p_None"},
                                   Root);
                               ihash = 818126955; ikey = "r_Root.p_None"},
                              Dep4);
                          ihash = 1019199703; ikey = "m_Dep4.r_Root.p_None"},
                         false)),
                   Z),
                Y)),
          a)),
   []))
let test_data = {|
module Dep6 : sig
  module type S = sig type d end
  module type T = sig
    module type R = S
    module Y : R
  end
  module X : T
end

module Dep7 :
  functor (Arg : sig
                   module type S
                   module type T = sig
                     module type R = S
                     module Y : R
                   end
                   module X : T
            end) -> sig
      module M : Arg.T
    end

type dep4 = Dep7(Dep6).M.Y.d
|};;
let sg = Common.signature_of_mli_string test_data;;
let resolved = Common.compile_signature sg;;
# Common.LangUtils.Lens.get (type_manifest "dep4") resolved;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Module
            (`Subst
               (`ModuleType
                  (`Substituted
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             Dep6);
                         ihash = 489035468; ikey = "m_Dep6.r_Root.p_None"}),
                   T),
                `Module
                  (`Apply
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             Dep7);
                         ihash = 108620130; ikey = "m_Dep7.r_Root.p_None"},
                      `Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             Dep6);
                         ihash = 489035468; ikey = "m_Dep6.r_Root.p_None"}),
                   M)),
             Y),
          d)),
   []))
let test_data = {|
module Dep8 : sig module type T = sig type t end end

module Dep9 : functor (X : sig module type T end) -> sig module type T = X.T end

module type Dep10 = Dep9(Dep8).T with type t = int

module Dep11 : sig
  module type S = sig
    type c
  end
end

module Dep12 :
  functor (Arg : sig module type S end) -> sig
      module type T = Arg.S
end

module Dep13 : Dep12(Dep11).T

type dep5 = Dep13.c
|};;
let sg = Common.signature_of_mli_string test_data;;
let resolved = Common.compile_signature sg;;
# Common.LangUtils.Lens.get (type_manifest "dep5") resolved;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Subst
            (`AliasModuleType
               (`ModuleType
                  (`Substituted
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Module
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             Dep11);
                         ihash = 873108764; ikey = "m_Dep11.r_Root.p_None"}),
                   S),
                `SubstT
                  (`ModuleType
                     (`Substituted
                        (`Identifier
                           {Odoc_model__Paths_types.iv =
                             `Module
                               ({Odoc_model__Paths_types.iv =
                                  `Root
                                    (Some
                                      {Odoc_model__Paths_types.iv =
                                        `Page (None, None);
                                       ihash = 236059787; ikey = "p_None"},
                                     Root);
                                 ihash = 818126955; ikey = "r_Root.p_None"},
                                Dep11);
                            ihash = 873108764;
                            ikey = "m_Dep11.r_Root.p_None"}),
                      S),
                   `ModuleType
                     (`Apply
                        (`Identifier
                           {Odoc_model__Paths_types.iv =
                             `Module
                               ({Odoc_model__Paths_types.iv =
                                  `Root
                                    (Some
                                      {Odoc_model__Paths_types.iv =
                                        `Page (None, None);
                                       ihash = 236059787; ikey = "p_None"},
                                     Root);
                                 ihash = 818126955; ikey = "r_Root.p_None"},
                                Dep12);
                            ihash = 755368715;
                            ikey = "m_Dep12.r_Root.p_None"},
                         `Identifier
                           {Odoc_model__Paths_types.iv =
                             `Module
                               ({Odoc_model__Paths_types.iv =
                                  `Root
                                    (Some
                                      {Odoc_model__Paths_types.iv =
                                        `Page (None, None);
                                       ihash = 236059787; ikey = "p_None"},
                                     Root);
                                 ihash = 818126955; ikey = "r_Root.p_None"},
                                Dep11);
                            ihash = 873108764;
                            ikey = "m_Dep11.r_Root.p_None"}),
                      T))),
             `Identifier
               {Odoc_model__Paths_types.iv =
                 `Module
                   ({Odoc_model__Paths_types.iv =
                      `Root
                        (Some
                          {Odoc_model__Paths_types.iv = `Page (None, None);
                           ihash = 236059787; ikey = "p_None"},
                         Root);
                     ihash = 818126955; ikey = "r_Root.p_None"},
                    Dep13);
                ihash = 726816582; ikey = "m_Dep13.r_Root.p_None"}),
          c)),
   []))
let test_data = {|
module With7 : functor
  (X : sig
     module type T
   end)
  -> sig
  module type T = X.T
end

module With9 : sig
  module type S = sig
    type t
  end
end

module With10 : sig
  (** {!With10.T} is a submodule type. *)
  module type T = sig
    module M : sig
      module type S
    end

    module N : M.S
  end
end

module type With11 = With7(With10).T with module M = With9 and type N.t = int
|};;
let sg = Common.signature_of_mli_string test_data;;
let resolved = Common.compile_signature sg;;
let with11 = Common.LangUtils.Lens.Signature.module_type "With11"

Let's take a look now at hidden modules

let test_data = {|
module Hidden__ : sig
  type t
end

module H=Hidden__

type t = Hidden__.t
|};;
let sg = Common.signature_of_mli_string test_data;;
let resolved = Common.compile_signature sg;;
# Common.LangUtils.Lens.get (type_manifest "t") resolved;;
- : Odoc_model.Lang.TypeExpr.t option =
Some
 (Odoc_model.Lang.TypeExpr.Constr
   (`Resolved
      (`Type
         (`Hidden
            (`Identifier
               {Odoc_model__Paths_types.iv =
                 `Module
                   ({Odoc_model__Paths_types.iv =
                      `Root
                        (Some
                          {Odoc_model__Paths_types.iv = `Page (None, None);
                           ihash = 236059787; ikey = "p_None"},
                         Root);
                     ihash = 818126955; ikey = "r_Root.p_None"},
                    Hidden__);
                ihash = 762365111; ikey = "m_Hidden__.r_Root.p_None"}),
          t)),
   []))

How about references now

let test_data = {|
type t
(** [t] {!t} *)
|};;
let sg = Common.signature_of_mli_string test_data;;
let resolved = Common.compile_signature sg;;
# Common.LangUtils.Lens.get (Common.LangUtils.Lens.Signature.type_ "t") resolved;;
- : Odoc_model.Lang.TypeDecl.t =
{Odoc_model.Lang.TypeDecl.id =
  {Odoc_model__Paths_types.iv =
    `Type
      ({Odoc_model__Paths_types.iv =
         `Root
           (Some
             {Odoc_model__Paths_types.iv = `Page (None, None);
              ihash = 236059787; ikey = "p_None"},
            Root);
        ihash = 818126955; ikey = "r_Root.p_None"},
       t);
   ihash = 1016576344; ikey = "t_t.r_Root.p_None"};
 source_loc = None;
 doc =
  {Odoc_model__.Comment.elements =
    [{Odoc_model__.Location_.location =
       {Odoc_model__.Location_.file = "";
        start = {Odoc_model__.Location_.line = 3; column = 6};
        end_ = {Odoc_model__.Location_.line = 3; column = 14}};
      value =
       `Paragraph
         [{Odoc_model__.Location_.location =
            {Odoc_model__.Location_.file = "";
             start = {Odoc_model__.Location_.line = 3; column = 6};
             end_ = {Odoc_model__.Location_.line = 3; column = 9}};
           value = `Code_span "t"};
          {Odoc_model__.Location_.location =
            {Odoc_model__.Location_.file = "";
             start = {Odoc_model__.Location_.line = 3; column = 9};
             end_ = {Odoc_model__.Location_.line = 3; column = 10}};
           value = `Space};
          {Odoc_model__.Location_.location =
            {Odoc_model__.Location_.file = "";
             start = {Odoc_model__.Location_.line = 3; column = 10};
             end_ = {Odoc_model__.Location_.line = 3; column = 14}};
           value = `Reference (`Root ("t", `TUnknown), [])}]}];
   warnings_tag = None};
 canonical = None;
 equation =
  {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false;
   manifest = None; constraints = []};
 representation = None}

Expansion test#

let test_data = {|
module type M = sig
  type t
end

type u

module type M1 = M with type t = u
|};;
let sg = Common.signature_of_mli_string test_data;;
# Link.signature Env.empty id sg ;;
- : Odoc_model.Lang.Signature.t =
{Odoc_model.Lang.Signature.items =
  [Odoc_model.Lang.Signature.ModuleType
    {Odoc_model.Lang.ModuleType.id =
      {Odoc_model__Paths_types.iv =
        `ModuleType
          ({Odoc_model__Paths_types.iv =
             `Root
               (Some
                 {Odoc_model__Paths_types.iv = `Page (None, None);
                  ihash = 236059787; ikey = "p_None"},
                Root);
            ihash = 818126955; ikey = "r_Root.p_None"},
           M);
       ihash = 459143770; ikey = "mt_M.r_Root.p_None"};
     source_loc = None;
     doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
     canonical = None;
     expr =
      Some
       (Odoc_model.Lang.ModuleType.Signature
         {Odoc_model.Lang.Signature.items =
           [Odoc_model.Lang.Signature.Type
             (Odoc_model.Lang.Signature.Ordinary,
             {Odoc_model.Lang.TypeDecl.id =
               {Odoc_model__Paths_types.iv =
                 `Type
                   ({Odoc_model__Paths_types.iv =
                      `ModuleType
                        ({Odoc_model__Paths_types.iv =
                           `Root
                             (Some
                               {Odoc_model__Paths_types.iv =
                                 `Page (None, None);
                                ihash = 236059787; ikey = "p_None"},
                              Root);
                          ihash = 818126955; ikey = "r_Root.p_None"},
                         M);
                     ihash = 459143770; ikey = "mt_M.r_Root.p_None"},
                    t);
                ihash = 825731485; ikey = "t_t.mt_M.r_Root.p_None"};
              source_loc = None;
              doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
              canonical = None;
              equation =
               {Odoc_model.Lang.TypeDecl.Equation.params = [];
                private_ = false; manifest = None; constraints = []};
              representation = None})];
          compiled = false; removed = [];
          doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}})};
   Odoc_model.Lang.Signature.Type (Odoc_model.Lang.Signature.Ordinary,
    {Odoc_model.Lang.TypeDecl.id =
      {Odoc_model__Paths_types.iv =
        `Type
          ({Odoc_model__Paths_types.iv =
             `Root
               (Some
                 {Odoc_model__Paths_types.iv = `Page (None, None);
                  ihash = 236059787; ikey = "p_None"},
                Root);
            ihash = 818126955; ikey = "r_Root.p_None"},
           u);
       ihash = 15973539; ikey = "t_u.r_Root.p_None"};
     source_loc = None;
     doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
     canonical = None;
     equation =
      {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false;
       manifest = None; constraints = []};
     representation = None});
   Odoc_model.Lang.Signature.ModuleType
    {Odoc_model.Lang.ModuleType.id =
      {Odoc_model__Paths_types.iv =
        `ModuleType
          ({Odoc_model__Paths_types.iv =
             `Root
               (Some
                 {Odoc_model__Paths_types.iv = `Page (None, None);
                  ihash = 236059787; ikey = "p_None"},
                Root);
            ihash = 818126955; ikey = "r_Root.p_None"},
           M1);
       ihash = 756272831; ikey = "mt_M1.r_Root.p_None"};
     source_loc = None;
     doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
     canonical = None;
     expr =
      Some
       (Odoc_model.Lang.ModuleType.With
         {Odoc_model.Lang.ModuleType.w_substitutions =
           [Odoc_model.Lang.ModuleType.TypeEq (`Dot (`Root, "t"),
             {Odoc_model.Lang.TypeDecl.Equation.params = [];
              private_ = false;
              manifest =
               Some
                (Odoc_model.Lang.TypeExpr.Constr
                  (`Resolved
                     (`Identifier
                        {Odoc_model__Paths_types.iv =
                          `Type
                            ({Odoc_model__Paths_types.iv =
                               `Root
                                 (Some
                                   {Odoc_model__Paths_types.iv =
                                     `Page (None, None);
                                    ihash = 236059787; ikey = "p_None"},
                                  Root);
                              ihash = 818126955; ikey = "r_Root.p_None"},
                             u);
                         ihash = 15973539; ikey = "t_u.r_Root.p_None"}),
                  []));
              constraints = []})];
          w_expansion = None;
          w_expr =
           Odoc_model.Lang.ModuleType.U.Path
            (`Resolved
               (`Identifier
                  {Odoc_model__Paths_types.iv =
                    `ModuleType
                      ({Odoc_model__Paths_types.iv =
                         `Root
                           (Some
                             {Odoc_model__Paths_types.iv = `Page (None, None);
                              ihash = 236059787; ikey = "p_None"},
                            Root);
                        ihash = 818126955; ikey = "r_Root.p_None"},
                       M);
                   ihash = 459143770; ikey = "mt_M.r_Root.p_None"}))})}];
 compiled = false; removed = [];
 doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}}

Expansion continued#

let test_data = {|
module Foo (X : sig end) : sig
  type t
  module type S = sig type s = C of t end
end
module Bar : sig end
module M : Foo(Bar).S
|};;
let sg = Common.signature_of_mli_string test_data;;
let resolved = Common.compile_signature sg;;
let expanded = Link.signature Env.empty id resolved;;
let module_M_expansion =
  let open Common.LangUtils.Lens in
  Signature.module_ "M" |-- Module.type_ |-~ Module.decl_moduletype
# Common.LangUtils.Lens.get module_M_expansion expanded ;;
- : Odoc_model.Lang.ModuleType.expr =
Odoc_model.Lang.ModuleType.Path
 {Odoc_model.Lang.ModuleType.p_expansion =
   Some
    (Odoc_model.Lang.ModuleType.Signature
      {Odoc_model.Lang.Signature.items =
        [Odoc_model.Lang.Signature.Type (Odoc_model.Lang.Signature.Ordinary,
          {Odoc_model.Lang.TypeDecl.id =
            {Odoc_model__Paths_types.iv =
              `Type
                ({Odoc_model__Paths_types.iv =
                   `Module
                     ({Odoc_model__Paths_types.iv =
                        `Root
                          (Some
                            {Odoc_model__Paths_types.iv = `Page (None, None);
                             ihash = 236059787; ikey = "p_None"},
                           Root);
                       ihash = 818126955; ikey = "r_Root.p_None"},
                      M);
                  ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                 s);
             ihash = 395135148; ikey = "t_s.m_M.r_Root.p_None"};
           source_loc = None;
           doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
           canonical = None;
           equation =
            {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false;
             manifest = None; constraints = []};
           representation =
            Some
             (Odoc_model.Lang.TypeDecl.Representation.Variant
               [{Odoc_model.Lang.TypeDecl.Constructor.id =
                  {Odoc_model__Paths_types.iv =
                    `Constructor
                      ({Odoc_model__Paths_types.iv =
                         `Type
                           ({Odoc_model__Paths_types.iv =
                              `Module
                                ({Odoc_model__Paths_types.iv =
                                   `Root
                                     (Some
                                       {Odoc_model__Paths_types.iv =
                                         `Page (None, None);
                                        ihash = 236059787; ikey = "p_None"},
                                      Root);
                                  ihash = 818126955; ikey = "r_Root.p_None"},
                                 M);
                             ihash = 716453475; ikey = "m_M.r_Root.p_None"},
                            s);
                        ihash = 395135148; ikey = "t_s.m_M.r_Root.p_None"},
                       <abstr>);
                   ihash = 2570800; ikey = "ctor_C.t_s.m_M.r_Root.p_None"};
                 doc =
                  {Odoc_model__.Comment.elements = []; warnings_tag = None};
                 args =
                  Odoc_model.Lang.TypeDecl.Constructor.Tuple
                   [Odoc_model.Lang.TypeExpr.Constr
                     (`Resolved
                        (`Type
                           (`Apply
                              (`Identifier
                                 {Odoc_model__Paths_types.iv =
                                   `Module
                                     ({Odoc_model__Paths_types.iv =
                                        `Root
                                          (Some
                                            {Odoc_model__Paths_types.iv =
                                              `Page (None, None);
                                             ihash = 236059787;
                                             ikey = "p_None"},
                                           Root);
                                       ihash = 818126955;
                                       ikey = "r_Root.p_None"},
                                      Foo);
                                  ihash = 249248993;
                                  ikey = "m_Foo.r_Root.p_None"},
                               `Identifier
                                 {Odoc_model__Paths_types.iv =
                                   `Module
                                     ({Odoc_model__Paths_types.iv =
                                        `Root
                                          (Some
                                            {Odoc_model__Paths_types.iv =
                                              `Page (None, None);
                                             ihash = 236059787;
                                             ikey = "p_None"},
                                           Root);
                                       ihash = 818126955;
                                       ikey = "r_Root.p_None"},
                                      Bar);
                                  ihash = 608577;
                                  ikey = "m_Bar.r_Root.p_None"}),
                            t)),
                     [])];
                 res = None}])})];
       compiled = true; removed = [];
       doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}});
  p_path =
   `Resolved
     (`ModuleType
        (`Apply
           (`Identifier
              {Odoc_model__Paths_types.iv =
                `Module
                  ({Odoc_model__Paths_types.iv =
                     `Root
                       (Some
                         {Odoc_model__Paths_types.iv = `Page (None, None);
                          ihash = 236059787; ikey = "p_None"},
                        Root);
                    ihash = 818126955; ikey = "r_Root.p_None"},
                   Foo);
               ihash = 249248993; ikey = "m_Foo.r_Root.p_None"},
            `Identifier
              {Odoc_model__Paths_types.iv =
                `Module
                  ({Odoc_model__Paths_types.iv =
                     `Root
                       (Some
                         {Odoc_model__Paths_types.iv = `Page (None, None);
                          ihash = 236059787; ikey = "p_None"},
                        Root);
                    ihash = 818126955; ikey = "r_Root.p_None"},
                   Bar);
               ihash = 608577; ikey = "m_Bar.r_Root.p_None"}),
         S))}

Shadowing#

Let's see what happens when we have nested shadowing:

let test_data = {|
module Foo : sig
  type t
  val id : t
end

module Foo2 : sig
  include module type of struct include Foo end
  type t
  val id2 : t
end

module Foo3 : sig
  include module type of struct include Foo2 end
  type t
  val id3 : t
end
|};;
let sg = Common.signature_of_mli_string test_data;;
let module_expansion_include_sig name n =
  let open Common.LangUtils.Lens in
  Signature.module_ name |-- Module.type_ |-~ Module.decl_moduletype |-~ ModuleType.expr_signature |-- Signature.includes |-~ nth n |-- Include.expansion_sig
let m_e_i_s_value mod_name n val_name =
  let open Common.LangUtils.Lens in
   module_expansion_include_sig mod_name n |-- Signature.value val_name
# Common.LangUtils.Lens.get (m_e_i_s_value "Foo3" 0 "id") sg;;
- : Odoc_model.Lang.Value.t =
{Odoc_model.Lang.Value.id =
  {Odoc_model__Paths_types.iv =
    `Value
      ({Odoc_model__Paths_types.iv =
         `Module
           ({Odoc_model__Paths_types.iv =
              `Root
                (Some
                  {Odoc_model__Paths_types.iv = `Page (None, None);
                   ihash = 236059787; ikey = "p_None"},
                 Root);
             ihash = 818126955; ikey = "r_Root.p_None"},
            Foo3);
        ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
       id);
   ihash = 424389437; ikey = "v_id.m_Foo3.r_Root.p_None"};
 source_loc = None; value = Odoc_model.Lang.Value.Abstract;
 doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
 type_ =
  Odoc_model.Lang.TypeExpr.Constr
   (`DotT
      (`Identifier
         ({Odoc_model__Paths_types.iv =
            `Module
              ({Odoc_model__Paths_types.iv =
                 `Root
                   (Some
                     {Odoc_model__Paths_types.iv = `Page (None, None);
                      ihash = 236059787; ikey = "p_None"},
                    Root);
                ihash = 818126955; ikey = "r_Root.p_None"},
               Foo);
           ihash = 249248993; ikey = "m_Foo.r_Root.p_None"},
          false),
       t),
   [])}
# Common.LangUtils.Lens.get (m_e_i_s_value "Foo3" 0 "id2") sg;;
- : Odoc_model.Lang.Value.t =
{Odoc_model.Lang.Value.id =
  {Odoc_model__Paths_types.iv =
    `Value
      ({Odoc_model__Paths_types.iv =
         `Module
           ({Odoc_model__Paths_types.iv =
              `Root
                (Some
                  {Odoc_model__Paths_types.iv = `Page (None, None);
                   ihash = 236059787; ikey = "p_None"},
                 Root);
             ihash = 818126955; ikey = "r_Root.p_None"},
            Foo3);
        ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
       id2);
   ihash = 412619918; ikey = "v_id2.m_Foo3.r_Root.p_None"};
 source_loc = None; value = Odoc_model.Lang.Value.Abstract;
 doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
 type_ =
  Odoc_model.Lang.TypeExpr.Constr
   (`Identifier
      ({Odoc_model__Paths_types.iv =
         `Type
           ({Odoc_model__Paths_types.iv =
              `Module
                ({Odoc_model__Paths_types.iv =
                   `Root
                     (Some
                       {Odoc_model__Paths_types.iv = `Page (None, None);
                        ihash = 236059787; ikey = "p_None"},
                      Root);
                  ihash = 818126955; ikey = "r_Root.p_None"},
                 Foo3);
             ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
            {t}2/shadowed/(XXXX));
        ihash = 975388256;
        ikey = "t_{t}2/shadowed/(XXXX).m_Foo3.r_Root.p_None"},
       false),
   [])}

And what happens when we include multiple things defining a t?

let test_data = {|
module Foo : sig
  type t
  val id : t
end

module Foo2 : sig
  type t
  val id2 : t
end

module Foo3 : sig
  include module type of struct include Foo end
  include module type of struct include Foo2 end
  type t
  val id3 : t
end
|};;
let sg = Common.signature_of_mli_string test_data;;
# Common.LangUtils.Lens.get (module_expansion_include_sig "Foo3" 0) sg;;
- : Odoc_model.Lang.Signature.t =
{Odoc_model.Lang.Signature.items =
  [Odoc_model.Lang.Signature.Type (Odoc_model.Lang.Signature.Ordinary,
    {Odoc_model.Lang.TypeDecl.id =
      {Odoc_model__Paths_types.iv =
        `Type
          ({Odoc_model__Paths_types.iv =
             `Module
               ({Odoc_model__Paths_types.iv =
                  `Root
                    (Some
                      {Odoc_model__Paths_types.iv = `Page (None, None);
                       ihash = 236059787; ikey = "p_None"},
                     Root);
                 ihash = 818126955; ikey = "r_Root.p_None"},
                Foo3);
            ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
           {t}3/shadowed/(XXXX));
       ihash = 584226322;
       ikey = "t_{t}3/shadowed/(XXXX).m_Foo3.r_Root.p_None"};
     source_loc = None;
     doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
     canonical = None;
     equation =
      {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false;
       manifest =
        Some
         (Odoc_model.Lang.TypeExpr.Constr
           (`DotT
              (`Identifier
                 ({Odoc_model__Paths_types.iv =
                    `Module
                      ({Odoc_model__Paths_types.iv =
                         `Root
                           (Some
                             {Odoc_model__Paths_types.iv = `Page (None, None);
                              ihash = 236059787; ikey = "p_None"},
                            Root);
                        ihash = 818126955; ikey = "r_Root.p_None"},
                       Foo);
                   ihash = 249248993; ikey = "m_Foo.r_Root.p_None"},
                  false),
               t),
           []));
       constraints = []};
     representation = None});
   Odoc_model.Lang.Signature.Value
    {Odoc_model.Lang.Value.id =
      {Odoc_model__Paths_types.iv =
        `Value
          ({Odoc_model__Paths_types.iv =
             `Module
               ({Odoc_model__Paths_types.iv =
                  `Root
                    (Some
                      {Odoc_model__Paths_types.iv = `Page (None, None);
                       ihash = 236059787; ikey = "p_None"},
                     Root);
                 ihash = 818126955; ikey = "r_Root.p_None"},
                Foo3);
            ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
           id);
       ihash = 424389437; ikey = "v_id.m_Foo3.r_Root.p_None"};
     source_loc = None; value = Odoc_model.Lang.Value.Abstract;
     doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
     type_ =
      Odoc_model.Lang.TypeExpr.Constr
       (`Identifier
          ({Odoc_model__Paths_types.iv =
             `Type
               ({Odoc_model__Paths_types.iv =
                  `Module
                    ({Odoc_model__Paths_types.iv =
                       `Root
                         (Some
                           {Odoc_model__Paths_types.iv = `Page (None, None);
                            ihash = 236059787; ikey = "p_None"},
                          Root);
                      ihash = 818126955; ikey = "r_Root.p_None"},
                     Foo3);
                 ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
                {t}3/shadowed/(XXXX));
            ihash = 584226322;
            ikey = "t_{t}3/shadowed/(XXXX).m_Foo3.r_Root.p_None"},
           false),
       [])}];
 compiled = false; removed = [];
 doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}}
# Common.LangUtils.Lens.get (module_expansion_include_sig "Foo3" 1) sg;;
- : Odoc_model.Lang.Signature.t =
{Odoc_model.Lang.Signature.items =
  [Odoc_model.Lang.Signature.Type (Odoc_model.Lang.Signature.Ordinary,
    {Odoc_model.Lang.TypeDecl.id =
      {Odoc_model__Paths_types.iv =
        `Type
          ({Odoc_model__Paths_types.iv =
             `Module
               ({Odoc_model__Paths_types.iv =
                  `Root
                    (Some
                      {Odoc_model__Paths_types.iv = `Page (None, None);
                       ihash = 236059787; ikey = "p_None"},
                     Root);
                 ihash = 818126955; ikey = "r_Root.p_None"},
                Foo3);
            ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
           {t}4/shadowed/(XXXX));
       ihash = 466750041;
       ikey = "t_{t}4/shadowed/(XXXX).m_Foo3.r_Root.p_None"};
     source_loc = None;
     doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
     canonical = None;
     equation =
      {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false;
       manifest =
        Some
         (Odoc_model.Lang.TypeExpr.Constr
           (`DotT
              (`Identifier
                 ({Odoc_model__Paths_types.iv =
                    `Module
                      ({Odoc_model__Paths_types.iv =
                         `Root
                           (Some
                             {Odoc_model__Paths_types.iv = `Page (None, None);
                              ihash = 236059787; ikey = "p_None"},
                            Root);
                        ihash = 818126955; ikey = "r_Root.p_None"},
                       Foo2);
                   ihash = 926621908; ikey = "m_Foo2.r_Root.p_None"},
                  false),
               t),
           []));
       constraints = []};
     representation = None});
   Odoc_model.Lang.Signature.Value
    {Odoc_model.Lang.Value.id =
      {Odoc_model__Paths_types.iv =
        `Value
          ({Odoc_model__Paths_types.iv =
             `Module
               ({Odoc_model__Paths_types.iv =
                  `Root
                    (Some
                      {Odoc_model__Paths_types.iv = `Page (None, None);
                       ihash = 236059787; ikey = "p_None"},
                     Root);
                 ihash = 818126955; ikey = "r_Root.p_None"},
                Foo3);
            ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
           id2);
       ihash = 412619918; ikey = "v_id2.m_Foo3.r_Root.p_None"};
     source_loc = None; value = Odoc_model.Lang.Value.Abstract;
     doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
     type_ =
      Odoc_model.Lang.TypeExpr.Constr
       (`Identifier
          ({Odoc_model__Paths_types.iv =
             `Type
               ({Odoc_model__Paths_types.iv =
                  `Module
                    ({Odoc_model__Paths_types.iv =
                       `Root
                         (Some
                           {Odoc_model__Paths_types.iv = `Page (None, None);
                            ihash = 236059787; ikey = "p_None"},
                          Root);
                      ihash = 818126955; ikey = "r_Root.p_None"},
                     Foo3);
                 ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
                {t}4/shadowed/(XXXX));
            ihash = 466750041;
            ikey = "t_{t}4/shadowed/(XXXX).m_Foo3.r_Root.p_None"},
           false),
       [])}];
 compiled = false; removed = [];
 doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}}

And what happens when we override values?

let test_data = {|
module Foo : sig
  type t
  val x : int
  val id : t
end

module Foo2 : sig
  type t
  val id2 : t
end

module Foo3 : sig
  include module type of struct include Foo end
  include module type of struct include Foo2 end
  type t
  val x : float
  val id3 : t
end
|};;
let sg = Common.signature_of_mli_string test_data;;
# Common.LangUtils.Lens.get (module_expansion_include_sig "Foo3" 0) sg;;
- : Odoc_model.Lang.Signature.t =
{Odoc_model.Lang.Signature.items =
  [Odoc_model.Lang.Signature.Type (Odoc_model.Lang.Signature.Ordinary,
    {Odoc_model.Lang.TypeDecl.id =
      {Odoc_model__Paths_types.iv =
        `Type
          ({Odoc_model__Paths_types.iv =
             `Module
               ({Odoc_model__Paths_types.iv =
                  `Root
                    (Some
                      {Odoc_model__Paths_types.iv = `Page (None, None);
                       ihash = 236059787; ikey = "p_None"},
                     Root);
                 ihash = 818126955; ikey = "r_Root.p_None"},
                Foo3);
            ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
           {t}5/shadowed/(XXXX));
       ihash = 995358055;
       ikey = "t_{t}5/shadowed/(XXXX).m_Foo3.r_Root.p_None"};
     source_loc = None;
     doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
     canonical = None;
     equation =
      {Odoc_model.Lang.TypeDecl.Equation.params = []; private_ = false;
       manifest =
        Some
         (Odoc_model.Lang.TypeExpr.Constr
           (`DotT
              (`Identifier
                 ({Odoc_model__Paths_types.iv =
                    `Module
                      ({Odoc_model__Paths_types.iv =
                         `Root
                           (Some
                             {Odoc_model__Paths_types.iv = `Page (None, None);
                              ihash = 236059787; ikey = "p_None"},
                            Root);
                        ihash = 818126955; ikey = "r_Root.p_None"},
                       Foo);
                   ihash = 249248993; ikey = "m_Foo.r_Root.p_None"},
                  false),
               t),
           []));
       constraints = []};
     representation = None});
   Odoc_model.Lang.Signature.Value
    {Odoc_model.Lang.Value.id =
      {Odoc_model__Paths_types.iv =
        `Value
          ({Odoc_model__Paths_types.iv =
             `Module
               ({Odoc_model__Paths_types.iv =
                  `Root
                    (Some
                      {Odoc_model__Paths_types.iv = `Page (None, None);
                       ihash = 236059787; ikey = "p_None"},
                     Root);
                 ihash = 818126955; ikey = "r_Root.p_None"},
                Foo3);
            ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
           {x}6/shadowed/(XXXX));
       ihash = 1011043008;
       ikey = "v_{x}6/shadowed/(XXXX).m_Foo3.r_Root.p_None"};
     source_loc = None; value = Odoc_model.Lang.Value.Abstract;
     doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
     type_ = Odoc_model.Lang.TypeExpr.Constr (`Resolved (`CoreType int), [])};
   Odoc_model.Lang.Signature.Value
    {Odoc_model.Lang.Value.id =
      {Odoc_model__Paths_types.iv =
        `Value
          ({Odoc_model__Paths_types.iv =
             `Module
               ({Odoc_model__Paths_types.iv =
                  `Root
                    (Some
                      {Odoc_model__Paths_types.iv = `Page (None, None);
                       ihash = 236059787; ikey = "p_None"},
                     Root);
                 ihash = 818126955; ikey = "r_Root.p_None"},
                Foo3);
            ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
           id);
       ihash = 424389437; ikey = "v_id.m_Foo3.r_Root.p_None"};
     source_loc = None; value = Odoc_model.Lang.Value.Abstract;
     doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
     type_ =
      Odoc_model.Lang.TypeExpr.Constr
       (`Identifier
          ({Odoc_model__Paths_types.iv =
             `Type
               ({Odoc_model__Paths_types.iv =
                  `Module
                    ({Odoc_model__Paths_types.iv =
                       `Root
                         (Some
                           {Odoc_model__Paths_types.iv = `Page (None, None);
                            ihash = 236059787; ikey = "p_None"},
                          Root);
                      ihash = 818126955; ikey = "r_Root.p_None"},
                     Foo3);
                 ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
                {t}5/shadowed/(XXXX));
            ihash = 995358055;
            ikey = "t_{t}5/shadowed/(XXXX).m_Foo3.r_Root.p_None"},
           false),
       [])}];
 compiled = false; removed = [];
 doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}}

And overriding modules?

let test_data = {|
module Foo : sig
   module Bar : sig
     type t
   end

   val id : Bar.t
end

module Foo3 : sig
  include module type of struct include Foo end

  module Bar : sig
    type u
  end

  val id3 : Bar.u
end
|};;
let sg = Common.signature_of_mli_string test_data;;
# Common.LangUtils.Lens.get (module_expansion_include_sig "Foo3" 0) sg;;
- : Odoc_model.Lang.Signature.t =
{Odoc_model.Lang.Signature.items =
  [Odoc_model.Lang.Signature.Module (Odoc_model.Lang.Signature.Ordinary,
    {Odoc_model.Lang.Module.id =
      {Odoc_model__Paths_types.iv =
        `Module
          ({Odoc_model__Paths_types.iv =
             `Module
               ({Odoc_model__Paths_types.iv =
                  `Root
                    (Some
                      {Odoc_model__Paths_types.iv = `Page (None, None);
                       ihash = 236059787; ikey = "p_None"},
                     Root);
                 ihash = 818126955; ikey = "r_Root.p_None"},
                Foo3);
            ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
           {Bar}8/shadowed/(XXXX));
       ihash = 38422300;
       ikey = "m_{Bar}8/shadowed/(XXXX).m_Foo3.r_Root.p_None"};
     source_loc = None;
     doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
     type_ =
      Odoc_model.Lang.Module.Alias
       (`Dot
          (`Identifier
             ({Odoc_model__Paths_types.iv =
                `Module
                  ({Odoc_model__Paths_types.iv =
                     `Root
                       (Some
                         {Odoc_model__Paths_types.iv = `Page (None, None);
                          ihash = 236059787; ikey = "p_None"},
                        Root);
                    ihash = 818126955; ikey = "r_Root.p_None"},
                   Foo);
               ihash = 249248993; ikey = "m_Foo.r_Root.p_None"},
              false),
           Bar),
        None);
     canonical = None; hidden = false});
   Odoc_model.Lang.Signature.Value
    {Odoc_model.Lang.Value.id =
      {Odoc_model__Paths_types.iv =
        `Value
          ({Odoc_model__Paths_types.iv =
             `Module
               ({Odoc_model__Paths_types.iv =
                  `Root
                    (Some
                      {Odoc_model__Paths_types.iv = `Page (None, None);
                       ihash = 236059787; ikey = "p_None"},
                     Root);
                 ihash = 818126955; ikey = "r_Root.p_None"},
                Foo3);
            ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
           id);
       ihash = 424389437; ikey = "v_id.m_Foo3.r_Root.p_None"};
     source_loc = None; value = Odoc_model.Lang.Value.Abstract;
     doc = {Odoc_model__.Comment.elements = []; warnings_tag = None};
     type_ =
      Odoc_model.Lang.TypeExpr.Constr
       (`DotT
          (`Identifier
             ({Odoc_model__Paths_types.iv =
                `Module
                  ({Odoc_model__Paths_types.iv =
                     `Module
                       ({Odoc_model__Paths_types.iv =
                          `Root
                            (Some
                              {Odoc_model__Paths_types.iv =
                                `Page (None, None);
                               ihash = 236059787; ikey = "p_None"},
                             Root);
                         ihash = 818126955; ikey = "r_Root.p_None"},
                        Foo3);
                    ihash = 670280318; ikey = "m_Foo3.r_Root.p_None"},
                   {Bar}8/shadowed/(XXXX));
               ihash = 38422300;
               ikey = "m_{Bar}8/shadowed/(XXXX).m_Foo3.r_Root.p_None"},
              true),
           t),
       [])}];
 compiled = false; removed = [];
 doc = {Odoc_model__.Comment.elements = []; warnings_tag = None}}