Dune virtual libraries: default implementation bug?

Hi

I am playing with dune virtual_modules and default_implementation stanzas. Basically my dune file is (I can provide the full test project, it’s very short)

(library
 (name test)
 (public_name test)
 (virtual_modules a)
 (default_implementation test.a))

It compiles fine with dune build. However, running dune build @check violently fails with

 dune build @check
Internal error, please report upstream including the contents of _build/log.
Description:
  ("Map.find_exn: failed to find key",
   { key =
       { source =
           { path = [ "A" ]
           ; files =
               { impl = None
               ; intf =
                   Some
                     { path = In_build_dir "default/lib/a.mli"
                     ; original_path = In_build_dir "default/lib/a.mli"
                     ; dialect = "ocaml"
                     }
               }
           }
       ; obj_name = "test__A"
       ; pp = None
       ; visibility = "public"
       ; kind = "virtual"
       ; install_as = None
       }
   ; keys =
       [ { source =
             { path = [ "Test" ]
             ; files =
                 { impl =
                     Some
                       { path = In_build_dir "default/lib/test.ml"
                       ; original_path = In_build_dir "default/lib/test.ml"
                       ; dialect = "ocaml"
                       }
                 ; intf = None
                 }
             }
         ; obj_name = "test"
         ; pp = None
         ; visibility = "public"
         ; kind = "impl"
         ; install_as = None
         }
       ; { source =
             { path = [ "Test__" ]
             ; files =
                 { impl =
                     Some
                       { path = In_build_dir "default/lib/test__.ml-gen"
                       ; original_path =
                           In_build_dir "default/lib/test__.ml-gen"
                       ; dialect = "ocaml"
                       }
                 ; intf = None
                 }
             }
         ; obj_name = "test__"
         ; pp = None
         ; visibility = "public"
         ; kind = "alias"
         ; install_as = None
         }
       ]
   })
Raised at Stdune__Code_error.raise in file "stdune__Code_error.ml", line 11,
  characters 30-62
Called from Dune_rules__Dep_graph.top_closed_implementations.(fun) in file
  "dune_rules__Dep_graph.ml", line 56, characters 30-65
Called from Stdune__List.rev_filter_map.loop in file "stdune__List.ml", line
  22, characters 13-16
Called from Stdune__List.filter_map in file "stdune__List.ml" (inlined), line
  29, characters 26-47
Called from Dune_rules__Dep_graph.top_closed_implementations in file
  "dune_rules__Dep_graph.ml", lines 54-58, characters 10-26
Called from Dune_engine__Action_builder.T.M.map.(fun) in file
  "dune_engine__Action_builder.ml", line 45, characters 12-15
Called from Fiber__Core.O.(>>|).(fun) in file "fiber__Core.ml", line 254,
  characters 36-41
Called from Fiber__Scheduler.exec in file "fiber__Scheduler.ml", line 77,
  characters 8-11
-> required by ("top sorted implementations", ())
-> required by ("<unnamed>", ())
-> required by
   ("build-alias", { dir = In_build_dir "default/lib"; name = "check" })
-> required by ("toplevel", ())

I must not crash.  Uncertainty is the mind-killer. Exceptions are the
little-death that brings total obliteration.  I will fully express my cases. 
Execution will pass over me and through me.  And when it has gone past, I
will unwind the stack along its path.  Where the cases are handled there will
be nothing.  Only I will remain.

Is this a bug?

This is very annoying because the ocaml.ci uses the @check flag so this will never pass…

Here is the complete project:

$ ls -R.:
default_impl  dune-project  lib  test.opam

./default_impl:
a.ml  dune

./lib:
a.mli  dune  test.ml

* File: ./test.opam
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
synopsis: "Virtual test library with a default implementation"
depends: [
  "dune" {>= "3.10"}
  "odoc" {with-doc}
]
build: [
  ["dune" "subst"] {dev}
  [
    "dune"
    "build"
    "-p"
    name
    "-j"
    jobs
    "@install"
    "@runtest" {with-test}
    "@doc" {with-doc}
  ]
]

* File: ./default_impl/dune
(library
 (name test_a)
 (public_name test.a)
 (implements test)
)

* File: ./default_impl/a.ml
let compute x = x + 1

* File: ./lib/a.mli
val compute : int -> int

* File: ./lib/test.ml
let run x = A.compute x * 2

* File: ./lib/dune
(library
 (name test)
 (public_name test)
 (virtual_modules a)
 (default_implementation test.a)
)

* File: ./dune-project
(lang dune 3.10)
(name test)
(generate_opam_files true)

I think you should so what the first line tells you to do:

Internal error, please report upstream including the contents of _build/log.

Even if you’d be misusing the stuff this is not supposed to happen.

3 Likes
2 Likes