Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Make sure that dependencies of implementations do not create a cycle
back to the virtual library.

Signed-off-by: Rudi Grinberg <[email protected]>
  • Loading branch information
rgrinberg committed Mar 23, 2020
1 parent 3c0f0e3 commit 422ce5d
Show file tree
Hide file tree
Showing 2 changed files with 44 additions and 1 deletion.
39 changes: 38 additions & 1 deletion src/dune/lib.ml
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,9 @@ module Vlib : sig
-> linking:bool
-> t list Or_exn.t

val validate_impl_closure :
lib list -> impl:lib -> vlib:lib -> (unit, exn) result

module Unimplemented : sig
(** set of unimplemented libraries*)
type t
Expand Down Expand Up @@ -961,6 +964,12 @@ end = struct

type t = lib Map.t

let filled_impls_only (impls : Partial.t) =
Map.filter_map impls ~f:(fun status ->
match status with
| Partial.No_impl _ -> None
| Impl (impl, _stack) -> Some impl)

let make impls ~orig_stack : t Or_exn.t =
let rec loop acc = function
| [] -> Ok acc
Expand Down Expand Up @@ -1036,6 +1045,15 @@ end = struct
let+ () = Result.List.iter ts ~f:loop in
List.rev !res

let validate_impl_closure (closure : lib list) ~impl ~vlib =
let closure = List.map closure ~f:(fun x -> (x, Dep_stack.empty)) in
let* impls = Table.Partial.make closure ~orig_stack:Dep_stack.empty in
if Table.Partial.is_empty impls then
Ok ()
else
let impls = Table.filled_impls_only impls in
validate_closure ~vlib ~impl impls

let associate closure ~orig_stack ~linking =
let* impls = Table.Partial.make closure ~orig_stack in
let closure = List.map closure ~f:fst in
Expand Down Expand Up @@ -1730,7 +1748,26 @@ module Compile = struct
>>= Resolve.compile_closure_with_overlap_checks db
~stack:Dep_stack.empty ~forbidden_libraries:Map.empty )
in
{ direct_requires = t.requires
let valid_impl =
match t.implements with
| None
| Some (Error _) ->
Ok () (* we'll see the error later *)
| Some (Ok vlib) ->
(* we need this check to make sure *)
let* requires_link = Lazy.force requires_link in
Vlib.validate_impl_closure requires_link ~impl:t ~vlib
in
let direct_requires =
let* () = valid_impl in
t.requires
in
let requires_link =
match valid_impl with
| Ok _ -> requires_link
| Error e -> lazy (Error e)
in
{ direct_requires
; requires_link
; resolved_selects = t.resolved_selects
; pps = t.pps
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,12 @@ where vlib is a virtual library, and impl implements this library.
$ cat >impl/dune <<EOF
> (library (name impl) (implements vlib) (libraries lib))
> EOF
$ dune build @all
Error: Implementation impl has a dependency that uses the virtual library
vlib
- impl at _build/default/impl
-> - lib at _build/default/lib
[1]

The implementation impl was built, but it's not usable:

Expand Down

0 comments on commit 422ce5d

Please sign in to comment.