• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ocaml / odoc / 3129

01 May 2026 03:36PM UTC coverage: 71.05% (-0.1%) from 71.191%
3129

Pull #1407

github

web-flow
Merge 1ee25b106 into 27216c784
Pull Request #1407: OxCaml: Support for unboxed named types

1 of 31 new or added lines in 10 files covered. (3.23%)

11 existing lines in 3 files now uncovered.

10411 of 14653 relevant lines covered (71.05%)

5889.64 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

63.01
/src/xref2/tools.ml
1
open Odoc_model.Names
2

3
(* Add [result] and a bind operator over it in scope *)
4
open Odoc_utils.ResultMonad
5

6
type expansion =
7
  | Signature of Component.Signature.t
8
  | Functor of Component.FunctorParameter.t * Component.ModuleType.expr
9

10
type ('a, 'b) either = Left of 'a | Right of 'b
11

12
type module_modifiers =
13
  [ `Aliased of Cpath.Resolved.module_ | `SubstMT of Cpath.Resolved.module_type ]
14

15
type module_type_modifiers = [ `AliasModuleType of Cpath.Resolved.module_type ]
16

17
(* These three functions take a fully-qualified canonical path and return
18
   a list of shorter possibilities to test *)
19
let c_mod_poss env p =
20
  (* canonical module paths *)
21
  let rec inner = function
160✔
22
    | `Dot (p, n) -> (
205✔
23
        let rest = List.map (fun p -> `Dot (p, n)) (inner p) in
205✔
24
        match Env.lookup_by_name Env.s_module (ModuleName.to_string n) env with
205✔
25
        | Ok (`Module (id, m)) ->
190✔
26
            let m = Component.Delayed.get m in
27
            `Identifier (id, m.hidden) :: rest
190✔
28
        | Error _ -> rest)
15✔
29
    | p -> [ p ]
160✔
30
  in
31
  inner p
32

33
let c_modty_poss env p =
34
  (* canonical module type paths *)
35
  match p with
4✔
36
  | `DotMT (p, n) -> (
4✔
37
      let rest = List.map (fun p -> `DotMT (p, n)) (c_mod_poss env p) in
4✔
38
      match
4✔
39
        Env.lookup_by_name Env.s_module_type (ModuleTypeName.to_string n) env
4✔
40
      with
41
      | Ok (`ModuleType (id, _)) -> `Identifier (id, false) :: rest
4✔
42
      | Error _ -> rest)
×
43
  | p -> [ p ]
×
44

45
let c_ty_poss env p =
46
  (* canonical type paths *)
47
  match p with
6✔
48
  | `DotT (p, n) -> (
6✔
49
      let rest = List.map (fun p -> `DotT (p, n)) (c_mod_poss env p) in
6✔
50
      match Env.lookup_by_name Env.s_datatype (TypeName.to_string n) env with
6✔
51
      | Ok (`Type (id, _)) ->
6✔
52
          `Identifier ((id :> Odoc_model.Paths.Identifier.Path.Type.t), false)
53
          :: rest
54
      | Error _ -> rest)
×
55
  | p -> [ p ]
×
56

57
(* Small helper function for resolving canonical paths.
58
   [canonical_helper env resolve lang_of possibilities p2] takes the
59
   fully-qualified path [p2] and returns the shortest resolved path
60
   whose identifier is the same as the resolved fully qualified path.
61
   [resolve] is a function that resolves an arbitrary unresolved path,
62
   [lang_of] turns a resolved path into a generic resolved Lang path
63
   and [possibilities] is a function that, given the fully qualified
64
   unresolved path, returns an ordered list of all possible unresolved
65
   paths starting with the shortest and including the longest one. *)
66
let canonical_helper :
67
    'unresolved 'resolved.
68
    Env.t ->
69
    (Env.t -> 'unresolved -> ('resolved * 'result, _) result) ->
70
    ('resolved -> Odoc_model.Paths.Path.Resolved.t) ->
71
    (Env.t -> 'unresolved -> 'unresolved list) ->
72
    'unresolved ->
73
    ('resolved * 'result) option =
74
 fun env resolve lang_of possibilities p2 ->
75
  let resolve p =
162✔
76
    match resolve env p with Ok rp -> Some rp | Error _ -> None
2✔
77
  in
78
  let get_identifier cpath =
79
    Odoc_model.Paths.Path.Resolved.identifier (lang_of cpath)
329✔
80
  in
81
  match resolve p2 with
82
  | None -> None
2✔
83
  | Some (rp2, _) -> (
160✔
84
      let fallback_id = get_identifier rp2 in
85
      let resolved =
160✔
86
        Odoc_utils.List.filter_map resolve (possibilities env p2)
160✔
87
      in
88
      let find_fn (r, _) = get_identifier r = fallback_id in
160✔
89
      try Some (List.find find_fn resolved) with _ -> None)
×
90

91
let prefix_substitution path sg =
92
  let open Component.Signature in
955✔
93
  let rec get_sub sub' is =
94
    match is with
3,350✔
95
    | [] -> sub'
1,008✔
96
    | Type (id, _, _) :: rest ->
384✔
97
        let name = Ident.Name.typed_type id in
98
        get_sub
384✔
99
          (Subst.add_type id (`Type (path, name)) (`Type (path, name)) sub')
384✔
100
          rest
101
    | Module (id, _, _) :: rest ->
1,386✔
102
        let name = Ident.Name.typed_module id in
103
        get_sub
1,386✔
104
          (Subst.add_module
1,386✔
105
             (id :> Ident.module_)
106
             (`Module (path, name))
107
             (`Module (path, name))
108
             sub')
109
          rest
110
    | ModuleType (id, _) :: rest ->
213✔
111
        let name = Ident.Name.typed_module_type id in
112
        get_sub
213✔
113
          (Subst.add_module_type id
213✔
114
             (`ModuleType (path, name))
115
             (`ModuleType (path, name))
116
             sub')
117
          rest
118
    | ModuleTypeSubstitution (id, _) :: rest ->
3✔
119
        let name = Ident.Name.typed_module_type id in
120
        get_sub
3✔
121
          (Subst.add_module_type id
3✔
122
             (`ModuleType (path, name))
123
             (`ModuleType (path, name))
124
             sub')
125
          rest
126
    | ModuleSubstitution (id, _) :: rest ->
1✔
127
        let name = Ident.Name.typed_module id in
128
        get_sub
1✔
129
          (Subst.add_module
1✔
130
             (id :> Ident.module_)
131
             (`Module (path, name))
132
             (`Module (path, name))
133
             sub')
134
          rest
135
    | TypeSubstitution (id, _) :: rest ->
2✔
136
        let name = Ident.Name.typed_type id in
137
        get_sub
2✔
138
          (Subst.add_type id (`Type (path, name)) (`Type (path, name)) sub')
2✔
139
          rest
140
    | Exception _ :: rest
12✔
141
    | TypExt _ :: rest
29✔
142
    | Value (_, _) :: rest
114✔
143
    | Comment _ :: rest ->
131✔
144
        get_sub sub' rest
145
    | Class (id, _, _) :: rest ->
10✔
146
        let name = Ident.Name.typed_type id in
147
        get_sub
10✔
148
          (Subst.add_class id (`Class (path, name)) (`Class (path, name)) sub')
10✔
149
          rest
150
    | ClassType (id, _, _) :: rest ->
4✔
151
        let name = Ident.Name.typed_type id in
152
        get_sub
4✔
153
          (Subst.add_class_type id
4✔
154
             (`ClassType (path, name))
155
             (`ClassType (path, name))
156
             sub')
157
          rest
158
    | Include i :: rest -> get_sub (get_sub sub' i.expansion_.items) rest
42✔
159
    | Open o :: rest -> get_sub (get_sub sub' o.expansion.items) rest
11✔
160
  in
161
  get_sub Subst.identity sg.items
162

163
let prefix_signature (path, sg) =
164
  let open Component.Signature in
167✔
165
  let sub = prefix_substitution path sg in
166
  let items =
167✔
167
    List.map
168
      (function
169
        | Module (id, r, m) ->
222✔
170
            Module
171
              ( Ident.Rename.module_ id,
222✔
172
                r,
173
                Component.Delayed.put (fun () ->
222✔
174
                    Subst.module_ sub (Component.Delayed.get m)) )
64✔
175
        | ModuleType (id, mt) ->
90✔
176
            ModuleType
177
              ( Ident.Rename.module_type id,
90✔
178
                Component.Delayed.put (fun () ->
90✔
179
                    Subst.module_type sub (Component.Delayed.get mt)) )
12✔
180
        | Type (id, r, t) ->
174✔
181
            Type
182
              ( Ident.Rename.type_ id,
174✔
183
                r,
184
                Component.Delayed.put (fun () ->
174✔
185
                    Subst.type_ sub (Component.Delayed.get t)) )
60✔
186
        | TypeSubstitution (id, t) ->
2✔
187
            TypeSubstitution (Ident.Rename.type_ id, Subst.type_ sub t)
2✔
188
        | ModuleSubstitution (id, m) ->
1✔
189
            ModuleSubstitution
190
              (Ident.Rename.module_ id, Subst.module_substitution sub m)
1✔
191
        | ModuleTypeSubstitution (id, m) ->
1✔
192
            ModuleTypeSubstitution
193
              (Ident.Rename.module_type id, Subst.module_type_substitution sub m)
1✔
194
        | Exception (id, e) -> Exception (id, Subst.exception_ sub e)
6✔
195
        | TypExt t -> TypExt (Subst.extension sub t)
17✔
196
        | Value (id, v) ->
50✔
197
            Value
198
              ( id,
199
                Component.Delayed.put (fun () ->
50✔
200
                    Subst.value sub (Component.Delayed.get v)) )
9✔
201
        | Class (id, r, c) ->
4✔
202
            Class (Ident.Rename.type_ id, r, Subst.class_ sub c)
4✔
203
        | ClassType (id, r, c) ->
×
204
            ClassType (Ident.Rename.type_ id, r, Subst.class_type sub c)
×
205
        | Include i -> Include (Subst.include_ sub i)
17✔
206
        | Open o -> Open (Subst.open_ sub o)
3✔
207
        | Comment c -> Comment c)
72✔
208
      sg.items
209
  in
210
  { sg with items }
167✔
211

212
open Errors.Tools_error
213

214
type resolve_module_result =
215
  ( Cpath.Resolved.module_ * Component.Module.t Component.Delayed.t,
216
    simple_module_lookup_error )
217
  result
218

219
type resolve_module_type_result =
220
  ( Cpath.Resolved.module_type * Component.ModuleType.t,
221
    simple_module_type_lookup_error )
222
  result
223

224
type resolve_type_result =
225
  (Cpath.Resolved.type_ * Find.careful_type, simple_type_lookup_error) result
226

227
type resolve_value_result =
228
  (Cpath.Resolved.value * Find.value, simple_value_lookup_error) result
229

230
type resolve_class_type_result =
231
  ( Cpath.Resolved.class_type * Find.careful_class,
232
    simple_type_lookup_error )
233
  result
234

235
type ('a, 'b, 'c) sig_map = { type_ : 'a; module_ : 'b; module_type : 'c }
236

237
let id_map = { type_ = None; module_ = None; module_type = None }
238

239
module type MEMO = sig
240
  type result
241

242
  include Hashtbl.HashedType
243
end
244

245
module MakeMemo (X : MEMO) = struct
246
  module M = Hashtbl.Make (X)
247

248
  let cache : (X.result * int * Env.LookupTypeSet.t) M.t = M.create 10000
6,205✔
249

250
  let enabled = ref true
251

252
  let memoize f env arg =
253
    if not !enabled then f env arg
×
254
    else
255
      let env_id = Env.id env in
14,172✔
256
      let no_memo () =
14,172✔
257
        let lookups, result =
7,204✔
258
          Env.with_recorded_lookups env (fun env' -> f env' arg)
7,204✔
259
        in
260
        M.add cache arg (result, env_id, lookups);
7,204✔
261
        result
7,204✔
262
      in
263
      match M.find_all cache arg with
264
      | [] -> no_memo ()
7,156✔
265
      | xs ->
7,016✔
266
          let rec find_fast = function
267
            | (result, env_id', _) :: _ when env_id' = env_id -> result
3,488✔
268
            | _ :: ys -> find_fast ys
3,566✔
269
            | [] -> find xs
3,528✔
270
          and find = function
271
            | (m, _, lookups) :: xs ->
3,538✔
272
                if Env.verify_lookups env lookups then m else find xs
58✔
273
            | [] -> no_memo ()
48✔
274
          in
275
          find_fast xs
276

277
  let clear () = M.clear cache
×
278
end
279

280
module LookupModuleMemo = MakeMemo (struct
281
  type t = Cpath.Resolved.module_
282

283
  type result =
284
    ( Component.Module.t Component.Delayed.t,
285
      simple_module_lookup_error )
286
    Result.t
287

288
  let equal = ( = )
289

290
  let hash = Hashtbl.hash
291
end)
292

293
module LookupParentMemo = MakeMemo (struct
294
  type t = Cpath.Resolved.parent
295

296
  type result =
297
    ( Component.Signature.t * Component.Substitution.t,
298
      [ `Parent of parent_lookup_error ] )
299
    Result.t
300

301
  let equal = ( = )
302

303
  let hash = Hashtbl.hash
304
end)
305

306
module LookupAndResolveMemo = MakeMemo (struct
307
  type t = Cpath.module_
308

309
  type result = resolve_module_result
310

311
  let equal = ( = )
312

313
  let hash = Hashtbl.hash
314
end)
315

316
module HandleCanonicalModuleMemo = MakeMemo (struct
317
  type t = Odoc_model.Paths.Path.Module.t
318

319
  type result = Odoc_model.Paths.Path.Module.t
320

321
  let equal x3 y3 = x3 = y3
214✔
322

323
  let hash y = Hashtbl.hash y
466✔
324
end)
325

326
module ExpansionOfModuleMemo = MakeMemo (struct
327
  type t = Cpath.Resolved.module_
328

329
  type result = (expansion, expansion_of_module_error) Result.t
330

331
  let equal = ( = )
332

333
  let hash = Hashtbl.hash
334
end)
335

336
let disable_all_caches () =
337
  LookupModuleMemo.enabled := false;
×
338
  LookupAndResolveMemo.enabled := false;
339
  ExpansionOfModuleMemo.enabled := false;
340
  LookupParentMemo.enabled := false
341

342
let reset_caches () =
343
  LookupModuleMemo.clear ();
×
344
  LookupAndResolveMemo.clear ();
×
345
  ExpansionOfModuleMemo.clear ();
×
346
  LookupParentMemo.clear ()
×
347

348
let simplify_module : Env.t -> Cpath.Resolved.module_ -> Cpath.Resolved.module_
349
    =
350
 fun env m ->
351
  let open Odoc_model.Paths.Identifier in
1,006✔
352
  match m with
353
  | `Module (`Module (`Gpath (`Identifier p)), name) -> (
451✔
354
      let ident = (Mk.module_ ((p :> Signature.t), name) : Path.Module.t) in
451✔
355
      match Env.(lookup_by_id s_module (ident :> Signature.t) env) with
451✔
356
      | Some _ -> `Gpath (`Identifier ident)
358✔
357
      | None -> m)
93✔
358
  | _ -> m
555✔
359

