Test that unwrapped libraries can use instantation of parameterised libraries.

  $ cat > dune-project <<EOF
  > (lang dune 3.20)
  > (using oxcaml 0.1)
  > EOF

We define a parameter:

  $ mkdir param
  $ echo 'val v : string' > param/param.mli
  $ cat > param/dune <<EOF
  > (library_parameter (name param))
  > EOF

And an implementation of this parameter:

  $ mkdir impl
  $ echo 'let v = "impl"' > impl/helper.ml
  $ echo 'let v = Helper.v' > impl/impl.ml
  $ cat > impl/dune <<EOF
  > (library (name impl) (implements param))
  > EOF

  $ dune build

It's an error for the implementation to be unwrapped, since it must
exactly implement the parameter signature (a single mli):

  $ cat > impl/dune <<EOF
  > (library
  >   (name impl)
  >   (implements param)
  >   (wrapped false))
  > EOF

  $ dune build
  File "impl/dune", line 4, characters 11-16:
  4 |   (wrapped false))
                 ^^^^^
  Error: Wrapped cannot be set for implementations. It is inherited from the
  virtual library.
  [1]

  $ cat > impl/dune <<EOF
  > (library (name impl) (implements param))
  > EOF

A parameterised library:

  $ mkdir lib
  $ echo 'let v () = "helper:" ^ String.uppercase_ascii Param.v' > lib/helper.ml
  $ echo 'let v () = "lib:" ^ Helper.v ()' > lib/lib.ml
  $ cat > lib/dune <<EOF
  > (library (name lib) (parameters param))
  > EOF

And an executable:

  $ mkdir bin
  $ echo 'let a () = Util.util ()' > bin/a.ml
  $ echo 'let util () = print_endline (Lib.v ())' > bin/util.ml
  $ echo 'let () = A.a ()' > bin/bin.ml
  $ cat > bin/dune <<EOF
  > (executable (name bin) (libraries (instantiate lib impl)))
  > EOF

  $ dune exec ./bin/bin.exe
  lib:helper:IMPL

The library can be unwrapped:

  $ cat > lib/dune <<EOF
  > (library (name lib) (parameters param) (wrapped false))
  > EOF

  $ dune exec ./bin/bin.exe
  lib:helper:IMPL

The binary also has access to `lib` Helper module:

  $ echo 'let () = A.a (); print_endline (Helper.v ())' > bin/bin.ml
  $ dune exec ./bin/bin.exe
  lib:helper:IMPL
  helper:IMPL

We can instantiate multiple times, if we give a name to each instantiation, but
the result is wrapped:

  $ echo 'let () = print_endline (Lib1.Lib.v () ^ " " ^ Lib2.Helper.v ())' > bin/bin.ml
  $ cat > bin/dune <<EOF
  > (executable (name bin)
  >   (libraries
  >     (instantiate lib impl :as lib1)
  >     (instantiate lib impl :as lib2)))
  > EOF
  $ dune exec ./bin/bin.exe
  lib:helper:IMPL helper:IMPL

  $ cat _build/default/bin/.bin.eobjs/dune__exe.ml-gen
  (* generated by dune *)
  
  (** @canonical Dune__exe.A *)
  module A = Dune__exe__A
  
  (** @canonical Dune__exe.Bin *)
  module Bin = Dune__exe__Bin
  
  (** @canonical Dune__exe.Util *)
  module Util = Dune__exe__Util
  
  module Lib1 = struct
    module Helper = Helper(Param)(Impl) [@jane.non_erasable.instances]
    module Lib = Lib(Param)(Impl) [@jane.non_erasable.instances]
  end
  
  module Lib2 = struct
    module Helper = Helper(Param)(Impl) [@jane.non_erasable.instances]
    module Lib = Lib(Param)(Impl) [@jane.non_erasable.instances]
  end

Testing that it also works with another layer of library:

  $ mkdir lib2
  $ echo 'let v2 () = "lib2:" ^ Lib.v () ^ " " ^ Helper.v ()' > lib2/lib2.ml
  $ cat > lib2/dune <<EOF
  > (library (name lib2) (libraries (instantiate lib impl)))
  > EOF

  $ echo 'let () = A.a (); print_endline (Lib2.v2 ())' > bin/bin.ml
  $ cat > bin/dune <<EOF
  > (executable (name bin) (libraries (instantiate lib impl) lib2))
  > EOF

  $ dune exec ./bin/bin.exe
  lib:helper:IMPL
  lib2:lib:helper:IMPL helper:IMPL

TODO: An unwrapped library currently has to instantiate the functors manually,
because we don't have a file where to put the instantiations:

  $ mkdir unwrap_lib
  $ cat > unwrap_lib/unwrap_a.ml <<EOF
  > module Lib = Lib(Param)(Impl) [@jane.non_erasable.instances]
  > let a () = "a:" ^ Lib.v ()
  > EOF
  $ echo 'let b () = "b:" ^ Unwrap_a.a ()' > unwrap_lib/unwrap_b.ml
  $ cat > unwrap_lib/dune <<EOF
  > (library
  >   (name unwrap_lib)
  >   (wrapped false)
  >   (flags "-w" "-53") ; ignore misplaced-attribute warning
  >   (libraries (instantiate lib impl)))
  > EOF

  $ echo 'let () = print_endline (Unwrap_a.a () ^ "," ^ Unwrap_b.b ())' > bin/bin.ml
  $ cat > bin/dune <<EOF
  > (executable (name bin) (libraries unwrap_lib))
  > EOF

  $ dune exec ./bin/bin.exe
  a:lib:helper:IMPL,b:a:lib:helper:IMPL