360
let simplify_module_type :
361
    Env.t -> Cpath.Resolved.module_type -> Cpath.Resolved.module_type =
362
 fun env m ->
363
  let open Odoc_model.Paths.Identifier in
113✔
364
  match m with
365
  | `ModuleType (`Module (`Gpath (`Identifier p)), name) -> (
49✔
366
      let ident =
367
        (Mk.module_type ((p :> Signature.t), name) : Path.ModuleType.t)
49✔
368
      in
369
      match Env.(lookup_by_id s_module_type (ident :> Signature.t) env) with
49✔
370
      | Some _ -> `Gpath (`Identifier ident)
8✔
371
      | None -> m)
41✔
372
  | _ -> m
64✔
373

374
let simplify_type : Env.t -> Cpath.Resolved.type_ -> Cpath.Resolved.type_ =
375
 fun env m ->
376
  let open Odoc_model.Paths.Identifier in
161✔
377
  match m with
378
  | `Type (`Module (`Gpath (`Identifier p)), name) -> (
74✔
379
      let ident = (Mk.type_ ((p :> Signature.t), name) : Path.Type.t) in
74✔
380
      match Env.(lookup_by_id s_datatype (ident :> Path.Type.t) env) with
74✔
381
      | Some _ -> `Gpath (`Identifier ident)
10✔
382
      | None -> m)
64✔
383
  | _ -> m
87✔
384

385
let rec handle_apply env func_path arg_path m =
386
  let rec find_functor mty =
20✔
387
    match mty with
20✔
388
    | Component.ModuleType.Functor (Named arg, expr) ->
20✔
389
        Ok (arg.Component.FunctorParameter.id, expr)
390
    | Component.ModuleType.Path { p_path; _ } -> (
×
391
        match resolve_module_type env p_path with
392
        | Ok (_, { Component.ModuleType.expr = Some mty'; _ }) ->
×
393
            find_functor mty'
394
        | _ -> Error `OpaqueModule)
×
395
    | _ -> Error `ApplyNotFunctor
×
396
  in
397
  module_type_expr_of_module env m >>= fun mty' ->
20✔
398
  find_functor mty' >>= fun (arg_id, result) ->
20✔
399
  let new_module = { m with Component.Module.type_ = ModuleType result } in
20✔
400
  let substitution = `Substituted arg_path in
401

402
  let path = `Apply (func_path, arg_path) in
403
  let subst =
404
    Subst.add_module
405
      (arg_id :> Ident.module_)
406
      (`Resolved substitution) substitution Subst.identity
407
  in
408
  let subst = Subst.unresolve_opaque_paths subst in
20✔
409
  Ok (path, Subst.module_ subst new_module)
20✔
410

411
and add_canonical_path :
412
    Component.Module.t -> Cpath.Resolved.module_ -> Cpath.Resolved.module_ =
413
 fun m p ->
414
  match p with
1,850✔
415
  | `Canonical _ -> p
×
416
  | _ -> (
1,850✔
417
      match m.Component.Module.canonical with
418
      | Some cp -> `Canonical (p, cp)
441✔
419
      | None -> p)
1,409✔
420

421
and add_canonical_path_mt :
422
    Component.ModuleType.t ->
423
    Cpath.Resolved.module_type ->
424
    Cpath.Resolved.module_type =
425
 fun m p ->
426
  match p with
407✔
427
  | `CanonicalModuleType _ -> p
×
428
  | _ -> (
407✔
429
      match m.canonical with
430
      | Some cp -> `CanonicalModuleType (p, cp)
7✔
431
      | None -> p)
400✔
432

433
and get_substituted_module_type :
434
    Env.t -> Component.ModuleType.expr -> Cpath.Resolved.module_type option =
435
 fun env expr ->
436
  match expr with
924✔
437
  | Component.ModuleType.Path { p_path; _ } ->
72✔
438
      if Cpath.is_module_type_substituted p_path then
439
        match resolve_module_type env p_path with
16✔
440
        | Ok (resolved_path, _) -> Some resolved_path
16✔
441
        | Error _ -> None
×
442
      else None
56✔
443
  | _ -> None
852✔
444

445
and get_module_type_path_modifiers :
446
    Env.t -> Component.ModuleType.t -> module_type_modifiers option =
447
 fun env m ->
448
  let alias_of expr =
432✔
449
    match expr with
411✔
450
    | Component.ModuleType.Path alias_path -> (
47✔
451
        match resolve_module_type env alias_path.p_path with
452
        | Ok (resolved_alias_path, _) -> Some resolved_alias_path
47✔
453
        | Error _ -> None)
×
454
    (* | Functor (_arg, res) -> alias_of res *)
455
    | _ -> None
364✔
456
  in
457
  match m.expr with
458
  | Some e -> (
411✔
459
      match alias_of e with Some e -> Some (`AliasModuleType e) | None -> None)
47✔
460
  | None -> None
21✔
461

462
and process_module_type env m p' =
463
  let open Component.ModuleType in
407✔
464
  let open Odoc_utils.OptionMonad in
465
  (* Loop through potential chains of module_type equalities, looking for substitutions *)
466
  let substpath =
467
    m.expr >>= get_substituted_module_type env >>= fun p ->
407✔
468
    Some (`SubstT (p, p'))
10✔
469
  in
470

471
  let p' = match substpath with Some p -> p | None -> p' in
10✔
472
  let p'' =
473
    match get_module_type_path_modifiers env m with
474
    | Some (`AliasModuleType e) -> `AliasModuleType (e, p')
45✔
475
    | None -> p'
362✔
476
  in
477
  add_canonical_path_mt m p''
478

479
and get_module_path_modifiers : Env.t -> Component.Module.t -> _ option =
480
 fun env m ->
481
  match m.type_ with
2,029✔
482
  | Alias (alias_path, _) -> (
1,491✔
483
      match resolve_module env alias_path with
484
      | Ok (resolved_alias_path, _) -> Some (`Aliased resolved_alias_path)
1,488✔
485
      | Error _ -> None)
3✔
486
  | ModuleType t -> (
538✔
487
      match get_substituted_module_type env t with
488
      | Some s -> Some (`SubstMT s)
6✔
489
      | None -> None)
532✔
490

491
and process_module_path env m rp =
492
  let rp = if m.Component.Module.hidden then `Hidden rp else rp in
71✔
493
  let rp' =
494
    match get_module_path_modifiers env m with
495
    | None -> rp
371✔
496
    | Some (`Aliased rp') ->
1,474✔
497
        let dest_hidden =
498
          Cpath.is_resolved_module_hidden ~weak_canonical_test:true rp'
499
        in
500
        if dest_hidden then rp
28✔
501
        else
502
          let unresolved_rp =
1,446✔
503
            try Cpath.unresolve_resolved_module_path rp with _ -> `Resolved rp
1✔
504
          in
505
          (* Keep the resolved path for the canonical processing below in handle_canonical_module.strip_alias *)
506
          `Alias (rp', unresolved_rp, Some rp)
507
    | Some (`SubstMT p') -> `Subst (p', rp)
5✔
508
  in
509
  add_canonical_path m rp'
510

511
and handle_module_lookup env id rparent sg sub =
512
  match Find.careful_module_in_sig sg id with
1,008✔
513
  | Some (`FModule (name, m)) ->
1,006✔
514
      let rp' = simplify_module env (`Module (rparent, name)) in
515
      let m' = Subst.module_ sub m in
1,006✔
516
      let md' = Component.Delayed.put_val m' in
1,006✔
517
      Ok (process_module_path env m' rp', md')
1,006✔
518
  | Some (`FModule_removed p) -> resolve_module env p
×
519
  | None -> Error `Find_failure
2✔
520

521
and handle_module_type_lookup env id p sg sub =
522
  let open Odoc_utils.OptionMonad in
113✔
523
  Find.module_type_in_sig sg id >>= fun (`FModuleType (name, mt)) ->
113✔
524
  let mt = Subst.module_type sub mt in
113✔
525
  let p' = simplify_module_type env (`ModuleType (p, name)) in
113✔
526
  let p'' = process_module_type env mt p' in
113✔
527
  Some (p'', mt)
113✔
528

529
and handle_type_lookup env id p sg =
530
  match Find.careful_type_in_sig sg id with
168✔
531
  | Some (`FClass (name, _) as t) -> Ok (`Class (p, name), t)
2✔
532
  | Some (`CoreType _ as c) -> Ok (c, c)
×
533
  | Some (`FClassType (name, _) as t) -> Ok (`ClassType (p, name), t)
4✔
534
  | Some (`FType (name, _) as t) -> Ok (simplify_type env (`Type (p, name)), t)
161✔
535
  | Some (`FType_removed (name, _, _) as t) -> Ok (`Type (p, name), t)
1✔
536
  | None -> Error `Find_failure
×
537

538
and handle_value_lookup _env id p sg =
539
  match Find.value_in_sig sg id with
5✔
540
  | Some (`FValue (name, _) as v) -> Ok (`Value (p, name), v)
5✔
541
  | _ -> Error `Find_failure
×
542

543
and handle_class_type_lookup id p sg =
544
  match Find.careful_class_in_sig sg id with
6✔
545
  | Some (`FClass (name, _) as t) -> Ok (`Class (p, name), t)
×
546
  | Some (`FClassType (name, _) as t) -> Ok (`ClassType (p, name), t)
6✔
547
  | Some (`FType_removed (_name, _, _) as _t) -> Error `Class_replaced
×
548
  | None -> Error `Find_failure
×
549

550
and lookup_module_gpath :
551
    Env.t ->
552
    Odoc_model.Paths.Path.Resolved.Module.t ->
553
    (Component.Module.t Component.Delayed.t, simple_module_lookup_error) result
554
    =
555
 fun env path ->
556
  match path with
352✔
557
  | `Identifier i ->
352✔
558
      of_option ~error:(`Lookup_failure i) (Env.(lookup_by_id s_module) i env)
352✔
559
      >>= fun (`Module (_, m)) -> Ok m
352✔
560
  | `Apply (functor_path, argument_path) ->
×
561
      lookup_module_gpath env functor_path >>= fun functor_module ->
×
562
      let functor_module = Component.Delayed.get functor_module in
×
563
      handle_apply env (`Gpath functor_path) (`Gpath argument_path)
×
564
        functor_module
565
      |> map_error (fun e -> `Parent (`Parent_expr e))
×
566
      >>= fun (_, m) -> Ok (Component.Delayed.put_val m)
×
567
  | `Module (parent, name) ->
×
568
      let find_in_sg sg sub =
569
        match Find.careful_module_in_sig sg name with
×
570
        | None -> Error `Find_failure
×
571
        | Some (`FModule (_, m)) ->
×
572
            Ok (Component.Delayed.put_val (Subst.module_ sub m))
×
573
        | Some (`FModule_removed p) ->
×
574
            resolve_module env p >>= fun (_, m) -> Ok m
×
575
      in
576
      lookup_parent_gpath env parent
577
      |> map_error (fun e -> (e :> simple_module_lookup_error))
×
578
      >>= fun (sg, sub) -> find_in_sg sg sub
×
579
  | `Alias (p, _) -> lookup_module_gpath env p
×
580
  | `Subst (_, p) -> lookup_module_gpath env p
×
581
  | `Hidden p -> lookup_module_gpath env p
×
582
  | `Canonical (p, _) -> lookup_module_gpath env p
×
583
  | `OpaqueModule m -> lookup_module_gpath env m
×
584
  | `Substituted m -> lookup_module_gpath env m
×
585

586
and lookup_module :
587
    Env.t ->
588
    Cpath.Resolved.module_ ->
589
    (Component.Module.t Component.Delayed.t, simple_module_lookup_error) result
590
    =
591
 fun env' path' ->
592
  let lookup env (path : ExpansionOfModuleMemo.M.key) =
2,500✔
593
    match path with
1,787✔
594
    | `Local lpath -> Error (`Local (env, lpath))
×
595
    | `Gpath p -> lookup_module_gpath env p
352✔
596
    | `Substituted x -> lookup_module env x
21✔
597
    | `Apply (functor_path, argument_path) ->
11✔
598
        lookup_module env functor_path >>= fun functor_module ->
11✔
599
        let functor_module = Component.Delayed.get functor_module in
11✔
600
        handle_apply env functor_path argument_path functor_module
11✔
601
        |> map_error (fun e -> `Parent (`Parent_expr e))
×
602
        >>= fun (_, m) -> Ok (Component.Delayed.put_val m)
11✔
603
    | `Module (parent, name) ->
93✔
604
        let find_in_sg sg sub =
605
          match Find.careful_module_in_sig sg name with
93✔
606
          | None -> Error `Find_failure
×
607
          | Some (`FModule (_, m)) ->
93✔
608
              Ok (Component.Delayed.put_val (Subst.module_ sub m))
93✔
609
          | Some (`FModule_removed p) ->
×
610
              resolve_module env p >>= fun (_, m) -> Ok m
×
611
        in
612
        lookup_parent env parent
613
        |> map_error (fun e -> (e :> simple_module_lookup_error))
×
614
        >>= fun (sg, sub) -> find_in_sg sg sub
93✔
615
    | `Alias (_, cs, _) -> (
729✔
616
        match resolve_module env cs with
617
        | Ok (_, r) -> Ok r
729✔
618
        | Error e -> Error e)
×
619
    | `Subst (_, p) -> lookup_module env p
3✔
620
    | `Hidden p -> lookup_module env p
86✔
621
    | `Canonical (p, _) -> lookup_module env p
492✔
622
    | `OpaqueModule m -> lookup_module env m
×
623
  in
624
  LookupModuleMemo.memoize lookup env' path'
625

626
and lookup_module_type_gpath :
627
    Env.t ->
628
    Odoc_model.Paths.Path.Resolved.ModuleType.t ->
629
    (Component.ModuleType.t, simple_module_type_lookup_error) result =
630
 fun env path ->
631
  match path with
113✔
632
  | `Identifier i ->
113✔
633
      of_option ~error:(`Lookup_failureMT i)
113✔
634
        (Env.(lookup_by_id s_module_type) i env)
113✔
635
      >>= fun (`ModuleType (_, mt)) -> Ok mt
113✔
636
  | `CanonicalModuleType (s, _) | `SubstT (_, s) ->
×
637
      lookup_module_type_gpath env s
638
  | `ModuleType (parent, name) ->
×
639
      let find_in_sg sg sub =
640
        match Find.module_type_in_sig sg name with
×
641
        | None -> Error `Find_failure
×
642
        | Some (`FModuleType (_, mt)) -> Ok (Subst.module_type sub mt)
×
643
      in
644
      lookup_parent_gpath env parent
645
      |> map_error (fun e -> (e :> simple_module_type_lookup_error))
×
646
      >>= fun (sg, sub) -> find_in_sg sg sub
×
647
  | `AliasModuleType (_, mt) -> lookup_module_type_gpath env mt
×
648
  | `OpaqueModuleType m -> lookup_module_type_gpath env m
×
649
  | `SubstitutedMT m -> lookup_module_type_gpath env m
×
650

651
and lookup_module_type :
652
    Env.t ->
653
    Cpath.Resolved.module_type ->
654
    (Component.ModuleType.t, simple_module_type_lookup_error) result =
655
 fun env path ->
656
  let lookup env =
188✔
657
    match path with
188✔
658
    | `Local l -> Error (`LocalMT (env, l))
×
659
    | `Gpath p -> lookup_module_type_gpath env p
113✔
660
    | `Substituted s | `CanonicalModuleType (s, _) | `SubstT (_, s) ->
×
661
        lookup_module_type env s
662
    | `ModuleType (parent, name) ->
34✔
663
        let find_in_sg sg sub =
664
          match Find.module_type_in_sig sg name with
34✔
665
          | None -> Error `Find_failure
×
666
          | Some (`FModuleType (_, mt)) -> Ok (Subst.module_type sub mt)
34✔
667
        in
668
        lookup_parent env parent
669
        |> map_error (fun e -> (e :> simple_module_type_lookup_error))
×
670
        >>= fun (sg, sub) -> find_in_sg sg sub
34✔
671
    | `AliasModuleType (_, mt) -> lookup_module_type env mt
9✔
672
    | `OpaqueModuleType m -> lookup_module_type env m
10✔
673
  in
674
  lookup env
675

676
and lookup_parent :
677
    Env.t ->
678
    Cpath.Resolved.parent ->
679
    ( Component.Signature.t * Component.Substitution.t,
680
      [ `Parent of parent_lookup_error ] )
681
    result =
682
 fun env' parent' ->
683
  let lookup env parent =
1,422✔
684
    match parent with
783✔
685
    | `Module p ->
782✔
686
        lookup_module env p |> map_error (fun e -> `Parent (`Parent_module e))
×
687
        >>= fun m ->
688
        let m = Component.Delayed.get m in
782✔
689
        expansion_of_module env m
782✔
690
        |> map_error (fun e -> `Parent (`Parent_sig e))
×
691
        >>= assert_not_functor
782✔
692
        >>= fun sg -> Ok (sg, prefix_substitution parent sg)
782✔
693
    | `ModuleType p ->
×
694
        lookup_module_type env p
695
        |> map_error (fun e -> `Parent (`Parent_module_type e))
×
696
        >>= fun mt ->
697
        expansion_of_module_type env mt
×
698
        |> map_error (fun e -> `Parent (`Parent_sig e))
×
699
        >>= assert_not_functor
×
700
        >>= fun sg -> Ok (sg, prefix_substitution parent sg)
×
701
    | `FragmentRoot ->
1✔
702
        Env.lookup_fragment_root env
703
        |> of_option ~error:(`Parent `Fragment_root)
1✔
704
        >>= fun (_, sg) -> Ok (sg, prefix_substitution parent sg)
1✔
705
  in
706
  LookupParentMemo.memoize lookup env' parent'
707

708
and lookup_parent_gpath :
709
    Env.t ->
710
    Odoc_model.Paths.Path.Resolved.Module.t ->
711
    ( Component.Signature.t * Component.Substitution.t,
712
      [ `Parent of parent_lookup_error ] )
713
    result =
714
 fun env parent ->
715
  lookup_module_gpath env parent
×
716
  |> map_error (fun e -> `Parent (`Parent_module e))
×
717
  >>= fun m ->
718
  let m = Component.Delayed.get m in
×
719
  expansion_of_module env m
×
720
  |> map_error (fun e -> `Parent (`Parent_sig e))
×
721
  >>= assert_not_functor
×
722
  >>= fun sg -> Ok (sg, prefix_substitution (`Module (`Gpath parent)) sg)
×
723

724
and lookup_type_gpath :
725
    Env.t ->
726
    Odoc_model.Paths.Path.Resolved.Type.t ->
727
    (Find.careful_type, simple_type_lookup_error) result =
728
 fun env p ->
729
  let do_type p name =
260✔
730
    lookup_parent_gpath env p
×
731
    |> map_error (fun e -> (e :> simple_type_lookup_error))
×
732
    >>= fun (sg, sub) ->
733
    match Find.careful_type_in_sig sg name with
×
734
    | Some (`FClass (name, c)) -> Ok (`FClass (name, Subst.class_ sub c))
×
735
    | Some (`FClassType (name, ct)) ->
×
736
        Ok (`FClassType (name, Subst.class_type sub ct))
×
737
    | Some (`FType (name, t)) -> Ok (`FType (name, Subst.type_ sub t))
×
738
    | Some (`FType_removed (name, texpr, eq)) ->
×
739
        Ok (`FType_removed (name, Subst.type_expr sub texpr, eq))
×
740
    | Some (`CoreType _ as c) -> Ok c
×
741
    | None -> Error `Find_failure
×
742
  in
743
  let res =
744
    match p with
745
    | `CoreType _ as c -> Ok c
×
746
    | `Identifier ({ iv = `Type _; _ } as i) ->
250✔
747
        of_option ~error:(`Lookup_failureT i)
250✔
748
          (Env.(lookup_by_id s_datatype) i env)
250✔
749
        >>= fun (`Type ({ iv = `Type (_, name); _ }, t)) ->
250✔
750
        Ok (`FType (name, t))
249✔
751
    | `Identifier ({ iv = `Class _; _ } as i) ->
5✔
752
        of_option ~error:(`Lookup_failureT i) (Env.(lookup_by_id s_class) i env)
5✔
753
        >>= fun (`Class ({ iv = `Class (_, name); _ }, t)) ->
5✔
754
        Ok (`FClass (name, t))
5✔
755
    | `Identifier ({ iv = `ClassType _; _ } as i) ->
5✔
756
        of_option ~error:(`Lookup_failureT i)
5✔
757
          (Env.(lookup_by_id s_class_type) i env)
5✔
758
        >>= fun (`ClassType ({ iv = `ClassType (_, name); _ }, t)) ->
5✔
759
        Ok (`FClassType (name, t))
5✔
760
    | `CanonicalType (t1, _) -> lookup_type_gpath env t1
×
761
    | `Type (p, id) -> do_type p id
×
762
    | `Class (p, id) -> do_type p id
×
763
    | `ClassType (p, id) -> do_type p id
×
NEW
764
    | `Unbox t -> lookup_type_gpath env t
×
765
    | `SubstitutedT t -> lookup_type_gpath env t
×
766
    | `SubstitutedCT t ->
×
767
        lookup_type_gpath env (t :> Odoc_model.Paths.Path.Resolved.Type.t)
×
768
  in
769
  res
770

771
and lookup_value_gpath :
772
    Env.t ->
773
    Odoc_model.Paths.Path.Resolved.Value.t ->
774
    (Find.value, simple_value_lookup_error) result =
775
 fun env p ->
776
  let do_value p name =
×
777
    lookup_parent_gpath env p
×
778
    |> map_error (fun e -> (e :> simple_value_lookup_error))
×
779
    >>= fun (sg, sub) ->
780
    match Find.value_in_sig sg name with
×
781
    | Some (`FValue (name, t)) -> Ok (`FValue (name, Subst.value sub t))
×
782
    | None -> Error `Find_failure
×
783
  in
784
  let res =
785
    match p with
786
    | `Identifier ({ iv = `Value _; _ } as i) ->
×
787
        of_option ~error:(`Lookup_failureV i) (Env.(lookup_by_id s_value) i env)
×
788
        >>= fun (`Value ({ iv = `Value (_, name); _ }, t)) ->
×
789
        Ok (`FValue (name, t))
×
790
    | `Value (p, id) -> do_value p id
×
791
  in
792
  res
793

794
and lookup_class_type_gpath :
795
    Env.t ->
796
    Odoc_model.Paths.Path.Resolved.ClassType.t ->
797
    (Find.careful_class, simple_type_lookup_error) result =
798
 fun env p ->
799
  let do_type p name =
13✔
800
    lookup_parent_gpath env p
×
801
    |> map_error (fun e -> (e :> simple_type_lookup_error))
×
802
    >>= fun (sg, sub) ->
803
    match Find.careful_class_in_sig sg name with
×
804
    | Some (`FClass (name, c)) -> Ok (`FClass (name, Subst.class_ sub c))
×
805
    | Some (`FClassType (name, ct)) ->
×
806
        Ok (`FClassType (name, Subst.class_type sub ct))
×
807
    | Some (`FType_removed (name, texpr, eq)) ->
×
808
        Ok (`FType_removed (name, Subst.type_expr sub texpr, eq))
×
809
    | None -> Error `Find_failure
×
810
  in
811
  let res =
812
    match p with
813
    | `Identifier ({ iv = `Class _; _ } as i) ->
7✔
814
        of_option ~error:(`Lookup_failureT i) (Env.(lookup_by_id s_class) i env)
7✔
815
        >>= fun (`Class ({ iv = `Class (_, name); _ }, t)) ->
7✔
816
        Ok (`FClass (name, t))
7✔
817
    | `Identifier ({ iv = `ClassType _; _ } as i) ->
6✔
818
        of_option ~error:(`Lookup_failureT i)
6✔
819
          (Env.(lookup_by_id s_class_type) i env)
6✔
820
        >>= fun (`ClassType ({ iv = `ClassType (_, name); _ }, t)) ->
6✔
821
        Ok (`FClassType (name, t))
6✔
822
    | `Class (p, id) -> do_type p id
×
823
    | `ClassType (p, id) -> do_type p id
×
824
    | `SubstitutedCT c -> lookup_class_type_gpath env c
×
825
  in
826
  res
827

828
and lookup_type :
829
    Env.t ->
830
    Cpath.Resolved.type_ ->
831
    (Find.careful_type, simple_type_lookup_error) result =
832
 fun env p ->
833
  let do_type p name =
885✔
834
    lookup_parent env p |> map_error (fun e -> (e :> simple_type_lookup_error))
×
835
    >>= fun (sg, sub) ->
836
    handle_type_lookup env name p sg >>= fun (_, t') ->
13✔
837
    let t =
13✔
838
      match t' with
839
      | `CoreType _ as c -> c
×
840
      | `FClass (name, c) -> `FClass (name, Subst.class_ sub c)
×
841
      | `FClassType (name, ct) -> `FClassType (name, Subst.class_type sub ct)
×
842
      | `FType (name, t) -> `FType (name, Subst.type_ sub t)
13✔
843
      | `FType_removed (name, texpr, eq) ->
×
844
          `FType_removed (name, Subst.type_expr sub texpr, eq)
×
845
    in
846
    Ok t
847
  in
848
  let res =
849
    match p with
850
    | `CoreType _ as c -> Ok c
609✔
851
    | `Local id -> Error (`LocalType (env, id))
×
852
    | `Gpath p -> lookup_type_gpath env p
260✔
853
    | `CanonicalType (t1, _) -> lookup_type env t1
3✔
854
    | `Substituted s -> lookup_type env s
×
NEW
855
    | `Unbox t -> lookup_type env t
×
856
    | `Type (p, id) -> do_type p id
13✔
857
    | `Class (p, id) -> do_type p id
×
858
    | `ClassType (p, id) -> do_type p id
×
859
  in
860
  res
861

862
and lookup_value :
863
    Env.t -> Cpath.Resolved.value -> (_, simple_value_lookup_error) result =
864
 fun env p ->
865
  match p with
×
866
  | `Value (p, id) ->
×
867
      lookup_parent env p
868
      |> map_error (fun e -> (e :> simple_value_lookup_error))
×
869
      >>= fun (sg, sub) ->
870
      handle_value_lookup env id p sg >>= fun (_, `FValue (name, c)) ->
×
871
      Ok (`FValue (name, Subst.value sub c))
×
872
  | `Gpath p -> lookup_value_gpath env p
×
873

874
and lookup_class_type :
875
    Env.t ->
876
    Cpath.Resolved.class_type ->
877
    (Find.careful_class, simple_type_lookup_error) result =
878
 fun env p ->
879
  let do_type p name =
13✔
880
    lookup_parent env p |> map_error (fun e -> (e :> simple_type_lookup_error))
×
881
    >>= fun (sg, sub) ->
882
    handle_class_type_lookup name p sg >>= fun (_, t') ->
×
883
    let t =
×
884
      match t' with
885
      | `FClass (name, c) -> `FClass (name, Subst.class_ sub c)
×
886
      | `FClassType (name, ct) -> `FClassType (name, Subst.class_type sub ct)
×
887
      | `FType_removed (name, texpr, eq) ->
×
888
          `FType_removed (name, Subst.type_expr sub texpr, eq)
×
889
    in
890
    Ok t
891
  in
892
  let res =
893
    match p with
894
    | `Local id -> Error (`LocalType (env, (id :> Ident.type_)))
×
895
    | `Gpath p -> lookup_class_type_gpath env p
13✔
896
    | `Substituted s -> lookup_class_type env s
×
897
    | `Class (p, id) -> do_type p id
×
898
    | `ClassType (p, id) -> do_type p id
×
899
  in
900
  res
901

902
and resolve_and_lookup_parent :
903
    Env.t ->
904
    Cpath.module_ ->
905
    ( Cpath.Resolved.parent * Component.Signature.t * Component.Substitution.t,
906
      [ `Parent of parent_lookup_error ] )
907
    result =
908
 fun env parent ->
909
  resolve_module env parent |> map_error (fun e -> `Parent (`Parent_module e))
31✔
910
  >>= fun (parent, _) ->
911
  lookup_parent env (`Module parent) >>= fun (parent_sig, sub) ->
1,280✔
912
  Ok (`Module parent, parent_sig, sub)
1,280✔
913

914
and resolve_module : Env.t -> Cpath.module_ -> resolve_module_result =
915
 fun env' path ->
916
  let id = path in
7,207✔
917
  let resolve env p =
918
    match p with
2,927✔
919
    | `Dot (parent, id) ->
1,024✔
920
        resolve_and_lookup_parent env parent
921
        |> map_error (fun e -> (e :> simple_module_lookup_error))
18✔
922
        >>= fun (parent, parent_sig, sub) ->
923
        handle_module_lookup env id parent parent_sig sub
1,006✔
924
    | `Module (parent, id) ->
2✔
925
        lookup_parent env parent
926
        |> map_error (fun e -> (e :> simple_module_lookup_error))
×
927
        >>= fun (parent_sig, sub) ->
928
        handle_module_lookup env id parent parent_sig sub
2✔
929
    | `Apply (m1, m2) -> (
11✔
930
        let func = resolve_module env m1 in
931
        let arg = resolve_module env m2 in
11✔
932
        match (func, arg) with
11✔
933
        | Ok (func_path', m), Ok (arg_path', _) -> (
9✔
934
            let m = Component.Delayed.get m in
935
            match handle_apply env func_path' arg_path' m with
9✔
936
            | Ok (p, m) -> Ok (p, Component.Delayed.put_val m)
9✔
937
            | Error e -> Error (`Parent (`Parent_expr e)))
×
938
        | Error e, _ -> Error e
2✔
939
        | _, Error e -> Error e)
×
940
    | `Identifier (i, hidden) ->
714✔
941
        of_option ~error:(`Lookup_failure i) (Env.(lookup_by_id s_module) i env)
714✔
942
        >>= fun (`Module (_, m)) ->
943
        let rp =
713✔
944
          if hidden then `Hidden (`Gpath (`Identifier i))
211✔
945
          else `Gpath (`Identifier i)
502✔
946
        in
947
        Ok (process_module_path env (Component.Delayed.get m) rp, m)
713✔
948
    | `Local (p, _) -> Error (`Local (env, p))
×
949
    | `Resolved r -> lookup_module env r >>= fun m -> Ok (r, m)
991✔
950
    | `Substituted s ->
6✔
951
        resolve_module env s |> map_error (fun e -> `Parent (`Parent_module e))
×
952
        >>= fun (p, m) -> Ok (`Substituted p, m)
6✔
953
    | `Root r -> (
179✔
954
        match Env.lookup_root_module r env with
955
        | Some (Env.Resolved (_, p, m)) ->
130✔
956
            let p =
957
              `Gpath
958
                (`Identifier (p :> Odoc_model.Paths.Identifier.Path.Module.t))
959
            in
960
            let p = process_module_path env m p in
961
            Ok (p, Component.Delayed.put_val m)
130✔
962
        | Some Env.Forward ->
15✔
963
            Error (`Parent (`Parent_sig `UnresolvedForwardPath))
964
        | None -> Error (`Lookup_failure_root r))
34✔
965
    | `Forward f ->
×
966
        resolve_module env (`Root (ModuleName.make_std f))
×
967
        |> map_error (fun e -> `Parent (`Parent_module e))
×
968
  in
969
  LookupAndResolveMemo.memoize resolve env' id
970

971
and resolve_module_type :
972
    Env.t -> Cpath.module_type -> resolve_module_type_result =
973
 fun env p ->
974
  match p with
559✔
975
  | `DotMT (parent, id) ->
118✔
976
      resolve_and_lookup_parent env parent
977
      |> map_error (fun e -> (e :> simple_module_type_lookup_error))
5✔
978
      >>= fun (parent, parent_sig, sub) ->
979
      of_option ~error:`Find_failure
113✔
980
        (handle_module_type_lookup env id parent parent_sig sub)
113✔
981
      >>= fun (p', mt) -> Ok (p', mt)
113✔
982
  | `ModuleType (parent, id) ->
×
983
      lookup_parent env parent
984
      |> map_error (fun e -> (e :> simple_module_type_lookup_error))
×
985
      >>= fun (parent_sig, sub) ->
986
      handle_module_type_lookup env id parent parent_sig sub
×
987
      |> of_option ~error:`Find_failure
×
988
  | `Identifier (i, _) ->
294✔
989
      of_option ~error:(`Lookup_failureMT i)
294✔
990
        (Env.(lookup_by_id s_module_type) i env)
294✔
991
      >>= fun (`ModuleType (_, mt)) ->
992
      let p = `Gpath (`Identifier i) in
294✔
993
      let p' = process_module_type env mt p in
994
      Ok (p', mt)
294✔
995
  | `Local (l, _) -> Error (`LocalMT (env, l))
×
996
  | `Resolved r -> lookup_module_type env r >>= fun m -> Ok (r, m)
147✔
997
  | `Substituted s ->
×
998
      resolve_module_type env s
999
      |> map_error (fun e -> `Parent (`Parent_module_type e))
×
1000
      >>= fun (p, m) -> Ok (`Substituted p, m)
×
1001

1002
and resolve_type : Env.t -> Cpath.type_ -> resolve_type_result =
1003
 fun env p ->
1004
  let result =
1,039✔
1005
    match p with
1006
    | `DotT (parent, id) ->
163✔
1007
        resolve_and_lookup_parent env parent
1008
        |> map_error (fun e -> (e :> simple_type_lookup_error))
8✔
1009
        >>= fun (parent, parent_sig, sub) ->
163✔
1010
        handle_type_lookup env id parent parent_sig >>= fun (p', t') ->
155✔
1011
        let t =
155✔
1012
          match t' with
1013
          | `CoreType _ as c -> c
×
1014
          | `FClass (name, c) -> `FClass (name, Subst.class_ sub c)
2✔
1015
          | `FClassType (name, ct) -> `FClassType (name, Subst.class_type sub ct)
4✔
1016
          | `FType (name, t) -> `FType (name, Subst.type_ sub t)
148✔
1017
          | `FType_removed (name, texpr, eq) ->
1✔
1018
              `FType_removed (name, Subst.type_expr sub texpr, eq)
1✔
1019
        in
1020
        Ok (p', t)
1021
    | `Type (parent, id) ->
×
1022
        lookup_parent env parent
1023
        |> map_error (fun e -> (e :> simple_type_lookup_error))
×
1024
        >>= fun (parent_sig, sub) ->
×
1025
        let result =
×
1026
          match Find.datatype_in_sig parent_sig id with
1027
          | Some (`FType (name, t)) ->
×
1028
              Some (`Type (parent, name), `FType (name, Subst.type_ sub t))
×
1029
          | None -> None
×
1030
        in
1031
        of_option ~error:`Find_failure result
1032
    | `Class (parent, id) ->
×
1033
        lookup_parent env parent
1034
        |> map_error (fun e -> (e :> simple_type_lookup_error))
×
1035
        >>= fun (parent_sig, sub) ->
×
1036
        let t =
×
1037
          match Find.type_in_sig parent_sig id with
1038
          | Some (`FClass (name, t)) ->
×
1039
              Some (`Class (parent, name), `FClass (name, Subst.class_ sub t))
×
1040
          | Some _ -> None
×
1041
          | None -> None
×
1042
        in
1043
        of_option ~error:`Find_failure t
1044
    | `ClassType (parent, id) ->
×
1045
        lookup_parent env parent
1046
        |> map_error (fun e -> (e :> simple_type_lookup_error))
×
1047
        >>= fun (parent_sg, sub) ->
×
1048
        handle_type_lookup env id parent parent_sg >>= fun (p', t') ->
×
1049
        let t =
×
1050
          match t' with
1051
          | `CoreType _ as c -> c
×
1052
          | `FClass (name, c) -> `FClass (name, Subst.class_ sub c)
×
1053
          | `FClassType (name, ct) -> `FClassType (name, Subst.class_type sub ct)
×
1054
          | `FType (name, t) -> `FType (name, Subst.type_ sub t)
×
1055
          | `FType_removed (name, texpr, eq) ->
×
1056
              `FType_removed (name, Subst.type_expr sub texpr, eq)
×
1057
        in
1058
        Ok (p', t)
1059
    | `Identifier (i, _) ->
235✔
1060
        let i' = `Identifier i in
1061
        lookup_type env (`Gpath i') >>= fun t -> Ok (`Gpath i', t)
234✔
1062
    | `Resolved r -> lookup_type env r >>= fun t -> Ok (r, t)
641✔
1063
    | `Local (l, _) -> Error (`LocalType (env, l))
×
1064
    | `Substituted s ->
×
1065
        resolve_type env s >>= fun (p, m) -> Ok (`Substituted p, m)
×
NEW
1066
    | `Unbox s -> resolve_type env s >>= fun (p, m) -> Ok (`Unbox p, m)
×
1067
  in
1068
  result >>= fun (p, t) ->
1069
  match t with
1,030✔
1070
  | `FType (_, { canonical = Some c; _ }) -> Ok (`CanonicalType (p, c), t)
9✔
1071
  | _ -> result
1,021✔
1072

1073
and resolve_value : Env.t -> Cpath.value -> resolve_value_result =
1074
 fun env p ->
1075
  let result =
69✔
1076
    match p with
1077
    | `DotV (parent, id) ->
69✔
1078
        resolve_module env parent
1079
        |> map_error (fun e -> `Parent (`Parent_module e))
64✔
1080
        >>= fun (p, m) ->
69✔
1081
        let m = Component.Delayed.get m in
5✔
1082
        expansion_of_module_cached env p m
5✔
1083
        |> map_error (fun e -> `Parent (`Parent_sig e))
×
1084
        >>= assert_not_functor
5✔
1085
        >>= fun sg ->
1086
        let sub = prefix_substitution (`Module p) sg in
5✔
1087
        handle_value_lookup env id (`Module p) sg
5✔
1088
        >>= fun (p', `FValue (name, c)) ->
1089
        Ok (p', `FValue (name, Subst.value sub c))
5✔
1090
    | `Value (parent, id) ->
×
1091
        lookup_parent env parent
1092
        |> map_error (fun e -> (e :> simple_value_lookup_error))
×
1093
        >>= fun (parent_sig, sub) ->
×
1094
        let result =
×
1095
          match Find.value_in_sig parent_sig id with
1096
          | Some (`FValue (name, t)) ->
×
1097
              Some (`Value (parent, name), `FValue (name, Subst.value sub t))
×
1098
          | None -> None
×
1099
        in
1100
        of_option ~error:`Find_failure result
1101
    | `Resolved r -> lookup_value env r >>= fun t -> Ok (r, t)
×
1102
    | `Identifier (i, _) ->
×
1103
        let i' = `Identifier i in
1104
        lookup_value env (`Gpath i') >>= fun t -> Ok (`Gpath i', t)
×
1105
  in
1106
  result
1107

1108
and resolve_class_type : Env.t -> Cpath.class_type -> resolve_class_type_result
1109
    =
1110
 fun env p ->
1111
  match p with
19✔
1112
  | `DotT (parent, id) ->
6✔
1113
      resolve_and_lookup_parent env parent
1114
      |> map_error (fun e -> (e :> simple_type_lookup_error))
×
1115
      >>= fun (parent, parent_sig, sub) ->
1116
      handle_class_type_lookup id parent parent_sig >>= fun (p', t') ->
6✔
1117
      let t =
6✔
1118
        match t' with
1119
        | `FClass (name, c) -> `FClass (name, Subst.class_ sub c)
×
1120
        | `FClassType (name, ct) -> `FClassType (name, Subst.class_type sub ct)
6✔
1121
        | `FType_removed (name, texpr, eq) ->
×
1122
            `FType_removed (name, Subst.type_expr sub texpr, eq)
×
1123
      in
1124
      Ok (p', t)
1125
  | `Identifier (i, _) ->
13✔
1126
      let i' = `Identifier i in
1127
      let id = `Gpath i' in
1128
      lookup_class_type env id >>= fun t -> Ok (id, t)
13✔
1129
  | `Resolved r -> lookup_class_type env r >>= fun t -> Ok (r, t)
×
1130
  | `Local (l, _) -> Error (`LocalType (env, (l :> Ident.type_)))
×
1131
  | `Substituted s ->
×
1132
      resolve_class_type env s >>= fun (p, m) -> Ok (`Substituted p, m)
×
1133
  | `Class (parent, id) ->
×
1134
      lookup_parent env parent
1135
      |> map_error (fun e -> (e :> simple_type_lookup_error))
×
1136
      >>= fun (parent_sig, sub) ->
1137
      let t =
×
1138
        match Find.type_in_sig parent_sig id with
1139
        | Some (`FClass (name, t)) ->
×
1140
            Some (`Class (parent, name), `FClass (name, Subst.class_ sub t))
×
1141
        | Some _ -> None
×
1142
        | None -> None
×
1143
      in
1144
      of_option ~error:`Find_failure t
1145
  | `ClassType (parent, id) ->
×
1146
      lookup_parent env parent
1147
      |> map_error (fun e -> (e :> simple_type_lookup_error))
×
1148
      >>= fun (parent_sg, sub) ->
1149
      handle_class_type_lookup id parent parent_sg >>= fun (p', t') ->
×
1150
      let t =
×
1151
        match t' with
1152
        | `FClass (name, c) -> `FClass (name, Subst.class_ sub c)
×
1153
        | `FClassType (name, ct) -> `FClassType (name, Subst.class_type sub ct)
×
1154
        | `FType_removed (name, texpr, eq) ->
×
1155
            `FType_removed (name, Subst.type_expr sub texpr, eq)
×
1156
      in
1157
      Ok (p', t)
1158

1159
and reresolve_module_gpath :
1160
    Env.t ->
1161
    Odoc_model.Paths.Path.Resolved.Module.t ->
1162
    Odoc_model.Paths.Path.Resolved.Module.t =
1163
 fun env path ->
1164
  match path with
822✔
1165
  | `Identifier _ -> path
822✔
1166
  | `Apply (functor_path, argument_path) ->
×
1167
      `Apply
1168
        ( reresolve_module_gpath env functor_path,
×
1169
          reresolve_module_gpath env argument_path )
×
1170
  | `Module (parent, name) -> `Module (reresolve_module_gpath env parent, name)
×
1171
  | `Alias (p1, p2) ->
×
1172
      let dest' = reresolve_module_gpath env p1 in
1173
      if
×
1174
        Odoc_model.Paths.Path.Resolved.Module.is_hidden
1175
          ~weak_canonical_test:false dest'
1176
      then
1177
        let cp2 = Component.Of_Lang.(module_path (empty ()) p2) in
×
1178
        match resolve_module env cp2 with
1179
        | Ok (`Alias (_, _, Some p3), _) ->
×
1180
            let p = reresolve_module env p3 in
1181
            Lang_of.(Path.resolved_module (empty ()) p)
×
1182
        | _ -> `Alias (dest', p2)
×
1183
      else `Alias (dest', p2)
×
1184
  | `Subst (p1, p2) ->
×
1185
      `Subst (reresolve_module_type_gpath env p1, reresolve_module_gpath env p2)
×
1186
  | `Hidden p ->
×
1187
      let p' = reresolve_module_gpath env p in
1188
      `Hidden p'
×
1189
  | `Canonical (p, `Resolved p2) ->
×
1190
      `Canonical
1191
        (reresolve_module_gpath env p, `Resolved (reresolve_module_gpath env p2))
×
1192
  | `Canonical (p, p2) ->
×
1193
      `Canonical (reresolve_module_gpath env p, handle_canonical_module env p2)
×
1194
  | `OpaqueModule m -> `OpaqueModule (reresolve_module_gpath env m)
×
1195
  | `Substituted m -> `Substituted (reresolve_module_gpath env m)
×
1196

1197
and strip_canonical :
1198
    c:Odoc_model.Paths.Path.Module.t ->
1199
    Cpath.Resolved.module_ ->
1200
    Cpath.Resolved.module_ =
1201
 fun ~c path ->
1202
  match path with
472✔
1203
  | `Canonical (x, y) when y = c -> strip_canonical ~c x
×
1204
  | `Canonical (x, y) -> `Canonical (strip_canonical ~c x, y)
×
1205
  | `Alias (x, y, z) -> `Alias (strip_canonical ~c x, y, z)
×
1206
  | `Subst (x, y) -> `Subst (x, strip_canonical ~c y)
×
1207
  | `Hidden x -> `Hidden (strip_canonical ~c x)
×
1208
  | `OpaqueModule x -> `OpaqueModule (strip_canonical ~c x)
×
1209
  | `Substituted x -> `Substituted (strip_canonical ~c x)
×
1210
  | `Gpath p -> `Gpath (strip_canonical_gpath ~c p)
406✔
1211
  | `Local _ | `Apply _ | `Module _ -> path
×
1212

1213
and strip_canonical_gpath :
1214
    c:Odoc_model.Paths.Path.Module.t ->
1215
    Odoc_model.Paths.Path.Resolved.Module.t ->
1216
    Odoc_model.Paths.Path.Resolved.Module.t =
1217
 fun ~c path ->
1218
  match path with
406✔
1219
  | `Canonical (x, y) when y = c -> strip_canonical_gpath ~c x
×
1220
  | `Canonical (x, y) -> `Canonical (strip_canonical_gpath ~c x, y)
×
1221
  | `Alias (x, y) -> `Alias (strip_canonical_gpath ~c x, y)
×
1222
  | `Subst (x, y) -> `Subst (x, strip_canonical_gpath ~c y)
×
1223
  | `Hidden x -> `Hidden (strip_canonical_gpath ~c x)
×
1224
  | `OpaqueModule x -> `OpaqueModule (strip_canonical_gpath ~c x)
×
1225
  | `Apply _ | `Module _ | `Identifier _ -> path
×
1226
  | `Substituted x -> `Substituted (strip_canonical_gpath ~c x)
×
1227

1228
and reresolve_module : Env.t -> Cpath.Resolved.module_ -> Cpath.Resolved.module_
1229
    =
1230
 fun env path ->
1231
  match path with
21,675✔
1232
  | `Local _ -> path
×
1233
  | `Gpath g -> `Gpath (reresolve_module_gpath env g)
822✔
1234
  | `Substituted x -> `Substituted (reresolve_module env x)
21✔
1235
  | `Apply (functor_path, argument_path) ->
6✔
1236
      `Apply
1237
        (reresolve_module env functor_path, reresolve_module env argument_path)
6✔
1238
  | `Module (parent, name) -> `Module (reresolve_parent env parent, name)
333✔
1239
  | `Alias (p1, p2, p3opt) ->
20,146✔
1240
      let dest' = reresolve_module env p1 in
1241
      if Cpath.is_resolved_module_hidden ~weak_canonical_test:false dest' then
20,146✔
1242
        match p3opt with
×
1243
        | Some p3 -> reresolve_module env p3
×
1244
        | None -> (
×
1245
            match resolve_module env p2 with
1246
            | Ok (`Alias (_, _, Some p3), _) -> reresolve_module env p3
×
1247
            | _ -> `Alias (dest', p2, None))
×
1248
      else `Alias (dest', p2, p3opt)
20,146✔
1249
  | `Subst (p1, p2) ->
2✔
1250
      `Subst (reresolve_module_type env p1, reresolve_module env p2)
2✔
1251
  | `Hidden p ->
28✔
1252
      let p' = reresolve_module env p in
1253
      `Hidden p'
28✔
1254
  | `Canonical (p, `Resolved p2) ->
3✔
1255
      let cp2 = Component.Of_Lang.(resolved_module_path (empty ()) p2) in
3✔
1256
      let cp2' = reresolve_module env cp2 in
1257
      let p2' = Lang_of.(Path.resolved_module (empty ()) cp2') in
3✔
1258
      `Canonical (reresolve_module env p, `Resolved p2')
3✔
1259
  | `Canonical (p, p2) -> (
314✔
1260
      match handle_canonical_module env p2 with
1261
      | `Resolved _ as r -> `Canonical (p, r)
311✔
1262
      | r -> `Canonical (reresolve_module env p, r))
3✔
1263
  | `OpaqueModule m -> `OpaqueModule (reresolve_module env m)
×
1264

1265
and handle_canonical_module_real env p2 =
1266
  (* Canonical paths are always fully qualified, but this isn't
1267
     necessarily good for rendering, as the full path would
1268
     always be written out whenever a canonical module path is
1269
     encountered.
1270

1271
     Instead the intent of this code is to try to find the shortest
1272
     path that still correctly references the canonical module.
1273

1274
     It works by starting with the fully qualified path, e.g.
1275
     A.B.C.D where A is a root module. It then makes the list
1276
     of possibilities (A).B.C.D (A.B).C.D (A.B.C).D and (A.B.C.D)
1277
     where brackets represent the part that's an identifier.
1278
     It then resolved each one in turn and calculates the
1279
     identifier of the resolved path. The shortest path that
1280
     has the same identifier as the fully-qualified path is
1281
     chosen as the canonical path.
1282

1283
     When doing this, we end up resolving each possibility.
1284
     Additionally, we need to 'reresolve' - resolve the canonical
1285
     references - while we're doing this. This is because the
1286
     parent parts of the resolved path can contain aliases and
1287
     canonical paths themselves which require resolving in order
1288
     to check the identifier is the same.
1289

1290
     However, we first need to strip off any alias/canonical paths
1291
     in the resolved module, as we want the identifier for the
1292
     module itself, not any aliased module, and the canonical path
1293
     _ought_ to be the same as the one we're _currently_ resolving
1294
     anyway, so we'd end up looping forever. Note that the alias
1295
     chain may include modules that have already been resolved and
1296
     hence have canonical constructors in their resolved paths.
1297
  *)
1298

1299
  (* [strip p] strips the top-level aliases and canonical paths from
1300
     the path [p]. Any aliases/canonicals in parents are left as is. *)
1301
  let rec strip : Cpath.Resolved.module_ -> Cpath.Resolved.module_ =
152✔
1302
   fun x ->
1303
    match x with
1,251✔
1304
    | `Canonical (x, _) -> strip x
149✔
1305
    | `Alias (_, _, Some p) -> strip (strip_canonical ~c:p2 p)
472✔
1306
    | _ -> x
630✔
1307
  in
1308

1309
  (* Resolve the path, then 'reresolve', making sure to strip off the
1310
     top-level alias and canonicals to avoid looping forever *)
1311
  let resolve env p =
1312
    (* Format.eprintf "Resolve: path=%a\n%!" Component.Fmt.module_path p; *)
1313
    resolve_module env p >>= fun (p, m) ->
484✔
1314
    (* Format.eprintf "Resolve: resolved_path=%a\n%!" Component.Fmt.resolved_module_path (strip p); *)
1315
    Ok (reresolve_module env (strip p), m)
482✔
1316
  in
1317

1318
  let lang_of cpath =
1319
    (Lang_of.(Path.resolved_module (empty ()) cpath)
308✔
1320
      :> Odoc_model.Paths.Path.Resolved.t)
1321
  in
1322

1323
  let cp2 = Component.Of_Lang.(module_path (empty ()) p2) in
152✔
1324
  match canonical_helper env resolve lang_of c_mod_poss cp2 with
1325
  | None -> p2
2✔
1326
  | Some (rp, m) ->
150✔
1327
      let m = Component.Delayed.get m in
1328
      (* Need to check if the module we're going to link to has been expanded.
1329
         ModuleTypes are always expanded if possible, but Aliases are only expanded
1330
         if they're an alias to a hidden module or if they're self canonical.
1331

1332
         Checking if a module is self canonical is a bit tricky, since this function
1333
         is itself part of the process of resolving any canonical reference. Hence
1334
         what we do here is to look through alias chains looking for one that's marked
1335
         with the same _unresolved_ canonical path that we're currently trying to resolve.
1336

1337
         This is particularly important because some modules don't know they're canonical!
1338
         For example the module Caml in base, which is marked as the canonical path for
1339
         all references to the standard library in the file [import0.ml], but is itself just
1340
         defined by including [Stdlib].
1341

1342
         If a module doesn't know it's canonical, it will fail the self-canonical check, and
1343
         therefore not necessarily be expanded. If this happens, we call [process_module_path]
1344
         to stick the [`Alias] constructor back on so we'll link to the correct place. *)
1345
      let expanded =
150✔
1346
        match m.type_ with
1347
        | Component.Module.Alias (_, Some _) -> true
×
1348
        | Alias (p, None) -> (
148✔
1349
            (* Format.eprintf "Going to resolve %a\n%!" Component.Fmt.module_path p; *)
1350
            match resolve_module env p with
1351
            | Ok (rp, _) ->
148✔
1352
                (* we're an alias - check to see if we're marked as the canonical path.
1353
                   If not, check for an alias chain with us as canonical in it... *)
1354
                let rec check m =
1355
                  match m.Component.Module.canonical with
228✔
1356
                  | Some p ->
113✔
1357
                      p = p2
1358
                      (* The canonical path is the same one we're trying to resolve *)
1359
                  | None -> (
115✔
1360
                      match m.type_ with
1361
                      | Component.Module.Alias (p, _) -> (
114✔
1362
                          (* Format.eprintf "Going to resolve %a\n%!" Component.Fmt.module_path p; *)
1363
                          match resolve_module env p with
1364
                          | Ok (rp, _) -> (
114✔
1365
                              match lookup_module env rp with
1366
                              | Error _ -> false
×
1367
                              | Ok m ->
114✔
1368
                                  let m = Component.Delayed.get m in
1369
                                  check m)
114✔
1370
                          | _ -> false)
×
1371
                      | _ -> false)
1✔
1372
                in
1373
                let self_canonical () = check m in
114✔
1374
                let hidden =
1375
                  Cpath.is_resolved_module_hidden ~weak_canonical_test:true
1376
                    (strip rp)
148✔
1377
                in
1378
                hidden || self_canonical ()
34✔
1379
            | _ -> false)
×
1380
        | ModuleType _ -> true
2✔
1381
      in
1382
      let cpath = if expanded then rp else process_module_path env m rp in
1✔
1383

1384
      (* Format.eprintf "result: %a\n%!" Component.Fmt.resolved_module_path cpath; *)
1385
      Lang_of.(Path.module_ (empty ()) (`Resolved cpath))
150✔
1386

1387
and handle_canonical_module env p2 =
1388
  HandleCanonicalModuleMemo.memoize handle_canonical_module_real env p2
314✔
1389

1390
and handle_canonical_module_type env p2 =
1391
  let cp2 = Component.Of_Lang.(module_type_path (empty ()) p2) in
4✔
1392
  let rec strip : Cpath.Resolved.module_type -> Cpath.Resolved.module_type =
1393
    function
1394
    | `AliasModuleType (_, p) -> strip p
12✔
1395
    | `CanonicalModuleType (p, _) -> strip p
3✔
1396
    | p -> p
12✔
1397
  in
1398
  let resolve env p =
1399
    resolve_module_type env p >>= fun (p, m) ->
12✔
1400
    (* Note, we reresolve here in case any parent module has a canonical
1401
       constructor to deal with *)
1402
    Ok (reresolve_module_type env (strip p), m)
12✔
1403
  in
1404
  let lang_of cpath =
1405
    (Lang_of.(Path.resolved_module_type (empty ()) cpath)
8✔
1406
      :> Odoc_model.Paths.Path.Resolved.t)
1407
  in
1408
  match canonical_helper env resolve lang_of c_modty_poss cp2 with
1409
  | None -> p2
×
1410
  | Some (rp, _) -> `Resolved Lang_of.(Path.resolved_module_type (empty ()) rp)
4✔
1411

1412
and handle_canonical_type env p2 =
1413
  let cp2 = Component.Of_Lang.(type_path (empty ()) p2) in
6✔
1414
  let lang_of cpath =
1415
    (Lang_of.(Path.resolved_type (empty ()) cpath)
13✔
1416
      :> Odoc_model.Paths.Path.Resolved.t)
1417
  in
1418

1419
  let rec strip : Cpath.Resolved.type_ -> Cpath.Resolved.type_ =
1420
   fun x -> match x with `CanonicalType (x, _) -> strip x | _ -> x
3✔
1421
  in
1422

1423
  let resolve env p =
1424
    match resolve_type env p with
26✔
1425
    | Ok (_, `FType_removed _) -> Error `Find_failure
×
1426
    | Ok (x, y) ->
26✔
1427
        (* See comment in handle_canonical_module_type for why we're reresolving here *)
1428
        let r = reresolve_type env (strip x) in
26✔
1429
        Ok (r, y)
26✔
1430
    | Error y -> Error y
×
1431
  in
1432
  match canonical_helper env resolve lang_of c_ty_poss cp2 with
1433
  | None -> p2
×
1434
  | Some (rp, _) -> `Resolved Lang_of.(Path.resolved_type (empty ()) rp)
6✔
1435

1436
and reresolve_module_type_gpath :
1437
    Env.t ->
1438
    Odoc_model.Paths.Path.Resolved.ModuleType.t ->
1439
    Odoc_model.Paths.Path.Resolved.ModuleType.t =
1440
 fun env path ->
1441
  match path with
66✔
1442
  | `Identifier _ -> path
66✔
1443
  | `ModuleType (parent, name) ->
×
1444
      `ModuleType (reresolve_module_gpath env parent, name)
×
1445
  | `CanonicalModuleType (p1, (`Resolved _ as p2)) ->
×
1446
      `CanonicalModuleType (reresolve_module_type_gpath env p1, p2)
×
1447
  | `CanonicalModuleType (p1, p2) ->
×
1448
      `CanonicalModuleType
1449
        (reresolve_module_type_gpath env p1, handle_canonical_module_type env p2)
×
1450
  | `SubstT (p1, p2) ->
×
1451
      `SubstT
1452
        (reresolve_module_type_gpath env p1, reresolve_module_type_gpath env p2)
×
1453
  | `AliasModuleType (p1, p2) ->
×
1454
      `AliasModuleType
1455
        (reresolve_module_type_gpath env p1, reresolve_module_type_gpath env p2)
×
1456
  | `OpaqueModuleType m -> `OpaqueModuleType (reresolve_module_type_gpath env m)
×
1457
  | `SubstitutedMT m -> `SubstitutedMT (reresolve_module_type_gpath env m)
×
1458

1459
and reresolve_module_type :
1460
    Env.t -> Cpath.Resolved.module_type -> Cpath.Resolved.module_type =
1461
 fun env path ->
1462
  match path with
115✔
1463
  | `Local _ -> path
×
1464
  | `Gpath g -> `Gpath (reresolve_module_type_gpath env g)
66✔
1465
  | `Substituted x -> `Substituted (reresolve_module_type env x)
×
1466
  | `ModuleType (parent, name) -> `ModuleType (reresolve_parent env parent, name)
31✔
1467
  | `CanonicalModuleType (p1, (`Resolved _ as p2')) ->
×
1468
      `CanonicalModuleType (reresolve_module_type env p1, p2')
×
1469
  | `CanonicalModuleType (p1, p2) ->
4✔
1470
      `CanonicalModuleType
1471
        (reresolve_module_type env p1, handle_canonical_module_type env p2)
4✔
1472
  | `SubstT (p1, p2) ->
5✔
1473
      `SubstT (reresolve_module_type env p1, reresolve_module_type env p2)
5✔
1474
  | `AliasModuleType (p1, p2) ->
9✔
1475
      `AliasModuleType
1476
        (reresolve_module_type env p1, reresolve_module_type env p2)
9✔
1477
  | `OpaqueModuleType m -> `OpaqueModuleType (reresolve_module_type env m)
×
1478

1479
and reresolve_type : Env.t -> Cpath.Resolved.type_ -> Cpath.Resolved.type_ =
1480
 fun env path ->
1481
  let result =
98✔
1482
    match path with
1483
    | `Gpath _ | `Local _ | `CoreType _ -> path
×
1484
    | `Substituted s -> `Substituted (reresolve_type env s)
×
NEW
1485
    | `Unbox t -> `Unbox (reresolve_type env t)
×
1486
    | `CanonicalType (p1, p2) ->
6✔
1487
        `CanonicalType (reresolve_type env p1, handle_canonical_type env p2)
6✔
1488
    | `Type (p, n) -> `Type (reresolve_parent env p, n)
67✔
1489
    | `Class (p, n) -> `Class (reresolve_parent env p, n)
1✔
1490
    | `ClassType (p, n) -> `ClassType (reresolve_parent env p, n)
×
1491
  in
1492
  result
1493

1494
and reresolve_value : Env.t -> Cpath.Resolved.value -> Cpath.Resolved.value =
1495
 fun env p ->
1496
  match p with
4✔
1497
  | `Value (p, n) -> `Value (reresolve_parent env p, n)
4✔
1498
  | `Gpath _ -> p
×
1499

1500
and reresolve_class_type :
1501
    Env.t -> Cpath.Resolved.class_type -> Cpath.Resolved.class_type =
1502
 fun env path ->
1503
  let result =
×
1504
    match path with
1505
    | `Gpath _ | `Local _ -> path
×
1506
    | `Substituted s -> `Substituted (reresolve_class_type env s)
×
1507
    | `Class (p, n) -> `Class (reresolve_parent env p, n)
×
1508
    | `ClassType (p, n) -> `ClassType (reresolve_parent env p, n)
×
1509
  in
1510
  result
1511

1512
and reresolve_parent : Env.t -> Cpath.Resolved.parent -> Cpath.Resolved.parent =
1513
 fun env path ->
1514
  match path with
501✔
1515
  | `Module m -> `Module (reresolve_module env m)
490✔
1516
  | `ModuleType mty -> `ModuleType (reresolve_module_type env mty)
11✔
1517
  | `FragmentRoot -> path
×
1518

1519
(* *)
1520
and module_type_expr_of_module_decl :
1521
    Env.t ->
1522
    Component.Module.decl ->
1523
    (Component.ModuleType.expr, simple_module_type_expr_of_module_error) result
1524
    =
1525
 fun env decl ->
1526
  match decl with
20✔
1527
  | Component.Module.Alias (`Resolved r, _) ->
×
1528
      lookup_module env r |> map_error (fun e -> `Parent (`Parent_module e))
×
1529
      >>= fun m ->
1530
      let m = Component.Delayed.get m in
×
1531
      module_type_expr_of_module_decl env m.type_
×
1532
  | Component.Module.Alias (path, _) -> (
×
1533
      match resolve_module env path with
1534
      | Ok (_, m) ->
×
1535
          let m = Component.Delayed.get m in
1536
          module_type_expr_of_module env m
×
1537
      | Error _ when Cpath.is_module_forward path ->
×
1538
          Error `UnresolvedForwardPath
×
1539
      | Error e -> Error (`UnresolvedPath (`Module (path, e))))
×
1540
  | Component.Module.ModuleType expr -> Ok expr
20✔
1541

1542
and module_type_expr_of_module :
1543
    Env.t ->
1544
    Component.Module.t ->
1545
    (Component.ModuleType.expr, simple_module_type_expr_of_module_error) result
1546
    =
1547
 fun env m -> module_type_expr_of_module_decl env m.type_
20✔
1548

1549
and expansion_of_module_path :
1550
    Env.t ->
1551
    strengthen:bool ->
1552
    Cpath.module_ ->
1553
    (expansion, expansion_of_module_error) result =
1554
 fun env ~strengthen path ->
1555
  match resolve_module env path with
2,140✔
1556
  | Ok (p', m) -> (
2,131✔
1557
      let m = Component.Delayed.get m in
1558
      (* p' is the path to the aliased module *)
1559
      let strengthen =
2,131✔
1560
        strengthen
1561
        && not (Cpath.is_resolved_module_hidden ~weak_canonical_test:true p')
1,845✔
1562
      in
1563
      expansion_of_module_cached env p' m >>= function
2,131✔
1564
      | Signature sg ->
2,128✔
1565
          let sg =
1566
            if strengthen then Strengthen.signature (`Resolved p') sg else sg
352✔
1567
          in
1568
          Ok (Signature sg)
1569
      | Functor _ as f -> Ok f)
2✔
1570
  | Error _ when Cpath.is_module_forward path -> Error `UnresolvedForwardPath
×
1571
  | Error e -> Error (`UnresolvedPath (`Module (path, e)))
9✔
1572

1573
and handle_signature_with_subs :
1574
    Env.t ->
1575
    Component.Signature.t ->
1576
    Component.ModuleType.substitution list ->
1577
    (Component.Signature.t, expansion_of_module_error) result =
1578
 fun env sg subs ->
1579
  let open Odoc_utils.ResultMonad in
68✔
1580
  List.fold_left
1581
    (fun sg_opt sub -> sg_opt >>= fun sg -> fragmap env sub sg)
74✔
1582
    (Ok sg) subs
1583

1584
and assert_not_functor : type err.
1585
    expansion -> (Component.Signature.t, err) result = function
1586
  | Signature sg -> Ok sg
1,145✔
1587
  | _ -> assert false
1588

1589
and unresolve_subs subs =
1590
  List.map
68✔
1591
    (function
1592
      | Component.ModuleType.ModuleEq (`Resolved f, m) ->
×
1593
          Component.ModuleType.ModuleEq (Cfrag.unresolve_module f, m)
×
1594
      | ModuleSubst (`Resolved f, m) -> ModuleSubst (Cfrag.unresolve_module f, m)
×
1595
      | TypeEq (`Resolved f, t) -> TypeEq (Cfrag.unresolve_type f, t)
×
1596
      | TypeSubst (`Resolved f, t) -> TypeSubst (Cfrag.unresolve_type f, t)
×
1597
      | x -> x)
74✔
1598
    subs
1599

1600
and signature_of_module_type_of :
1601
    Env.t ->
1602
    Component.ModuleType.type_of_desc ->
1603
    original_path:Cpath.module_ ->
1604
    (expansion, expansion_of_module_error) result =
1605
 fun env desc ~original_path:_ ->
1606
  let p, strengthen =
165✔
1607
    match desc with ModPath p -> (p, false) | StructInclude p -> (p, true)
40✔
1608
  in
1609
  (*
1610
  match Cpath.original_path_cpath original_path with
1611
  | None -> Error (`UnresolvedOriginalPath (original_path, `Find_failure))
1612
  | Some cp ->
1613
  expansion_of_module_path env ~strengthen p >>= fun exp ->
1614
  match expansion_of_module_path env ~strengthen:false cp with
1615
  | Ok _orig_exp -> Ok exp
1616
    | Error _lookup_error ->
1617
    Ok (exp)
1618
  *)
1619
  expansion_of_module_path env ~strengthen p
1620

1621
and signature_of_u_module_type_expr :
1622
    Env.t ->
1623
    Component.ModuleType.U.expr ->
1624
    (Component.Signature.t, expansion_of_module_error) result =
1625
 fun env m ->
1626
  match m with
373✔
1627
  | Component.ModuleType.U.Path p -> (
171✔
1628
      match resolve_module_type env p with
1629
      | Ok (_, mt) -> expansion_of_module_type env mt >>= assert_not_functor
171✔
1630
      | Error e -> Error (`UnresolvedPath (`ModuleType (p, e))))
×
1631
  | Signature s -> Ok s
22✔
1632
  | With (subs, s) ->
15✔
1633
      signature_of_u_module_type_expr env s >>= fun sg ->
15✔
1634
      let subs = unresolve_subs subs in
15✔
1635
      handle_signature_with_subs env sg subs
15✔
1636
  | TypeOf (desc, original_path) ->
165✔
1637
      signature_of_module_type_of env desc ~original_path >>= assert_not_functor
165✔
1638
  | Strengthen (expr, path, _aliasable) ->
×
1639
      signature_of_u_module_type_expr env expr >>= fun sg ->
×
1640
      Ok (Strengthen.signature path sg)
×
1641

1642
and expansion_of_simple_expansion :
1643
    Component.ModuleType.simple_expansion -> expansion =
1644
  let rec helper :
1645
      Component.ModuleType.simple_expansion -> Component.ModuleType.expr =
1646
    function
1647
    | Signature sg -> Signature sg
×
1648
    | Functor (arg, e) -> Functor (arg, helper e)
×
1649
  in
1650
  function
1651
  | Signature sg -> Signature sg
20✔
1652
  | Functor (arg, e) -> Functor (arg, helper e)
×
1653

1654
and expansion_of_module_type_expr :
1655
    Env.t ->
1656
    Component.ModuleType.expr ->
1657
    (expansion, expansion_of_module_error) result =
1658
 fun env m ->
1659
  match m with
1,286✔
1660
  | Component.ModuleType.Path { p_expansion = Some e; _ } ->
15✔
1661
      Ok (expansion_of_simple_expansion e)
15✔
1662
  | Component.ModuleType.Path { p_path; _ } -> (
121✔
1663
      match resolve_module_type env p_path with
1664
      | Ok (_, mt) -> expansion_of_module_type env mt
120✔
1665
      | Error e -> Error (`UnresolvedPath (`ModuleType (p_path, e))))
1✔
1666
  | Component.ModuleType.Signature s -> Ok (Signature s)
1,045✔
1667
  | Component.ModuleType.With { w_expansion = Some e; _ } ->
5✔
1668
      Ok (expansion_of_simple_expansion e)
5✔
1669
  | Component.ModuleType.With { w_substitutions; w_expr; _ } ->
53✔
1670
      signature_of_u_module_type_expr env w_expr >>= fun sg ->
53✔
1671
      let subs = unresolve_subs w_substitutions in
53✔
1672
      handle_signature_with_subs env sg subs >>= fun sg -> Ok (Signature sg)
53✔
1673
  | Component.ModuleType.Functor (arg, expr) -> Ok (Functor (arg, expr))
7✔
1674
  | Component.ModuleType.TypeOf { t_expansion = Some (Signature sg); _ } ->
16✔
1675
      Ok (Signature sg)
1676
  | Component.ModuleType.TypeOf { t_desc; _ } ->
24✔
1677
      let p, strengthen =
1678
        match t_desc with
1679
        | ModPath p -> (p, false)
20✔
1680
        | StructInclude p -> (p, true)
4✔
1681
      in
1682
      expansion_of_module_path env ~strengthen p
1683
  | Component.ModuleType.Strengthen { s_expr; s_path; _ } ->
×
1684
      signature_of_u_module_type_expr env s_expr >>= fun sg ->
×
1685
      let sg = Strengthen.signature s_path sg in
×
1686
      Ok (Signature sg)
×
1687

1688
and expansion_of_module_type :
1689
    Env.t ->
1690
    Component.ModuleType.t ->
1691
    (expansion, expansion_of_module_error) result =
1692
 fun env m ->
1693
  match m.expr with
498✔
1694
  | None -> Error `OpaqueModule
26✔
1695
  | Some expr -> expansion_of_module_type_expr env expr
472✔
1696

1697
and expansion_of_module_decl :
1698
    Env.t ->
1699
    Component.Module.decl ->
1700
    (expansion, expansion_of_module_error) result =
1701
 fun env decl ->
1702
  match decl with
2,478✔
1703
  (* | Component.Module.Alias (_, Some e) -> Ok (expansion_of_simple_expansion e) *)
1704
  | Component.Module.Alias (p, _) ->
1,805✔
1705
      expansion_of_module_path env ~strengthen:true p
1706
  | Component.Module.ModuleType expr -> expansion_of_module_type_expr env expr
673✔
1707

1708
and expansion_of_module :
1709
    Env.t -> Component.Module.t -> (expansion, expansion_of_module_error) result
1710
    =
1711
 fun env m ->
1712
  expansion_of_module_decl env m.type_ >>= function
2,478✔
1713
  | Signature sg ->
2,469✔
1714
      let sg =
1715
        (* Override the signature's documentation when the module also has
1716
           a comment attached. *)
1717
        match m.doc.elements with
1718
        | [] -> sg
2,446✔
1719
        | _ -> { sg with doc = m.doc }
23✔
1720
      in
1721
      Ok (Signature sg)
1722
  | Functor _ as f -> Ok f
4✔
1723

1724
and expansion_of_module_cached :
1725
    Env.t ->
1726
    Cpath.Resolved.module_ ->
1727
    Component.Module.t ->
1728
    (expansion, expansion_of_module_error) result =
1729
 fun env' path m ->
1730
  let id = path in
2,729✔
1731
  let run env _id = expansion_of_module env m in
1,555✔
1732
  ExpansionOfModuleMemo.memoize run env' id
1733

1734
and _ascribe _env ~expansion ~original_expansion =
1735
  match (expansion, original_expansion) with
×
1736
  | Functor _, _ -> expansion
×
1737
  | Signature sg, Signature sg' ->
×
1738
      let items =
1739
        List.fold_right
1740
          (fun item acc ->
1741
            match item with
×
1742
            | Component.Signature.Module (id, _r, _m) ->
×
1743
                if Find.module_in_sig sg' (Ident.Name.typed_module id) = None
×
1744
                then acc
×
1745
                else item :: acc
×
1746
            | Component.Signature.ModuleType (id, _m) ->
×
1747
                if
1748
                  Find.module_type_in_sig sg' (Ident.Name.typed_module_type id)
×
1749
                  = None
1750
                then acc
×
1751
                else item :: acc
×
1752
            | Component.Signature.Type (id, _r, _t) ->
×
1753
                if Find.type_in_sig sg' (Ident.Name.typed_type id) = None then
×
1754
                  acc
×
1755
                else item :: acc
×
1756
            | Component.Signature.Value (id, _v) ->
×
1757
                if Find.value_in_sig sg' (Ident.Name.typed_value id) = None then
×
1758
                  acc
×
1759
                else item :: acc
×
1760
            | _ -> item :: acc)
×
1761
          sg.items []
1762
      in
1763
      Signature { sg with items }
×
1764
  | _ -> expansion
×
1765

1766
and umty_of_mty : Component.ModuleType.expr -> Component.ModuleType.U.expr =
1767
  function
1768
  | Signature sg -> Signature sg
15✔
1769
  | Path { p_path; _ } -> Path p_path
3✔
1770
  | TypeOf { t_desc; t_original_path; _ } -> TypeOf (t_desc, t_original_path)
×
1771
  | With { w_substitutions; w_expr; _ } -> With (w_substitutions, w_expr)
×
1772
  | Functor _ -> assert false
1773
  | Strengthen { s_expr; s_path; s_aliasable; _ } ->
×
1774
      Strengthen (s_expr, s_path, s_aliasable)
1775

1776
and fragmap :
1777
    Env.t ->
1778
    Component.ModuleType.substitution ->
1779
    Component.Signature.t ->
1780
    (Component.Signature.t, expansion_of_module_error) result =
1781
 fun env sub sg ->
1782
  (* Used when we haven't finished the substitution. For example, if the
1783
     substitution is `M.t = u`, this function is used to map the declaration
1784
     of `M` to be `M : ... with type t = u` *)
1785
  let map_module_decl decl subst =
281✔
1786
    let open Component.Module in
24✔
1787
    match decl with
1788
    | Alias (path, _) ->
6✔
1789
        Ok
1790
          (ModuleType
1791
             (With
1792
                {
1793
                  w_substitutions = [ subst ];
1794
                  w_expansion = None;
1795
                  w_expr =
1796
                    TypeOf (StructInclude path, Cpath.unresolve_module_path path);
6✔
1797
                }))
1798
    | ModuleType mty' ->
18✔
1799
        Ok
1800
          (ModuleType
1801
             (With
1802
                {
1803
                  w_substitutions = [ subst ];
1804
                  w_expansion = None;
1805
                  w_expr = umty_of_mty mty';
18✔
1806
                }))
1807
  in
1808
  let map_include_decl decl subst =
1809
    let open Component.Include in
6✔
1810
    match decl with
1811
    | Alias p ->
×
1812
        expansion_of_module_path env ~strengthen:true p >>= assert_not_functor
×
1813
        >>= fun sg ->
1814
        fragmap env subst sg >>= fun sg -> Ok (ModuleType (Signature sg))
×
1815
    | ModuleType mty' -> Ok (ModuleType (With ([ subst ], mty')))
6✔
1816
  in
1817
  let map_module m new_subst =
1818
    let open Component.Module in
24✔
1819
    map_module_decl m.type_ new_subst >>= fun type_ ->
24✔
1820
    Ok (Left { m with type_ })
24✔
1821
  in
1822
  let map_removed = function
1823
    | `RModule (id, p) ->
17✔
1824
        Component.Signature.RModule (Ident.Name.typed_module id, `Resolved p)
17✔
1825
    | `RType (id, x, y) -> RType (Ident.Name.typed_type id, x, y)
48✔
1826
    | `RModuleType (id, x) -> RModuleType (Ident.Name.typed_module_type id, x)
8✔
1827
  in
1828

1829
  let rec map_signature map items =
1830
    List.fold_right
298✔
1831
      (fun item acc ->
1832
        acc >>= fun (items, handled, subbed_modules, removed) ->
641✔
1833
        match (item, map) with
641✔
1834
        | Component.Signature.Type (id, r, t), { type_ = Some (id', fn); _ }
157✔
1835
          when Ident.Name.type_ id = id' -> (
97✔
1836
            fn (Component.Delayed.get t) >>= function
97✔
1837
            | Left x ->
49✔
1838
                Ok
1839
                  ( Component.Signature.Type
1840
                      (id, r, Component.Delayed.put (fun () -> x))
20✔
1841
                    :: items,
1842
                    true,
1843
                    subbed_modules,
1844
                    removed )
1845
            | Right (texpr, eq) ->
48✔
1846
                Ok
1847
                  ( items,
1848
                    true,
1849
                    subbed_modules,
1850
                    `RType (id, texpr, eq) :: removed ))
1851
        | Component.Signature.Module (id, r, m), { module_ = Some (id', fn); _ }
204✔
1852
          when Ident.Name.module_ id = id' -> (
166✔
1853
            fn (Component.Delayed.get m) >>= function
166✔
1854
            | Left x ->
149✔
1855
                Ok
1856
                  ( Component.Signature.Module
1857
                      (id, r, Component.Delayed.put (fun () -> x))
31✔
1858
                    :: items,
1859
                    true,
1860
                    id :: subbed_modules,
1861
                    removed )
1862
            | Right y ->
17✔
1863
                Ok (items, true, subbed_modules, `RModule (id, y) :: removed))
1864
        | Component.Signature.Include ({ expansion_; _ } as i), _ ->
17✔
1865
            map_signature map expansion_.items
17✔
1866
            >>= fun (items', handled', subbed_modules', removed') ->
1867
            let component =
17✔
1868
              if handled' then
1869
                map_include_decl i.decl sub >>= fun decl ->
6✔
1870
                let expansion_ =
6✔
1871
                  Component.Signature.
1872
                    {
1873
                      expansion_ with
1874
                      items = items';
1875
                      removed = List.map map_removed removed';
6✔
1876
                      compiled = false;
1877
                    }
1878
                in
1879
                Ok
1880
                  (Component.Signature.Include
1881
                     { i with decl; expansion_; strengthened = None })
1882
              else Ok item
11✔
1883
            in
1884
            component >>= fun c ->
1885
            Ok
17✔
1886
              ( c :: items,
1887
                handled' || handled,
×
1888
                subbed_modules' @ subbed_modules,
1889
                removed' @ removed )
1890
        | ( Component.Signature.ModuleType (id, mt),
18✔
1891
            { module_type = Some (id', fn); _ } )
1892
          when Ident.Name.module_type id = id' -> (
18✔
1893
            fn (Component.Delayed.get mt) >>= function
18✔
1894
            | Left x ->
10✔
1895
                Ok
1896
                  ( Component.Signature.ModuleType
1897
                      (id, Component.Delayed.put (fun () -> x))
4✔
1898
                    :: items,
1899
                    true,
1900
                    subbed_modules,
1901
                    removed )
1902
            | Right y ->
8✔
1903
                Ok (items, true, subbed_modules, `RModuleType (id, y) :: removed)
1904
            )
1905
        | x, _ -> Ok (x :: items, handled, subbed_modules, removed))
343✔
1906
      items
1907
      (Ok ([], false, [], []))
1908
  in
1909
  let handle_intermediate name new_subst =
1910
    let modmaps = Some (name, fun m -> map_module m new_subst) in
24✔
1911
    map_signature { id_map with module_ = modmaps } sg.items
1912
  in
1913
  let new_sg =
1914
    match sub with
1915
    | ModuleEq (frag, type_) -> (
125✔
1916
        match Cfrag.module_split frag with
1917
        | name, Some frag' ->
×
1918
            let new_subst = Component.ModuleType.ModuleEq (frag', type_) in
1919
            handle_intermediate name new_subst
×
1920
        | name, None ->
125✔
1921
            let mapfn m =
1922
              let type_ =
125✔
1923
                let open Component.Module in
1924
                match type_ with
1925
                | Alias (`Resolved p, _) ->
105✔
1926
                    let new_p = `Substituted p in
1927
                    Alias (`Resolved new_p, None)
1928
                | Alias _ | ModuleType _ -> type_
×
1929
              in
1930
              Ok (Left { m with Component.Module.type_ })
1931
            in
1932
            map_signature { id_map with module_ = Some (name, mapfn) } sg.items)
125✔
1933
    | ModuleSubst (frag, p) -> (
17✔
1934
        match Cfrag.module_split frag with
1935
        | name, Some frag' ->
×
1936
            let new_subst = Component.ModuleType.ModuleSubst (frag', p) in
1937
            handle_intermediate name new_subst
×
1938
        | name, None ->
17✔
1939
            let mapfn _ =
1940
              match resolve_module env p with
17✔
1941
              | Ok (`Canonical (p, _), _) | Ok (p, _) -> Ok (Right p)
×
1942
              | Error e -> Error (`UnresolvedPath (`Module (p, e)))
×
1943
            in
1944
            map_signature { id_map with module_ = Some (name, mapfn) } sg.items)
17✔
1945
    | ModuleTypeEq (frag, mtye) -> (
13✔
1946
        match Cfrag.module_type_split frag with
1947
        | name, Some frag' ->
3✔
1948
            let new_subst = Component.ModuleType.ModuleTypeEq (frag', mtye) in
1949
            handle_intermediate name new_subst
3✔
1950
        | name, None ->
10✔
1951
            let mapfn t =
1952
              Ok (Left { t with Component.ModuleType.expr = Some mtye })
10✔
1953
            in
1954
            map_signature
10✔
1955
              { id_map with module_type = Some (name, mapfn) }
1956
              sg.items)
1957
    | ModuleTypeSubst (frag, mtye) -> (
11✔
1958
        match Cfrag.module_type_split frag with
1959
        | name, Some frag' ->
3✔
1960
            let new_subst =
1961
              Component.ModuleType.ModuleTypeSubst (frag', mtye)
1962
            in
1963
            handle_intermediate name new_subst
3✔
1964
        | name, None ->
8✔
1965
            let mapfn _t = Ok (Right mtye) in
8✔
1966
            map_signature
8✔
1967
              { id_map with module_type = Some (name, mapfn) }
1968
              sg.items)
1969
    | TypeEq (frag, equation) -> (
64✔
1970
        match Cfrag.type_split frag with
1971
        | name, Some frag' ->
15✔
1972
            let new_subst = Component.ModuleType.TypeEq (frag', equation) in
1973
            handle_intermediate name new_subst
15✔
1974
        | name, None ->
49✔
1975
            let mapfn t = Ok (Left { t with Component.TypeDecl.equation }) in
49✔
1976
            map_signature { id_map with type_ = Some (name, mapfn) } sg.items)
49✔
1977
    | TypeSubst
51✔
1978
        ( frag,
1979
          ({ Component.TypeDecl.Equation.manifest = Some x; _ } as equation) )
1980
      -> (
1981
        match Cfrag.type_split frag with
1982
        | name, Some frag' ->
3✔
1983
            let new_subst = Component.ModuleType.TypeSubst (frag', equation) in
1984
            handle_intermediate name new_subst
3✔
1985
        | name, None ->
48✔
1986
            let mapfn _t = Ok (Right (x, equation)) in
48✔
1987
            map_signature { id_map with type_ = Some (name, mapfn) } sg.items)
48✔
1988
    | TypeSubst (_, { Component.TypeDecl.Equation.manifest = None; _ }) ->
×
1989
        failwith "Unhandled condition: TypeSubst with no manifest"
1990
  in
1991
  new_sg >>= fun (items, _handled, subbed_modules, removed) ->
1992
  let sub_of_removed removed sub =
281✔
1993
    match removed with
73✔
1994
    | `RModule (id, p) ->
17✔
1995
        Subst.add_module (id :> Ident.module_) (`Resolved p) p sub
1996
    | `RType (id, r_texpr, r_eq) ->
48✔
1997
        Subst.add_type_replacement (id :> Ident.type_) r_texpr r_eq sub
1998
    | `RModuleType (id, e) ->
8✔
1999
        Subst.add_module_type_replacement (id :> Ident.module_type) e sub
2000
  in
2001

2002
  let sub = List.fold_right sub_of_removed removed Subst.identity in
2003

2004
  (* Invalidate resolved paths containing substituted idents - See the `With11`
2005
     test for an example of why this is necessary *)
2006
  let sub_of_substituted x sub =
281✔
2007
    let x = (x :> Ident.module_) in
149✔
2008
    Subst.add_module_substitution x sub |> Subst.path_invalidate_module x
149✔
2009
  in
2010

2011
  let substituted_sub =
2012
    List.fold_right sub_of_substituted subbed_modules Subst.identity
2013
  in
2014

2015
  (* Need to call `apply_sig_map_items` directly as we're substituting for an item
2016
     that's declared within the signature *)
2017
  let items = Subst.apply_sig_map_items substituted_sub items in
281✔
2018

2019
  let res =
281✔
2020
    Subst.signature sub
2021
      {
2022
        Component.Signature.items;
2023
        removed = List.map map_removed removed @ sg.removed;
281✔
2024
        compiled = false;
2025
        doc = sg.doc;
2026
      }
2027
  in
2028
  Ok res
281✔
2029

2030
and find_external_module_path :
2031
    Cpath.Resolved.module_ -> Cpath.Resolved.module_ option =
2032
 fun p ->
2033
  let open Odoc_utils.OptionMonad in
14✔
2034
  match p with
2035
  | `Subst (x, y) ->
1✔
2036
      find_external_module_type_path x >>= fun x ->
1✔
2037
      find_external_module_path y >>= fun y -> Some (`Subst (x, y))
1✔
2038
  | `Module (p, n) ->
2✔
2039
      find_external_parent_path p >>= fun p -> Some (`Module (p, n))
2✔
2040
  | `Local x -> Some (`Local x)
×
2041
  | `Substituted x ->
5✔
2042
      find_external_module_path x >>= fun x -> Some (`Substituted x)
4✔
2043
  | `Canonical (x, y) ->
×
2044
      find_external_module_path x >>= fun x -> Some (`Canonical (x, y))
×
2045
  | `Hidden x -> find_external_module_path x >>= fun x -> Some (`Hidden x)
×
2046
  | `Alias _ -> None
1✔
2047
  | `Apply (x, y) ->
×
2048
      find_external_module_path x >>= fun x ->
×
2049
      find_external_module_path y >>= fun y -> Some (`Apply (x, y))
×
2050
  | `Gpath x -> Some (`Gpath x)
5✔
2051
  | `OpaqueModule m ->
×
2052
      find_external_module_path m >>= fun x -> Some (`OpaqueModule x)
×
2053

2054
and find_external_module_type_path :
2055
    Cpath.Resolved.module_type -> Cpath.Resolved.module_type option =
2056
 fun p ->
2057
  let open Odoc_utils.OptionMonad in
6✔
2058
  match p with
2059
  | `ModuleType (p, name) ->
4✔
2060
      find_external_parent_path p >>= fun p -> Some (`ModuleType (p, name))
3✔
2061
  | `Local _ -> Some p
×
2062
  | `SubstT (x, y) ->
1✔
2063
      find_external_module_type_path x >>= fun x ->
1✔
2064
      find_external_module_type_path y >>= fun y -> Some (`SubstT (x, y))
×
2065
  | `CanonicalModuleType (x, _) | `Substituted x ->
×
2066
      find_external_module_type_path x >>= fun x -> Some (`Substituted x)
×
2067
  | `Gpath _ -> Some p
×
2068
  | `AliasModuleType (x, y) -> (
1✔
2069
      match
2070
        (find_external_module_type_path x, find_external_module_type_path y)
1✔
2071
      with
2072
      | Some x, Some y -> Some (`AliasModuleType (x, y))
×
2073
      | Some x, None -> Some x
1✔
2074
      | None, Some x -> Some x
×
2075
      | None, None -> None)
×
2076
  | `OpaqueModuleType m ->
×
2077
      find_external_module_type_path m >>= fun x -> Some (`OpaqueModuleType x)
×
2078

2079
and find_external_parent_path :
2080
    Cpath.Resolved.parent -> Cpath.Resolved.parent option =
2081
 fun p ->
2082
  let open Odoc_utils.OptionMonad in
6✔
2083
  match p with
2084
  | `Module m -> find_external_module_path m >>= fun m -> Some (`Module m)
5✔
2085
  | `ModuleType m ->
×
2086
      find_external_module_type_path m >>= fun m -> Some (`ModuleType m)
×
2087
  | `FragmentRoot -> None
×
2088

2089
and fixup_module_cfrag (f : Cfrag.resolved_module) : Cfrag.resolved_module =
2090
  match f with
33✔
2091
  | `Subst (path, frag) -> (
1✔
2092
      match find_external_module_type_path path with
2093
      | Some p -> `Subst (p, frag)
1✔
2094
      | None -> frag)
×
2095
  | `Alias (path, frag) -> (
2✔
2096
      match find_external_module_path path with
2097
      | Some p -> `Alias (p, frag)
2✔
2098
      | None -> frag)
×
2099
  | `Module (parent, name) -> `Module (fixup_signature_cfrag parent, name)
30✔
2100
  | `OpaqueModule m -> `OpaqueModule (fixup_module_cfrag m)
×
2101

2102
and fixup_module_type_cfrag (f : Cfrag.resolved_module_type) :
2103
    Cfrag.resolved_module_type =
2104
  match f with
6✔
2105
  | `ModuleType (parent, name) ->
6✔
2106
      `ModuleType (fixup_signature_cfrag parent, name)
6✔
2107

2108
and fixup_signature_cfrag (f : Cfrag.resolved_signature) =
2109
  match f with
71✔
2110
  | `Root x -> `Root x
63✔
2111
  | (`OpaqueModule _ | `Subst _ | `Alias _ | `Module _) as f ->
×
2112
      (fixup_module_cfrag f :> Cfrag.resolved_signature)
2113

2114
and fixup_type_cfrag (f : Cfrag.resolved_type) : Cfrag.resolved_type =
2115
  match f with
35✔
2116
  | `Type (p, x) -> `Type (fixup_signature_cfrag p, x)
35✔
2117
  | `Class (p, x) -> `Class (fixup_signature_cfrag p, x)
×
2118
  | `ClassType (p, x) -> `ClassType (fixup_signature_cfrag p, x)
×
2119

2120
and find_module_with_replacement :
2121
    Env.t ->
2122
    Component.Signature.t ->
2123
    ModuleName.t ->
2124
    (Component.Module.t Component.Delayed.t, simple_module_lookup_error) result
2125
    =
2126
 fun env sg name ->
2127
  match Find.careful_module_in_sig sg name with
34✔
2128
  | Some (`FModule (_, m)) -> Ok (Component.Delayed.put_val m)
34✔
2129
  | Some (`FModule_removed path) ->
×
2130
      resolve_module env path >>= fun (_, m) -> Ok m
×
2131
  | None -> Error `Find_failure
×
2132

2133
and find_module_type_with_replacement :
2134
    Env.t ->
2135
    Component.Signature.t ->
2136
    ModuleTypeName.t ->
2137
    ( Component.ModuleType.t Component.Delayed.t,
2138
      simple_module_type_lookup_error )
2139
    result =
2140
 fun _env sg name ->
2141
  match Find.careful_module_type_in_sig sg name with
6✔
2142
  | Some (`FModuleType (_, m)) -> Ok (Component.Delayed.put_val m)
6✔
2143
  | None -> Error `Find_failure
×
2144
  | Some (`FModuleType_removed _mty) -> Error `Find_failure
×
2145

2146
and resolve_signature_fragment :
2147
    Env.t ->
2148
    Cfrag.root * Component.Signature.t ->
2149
    Cfrag.signature ->
2150
    (Cfrag.resolved_signature * Cpath.Resolved.parent * Component.Signature.t)
2151
    option =
2152
 fun env (p, sg) frag ->
2153
  match frag with
75✔
2154
  | `Root ->
66✔
2155
      let sg = prefix_signature (`FragmentRoot, sg) in
2156
      Some (`Root p, `FragmentRoot, sg)
66✔
2157
  | `Resolved _r -> None
×
2158
  | `Dot (parent, name) ->
9✔
2159
      let open Odoc_utils.OptionMonad in
2160
      resolve_signature_fragment env (p, sg) parent
9✔
2161
      >>= fun (pfrag, ppath, sg) ->
2162
      of_result (find_module_with_replacement env sg (ModuleName.make_std name))
9✔
2163
      >>= fun m' ->
2164
      let mname = ModuleName.make_std name in
9✔
2165
      let new_path = `Module (ppath, mname) in
9✔
2166
      let new_frag = `Module (pfrag, mname) in
2167
      let m' = Component.Delayed.get m' in
2168
      let modifier = get_module_path_modifiers env m' in
9✔
2169
      let cp', f' =
9✔
2170
        match modifier with
2171
        | None -> (new_path, new_frag)
5✔
2172
        | Some (`Aliased (`Canonical (p', _))) | Some (`Aliased p') ->
×
2173
            (`Alias (p', `Resolved new_path, None), `Alias (p', new_frag))
2174
        | Some (`SubstMT p') -> (`Subst (p', new_path), `Subst (p', new_frag))
1✔
2175
      in
2176
      (* Don't use the cached one - `FragmentRoot` is not unique *)
2177
      of_result
9✔
2178
        Odoc_utils.ResultMonad.(
2179
          expansion_of_module env m' >>= assert_not_functor)
9✔
2180
      >>= fun parent_sg ->
2181
      let sg = prefix_signature (`Module cp', parent_sg) in
9✔
2182
      Some (f', `Module cp', sg)
9✔
2183

2184
and resolve_module_fragment :
2185
    Env.t ->
2186
    Cfrag.root * Component.Signature.t ->
2187
    Cfrag.module_ ->
2188
    Cfrag.resolved_module option =
2189
 fun env (p, sg) frag ->
2190
  match frag with
103✔
2191
  | `Resolved r -> Some r
78✔
2192
  | `Dot (parent, name) ->
25✔
2193
      let open Odoc_utils.OptionMonad in
2194
      resolve_signature_fragment env (p, sg) parent
25✔
2195
      >>= fun (pfrag, _ppath, sg) ->
2196
      of_result (find_module_with_replacement env sg (ModuleName.make_std name))
25✔
2197
      >>= fun m' ->
2198
      let mname = ModuleName.make_std name in
25✔
2199
      let new_frag = `Module (pfrag, mname) in
25✔
2200
      let m' = Component.Delayed.get m' in
2201
      let modifier = get_module_path_modifiers env m' in
25✔
2202
      let f' =
25✔
2203
        match modifier with
2204
        | None -> new_frag
25✔
2205
        | Some (`Aliased (`Canonical (p', _))) | Some (`Aliased p') ->
×
2206
            `Alias (p', new_frag)
2207
        | Some (`SubstMT p') -> `Subst (p', new_frag)
×
2208
      in
2209
      let f'' =
2210
        match expansion_of_module env m' with
2211
        | Ok (_m : expansion) -> f'
25✔
2212
        | Error `OpaqueModule -> `OpaqueModule f'
×
2213
        | Error
2214
            ( `UnresolvedForwardPath | `UnresolvedPath _
×
2215
            | `UnresolvedOriginalPath _ ) ->
×
2216
            f'
2217
      in
2218
      Some (fixup_module_cfrag f'')
25✔
2219

2220
and resolve_module_type_fragment :
2221
    Env.t ->
2222
    Cfrag.root * Component.Signature.t ->
2223
    Cfrag.module_type ->
2224
    Cfrag.resolved_module_type option =
2225
 fun env (p, sg) frag ->
2226
  match frag with
6✔
2227
  | `Resolved r -> Some r
×
2228
  | `Dot (parent, name) ->
6✔
2229
      let open Odoc_utils.OptionMonad in
2230
      resolve_signature_fragment env (p, sg) parent
6✔
2231
      >>= fun (pfrag, _ppath, sg) ->
2232
      of_result
6✔
2233
        (find_module_type_with_replacement env sg
6✔
2234
           (ModuleTypeName.make_std name))
6✔
2235
      >>= fun mt' ->
2236
      let mtname = ModuleTypeName.make_std name in
6✔
2237
      let f' = `ModuleType (pfrag, mtname) in
6✔
2238
      let m' = Component.Delayed.get mt' in
2239
      let f'' =
6✔
2240
        match expansion_of_module_type env m' with
2241
        | Ok (_m : expansion) -> f'
6✔
2242
        | Error
2243
            ( `UnresolvedForwardPath | `UnresolvedPath _ | `OpaqueModule
×
2244
            | `UnresolvedOriginalPath _ ) ->
×
2245
            f'
2246
      in
2247
      Some (fixup_module_type_cfrag f'')
6✔
2248

2249
and resolve_type_fragment :
2250
    Env.t ->
2251
    Cfrag.root * Component.Signature.t ->
2252
    Cfrag.type_ ->
2253
    Cfrag.resolved_type option =
2254
 fun env (p, sg) frag ->
2255
  match frag with
37✔
2256
  | `Resolved r -> Some r
2✔
2257
  | `Dot (parent, name) ->
35✔
2258
      let open Odoc_utils.OptionMonad in
2259
      resolve_signature_fragment env (p, sg) parent
35✔
2260
      >>= fun (pfrag, _ppath, _sg) ->
2261
      let result = fixup_type_cfrag (`Type (pfrag, TypeName.make_std name)) in
35✔
2262
      Some result
35✔
2263

2264
let rec reresolve_signature_fragment :
2265
    Env.t -> Cfrag.resolved_signature -> Cfrag.resolved_signature =
2266
 fun env m ->
2267
  match m with
61✔
2268
  | `Root (`ModuleType p) -> `Root (`ModuleType (reresolve_module_type env p))
45✔
2269
  | `Root (`Module p) -> `Root (`Module (reresolve_module env p))
7✔
2270
  | (`OpaqueModule _ | `Subst _ | `Alias _ | `Module _) as x ->
×
2271
      (reresolve_module_fragment env x :> Cfrag.resolved_signature)
2272

2273
and reresolve_module_fragment :
2274
    Env.t -> Cfrag.resolved_module -> Cfrag.resolved_module =
2275
 fun env m ->
2276
  match m with
25✔
2277
  | `Subst (p, f) ->
1✔
2278
      let p' = reresolve_module_type env p in
2279
      `Subst (p', reresolve_module_fragment env f)
1✔
2280
  | `Alias (p, f) ->
3✔
2281
      let p' = reresolve_module env p in
2282
      `Alias (p', reresolve_module_fragment env f)
3✔
2283
  | `OpaqueModule m -> `OpaqueModule (reresolve_module_fragment env m)
×
2284
  | `Module (sg, m) -> `Module (reresolve_signature_fragment env sg, m)
21✔
2285

2286
and reresolve_type_fragment :
2287
    Env.t -> Cfrag.resolved_type -> Cfrag.resolved_type =
2288
 fun env m ->
2289
  match m with
34✔
2290
  | `Type (p, n) -> `Type (reresolve_signature_fragment env p, n)
34✔
2291
  | `ClassType (p, n) -> `ClassType (reresolve_signature_fragment env p, n)
×
2292
  | `Class (p, n) -> `Class (reresolve_signature_fragment env p, n)
×
2293

2294
and reresolve_module_type_fragment :
2295
    Env.t -> Cfrag.resolved_module_type -> Cfrag.resolved_module_type =
2296
 fun env m ->
2297
  match m with
6✔
2298
  | `ModuleType (p, n) -> `ModuleType (reresolve_signature_fragment env p, n)
6✔
2299

2300
let rec class_signature_of_class :
2301
    Env.t -> Component.Class.t -> Component.ClassSignature.t option =
2302
 fun env c ->
2303
  let rec inner decl =
29✔
2304
    match decl with
31✔
2305
    | Component.Class.ClassType e -> class_signature_of_class_type_expr env e
29✔
2306
    | Arrow (_, _, d) -> inner d
2✔
2307
  in
2308
  inner c.type_
2309

2310
and class_signature_of_class_type_expr :
2311
    Env.t -> Component.ClassType.expr -> Component.ClassSignature.t option =
2312
 fun env e ->
2313
  match e with
53✔
2314
  | Signature s -> Some s
46✔
2315
  | Constr (p, _) -> (
7✔
2316
      match resolve_type env (p :> Cpath.type_) with
2317
      | Ok (_, `FClass (_, c)) -> class_signature_of_class env c
2✔
2318
      | Ok (_, `FClassType (_, c)) -> class_signature_of_class_type env c
5✔
2319
      | _ -> None)
×
2320

2321
and class_signature_of_class_type :
2322
    Env.t -> Component.ClassType.t -> Component.ClassSignature.t option =
2323
 fun env c -> class_signature_of_class_type_expr env c.expr
24✔
2324

2325
let resolve_module_path env p =
2326
  resolve_module env p >>= fun (p, m) ->
676✔
2327
  match p with
641✔
2328
  | `Gpath (`Identifier { iv = `Root _; _ })
30✔
2329
  | `Hidden (`Gpath (`Identifier { iv = `Root _; _ })) ->
18✔
2330
      Ok p
2331
  | _ -> (
593✔
2332
      let m = Component.Delayed.get m in
2333
      match expansion_of_module_cached env p m with
593✔
2334
      | Ok _ -> Ok p
588✔
2335
      | Error `OpaqueModule -> Ok (`OpaqueModule p)
1✔
2336
      | Error
2337
          ( `UnresolvedForwardPath | `UnresolvedPath _
×
2338
          | `UnresolvedOriginalPath _ ) ->
×
2339
          Ok p)
2340

2341
let resolve_module_type_path env p =
2342
  resolve_module_type env p >>= fun (p, mt) ->
189✔
2343
  match expansion_of_module_type env mt with
185✔
2344
  | Ok _ -> Ok p
170✔
2345
  | Error `OpaqueModule -> Ok (`OpaqueModuleType p)
15✔
2346
  | Error
2347
      (`UnresolvedForwardPath | `UnresolvedPath _ | `UnresolvedOriginalPath _)
×
2348
    ->
2349
      Ok p
2350

2351
let resolve_type_path env p = resolve_type env p >>= fun (p, _) -> Ok p
35✔
2352

2353
let resolve_value_path env p = resolve_value env p >>= fun (p, _) -> Ok p
5✔
2354

2355
let resolve_class_type_path env p =
2356
  resolve_class_type env p >>= fun (p, _) -> Ok p
11✔
2357

2358
let apply_inner_substs env (sg : Component.Signature.t) : Component.Signature.t
2359
    =
2360
  let rec inner (items : Component.Signature.item list) :
121✔
2361
      Component.Signature.item list =
2362
    match items with
324✔
2363
    | Component.Signature.TypeSubstitution (id, typedecl) :: rest -> (
7✔
2364
        let subst =
2365
          Component.ModuleType.TypeSubst
2366
            (`Dot (`Root, Ident.Name.type_ id), typedecl.equation)
7✔
2367
        in
2368
        let rest =
2369
          Component.Signature.Type
2370
            (id, Ordinary, Component.Delayed.put (fun () -> typedecl))
7✔
2371
          :: inner rest
7✔
2372
        in
2373
        match fragmap env subst { sg with items = rest } with
2374
        | Ok sg' -> sg'.items
7✔
2375
        | Error _ -> failwith "error")
×
2376
    | Component.Signature.ModuleSubstitution (id, modsubst) :: rest -> (
2✔
2377
        let subst =
2378
          Component.ModuleType.ModuleSubst
2379
            (`Dot (`Root, Ident.Name.module_ id), modsubst.manifest)
2✔
2380
        in
2381
        let rest =
2382
          Component.Signature.Module
2383
            ( id,
2384
              Ordinary,
2385
              Component.Delayed.put (fun () ->
2✔
2386
                  {
2✔
2387
                    Component.Module.source_loc = None;
2388
                    doc = modsubst.doc;
2389
                    type_ = Alias (modsubst.manifest, None);
2390
                    canonical = None;
2391
                    hidden = false;
2392
                  }) )
2393
          :: inner rest
2✔
2394
        in
2395
        match fragmap env subst { sg with items = rest } with
2396
        | Ok sg' -> sg'.items
2✔
2397
        | Error _ -> failwith "error")
×
2398
    | Component.Signature.ModuleTypeSubstitution (id, modtypesubst) :: rest -> (
4✔
2399
        let subst =
2400
          Component.ModuleType.ModuleTypeSubst
2401
            (`Dot (`Root, Ident.Name.module_type id), modtypesubst.manifest)
4✔
2402
        in
2403
        let rest =
2404
          Component.Signature.ModuleType
2405
            ( id,
2406
              Component.Delayed.put (fun () ->
4✔
2407
                  {
4✔
2408
                    Component.ModuleType.source_loc = None;
2409
                    doc = modtypesubst.doc;
2410
                    expr = Some modtypesubst.manifest;
2411
                    canonical = None;
2412
                  }) )
2413
          :: inner rest
4✔
2414
        in
2415
        match fragmap env subst { sg with items = rest } with
2416
        | Ok sg' -> sg'.items
4✔
2417
        | Error _ -> failwith "error")
×
2418
    | x :: rest -> x :: inner rest
190✔
2419
    | [] -> []
121✔
2420
  in
2421
  { sg with items = inner sg.items }
121✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc