{-# LANGUAGE NondecreasingIndentation #-}
module Distribution.Backpack.MixLink (
mixLink,
) where
import Prelude ()
import Distribution.Compat.Prelude hiding (mod)
import Distribution.Backpack
import Distribution.Backpack.UnifyM
import Distribution.Backpack.FullUnitId
import Distribution.Backpack.ModuleScope
import qualified Distribution.Utils.UnionFind as UnionFind
import Distribution.ModuleName
import Distribution.Pretty
import Distribution.Types.ComponentId
import Text.PrettyPrint
import Control.Monad
import qualified Data.Map as Map
import qualified Data.Foldable as F
mixLink :: [ModuleScopeU s] -> UnifyM s (ModuleScopeU s)
mixLink :: forall s. [ModuleScopeU s] -> UnifyM s (ModuleScopeU s)
mixLink [ModuleScopeU s]
scopes = do
let provs :: Map ModuleName [ModuleWithSourceU s]
provs = forall (f :: * -> *) k a.
(Foldable f, Ord k) =>
(a -> a -> a) -> f (Map k a) -> Map k a
Map.unionsWith forall a. [a] -> [a] -> [a]
(++) (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> a
fst [ModuleScopeU s]
scopes)
reqs :: Map ModuleName [ModuleWithSourceU s]
reqs = forall (f :: * -> *) k a.
(Foldable f, Ord k) =>
(a -> a -> a) -> f (Map k a) -> Map k a
Map.unionsWith forall a. [a] -> [a] -> [a]
(++) (forall a b. (a -> b) -> [a] -> [b]
map forall a b. (a, b) -> b
snd [ModuleScopeU s]
scopes)
filled :: Map ModuleName (UnifyM s [ModuleWithSourceU s])
filled = forall k a b c.
Ord k =>
(k -> a -> b -> c) -> Map k a -> Map k b -> Map k c
Map.intersectionWithKey forall s.
ModuleName
-> [ModuleWithSourceU s]
-> [ModuleWithSourceU s]
-> UnifyM s [ModuleWithSourceU s]
linkProvision Map ModuleName [ModuleWithSourceU s]
provs Map ModuleName [ModuleWithSourceU s]
reqs
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Applicative f) =>
t (f a) -> f ()
F.sequenceA_ Map ModuleName (UnifyM s [ModuleWithSourceU s])
filled
let remaining :: Map ModuleName [ModuleWithSourceU s]
remaining = forall k a b. Ord k => Map k a -> Map k b -> Map k a
Map.difference Map ModuleName [ModuleWithSourceU s]
reqs Map ModuleName (UnifyM s [ModuleWithSourceU s])
filled
forall (m :: * -> *) a. Monad m => a -> m a
return (Map ModuleName [ModuleWithSourceU s]
provs, Map ModuleName [ModuleWithSourceU s]
remaining)
linkProvision :: ModuleName
-> [ModuleWithSourceU s]
-> [ModuleWithSourceU s]
-> UnifyM s [ModuleWithSourceU s]
linkProvision :: forall s.
ModuleName
-> [ModuleWithSourceU s]
-> [ModuleWithSourceU s]
-> UnifyM s [ModuleWithSourceU s]
linkProvision ModuleName
mod_name ret :: [ModuleWithSourceU s]
ret@(ModuleWithSourceU s
prov:[ModuleWithSourceU s]
provs) (ModuleWithSourceU s
req:[ModuleWithSourceU s]
reqs) = do
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [ModuleWithSourceU s]
provs forall a b. (a -> b) -> a -> b
$ \ModuleWithSourceU s
prov' -> do
OpenModule
mod <- forall s. ModuleU s -> UnifyM s OpenModule
convertModuleU (forall a. WithSource a -> a
unWithSource ModuleWithSourceU s
prov)
OpenModule
mod' <- forall s. ModuleU s -> UnifyM s OpenModule
convertModuleU (forall a. WithSource a -> a
unWithSource ModuleWithSourceU s
prov')
Maybe ()
r <- forall {s}.
WithSource (ModuleU s)
-> WithSource (ModuleU s) -> UnifyM s (Maybe ())
unify ModuleWithSourceU s
prov ModuleWithSourceU s
prov'
case Maybe ()
r of
Just () -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
Maybe ()
Nothing -> do
forall s. MsgDoc -> UnifyM s ()
addErr forall a b. (a -> b) -> a -> b
$
String -> MsgDoc
text String
"Ambiguous module" MsgDoc -> MsgDoc -> MsgDoc
<+> MsgDoc -> MsgDoc
quotes (forall a. Pretty a => a -> MsgDoc
pretty ModuleName
mod_name) MsgDoc -> MsgDoc -> MsgDoc
$$
String -> MsgDoc
text String
"It could refer to" MsgDoc -> MsgDoc -> MsgDoc
<+>
( String -> MsgDoc
text String
" " MsgDoc -> MsgDoc -> MsgDoc
<+> (MsgDoc -> MsgDoc
quotes (forall a. Pretty a => a -> MsgDoc
pretty OpenModule
mod) MsgDoc -> MsgDoc -> MsgDoc
$$ ModuleSource -> MsgDoc
in_scope_by (forall a. WithSource a -> ModuleSource
getSource ModuleWithSourceU s
prov)) MsgDoc -> MsgDoc -> MsgDoc
$$
String -> MsgDoc
text String
"or" MsgDoc -> MsgDoc -> MsgDoc
<+> (MsgDoc -> MsgDoc
quotes (forall a. Pretty a => a -> MsgDoc
pretty OpenModule
mod') MsgDoc -> MsgDoc -> MsgDoc
$$ ModuleSource -> MsgDoc
in_scope_by (forall a. WithSource a -> ModuleSource
getSource ModuleWithSourceU s
prov')) ) MsgDoc -> MsgDoc -> MsgDoc
$$
MsgDoc
link_doc
OpenModule
mod <- forall s. ModuleU s -> UnifyM s OpenModule
convertModuleU (forall a. WithSource a -> a
unWithSource ModuleWithSourceU s
prov)
OpenModule
req_mod <- forall s. ModuleU s -> UnifyM s OpenModule
convertModuleU (forall a. WithSource a -> a
unWithSource ModuleWithSourceU s
req)
ComponentId
self_cid <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall s. UnifEnv s -> ComponentId
unify_self_cid forall s. UnifyM s (UnifEnv s)
getUnifEnv
case OpenModule
mod of
OpenModule (IndefFullUnitId ComponentId
cid OpenModuleSubst
_) ModuleName
_
| ComponentId
cid forall a. Eq a => a -> a -> Bool
== ComponentId
self_cid -> forall s. MsgDoc -> UnifyM s ()
addErr forall a b. (a -> b) -> a -> b
$
String -> MsgDoc
text String
"Cannot instantiate requirement" MsgDoc -> MsgDoc -> MsgDoc
<+> MsgDoc -> MsgDoc
quotes (forall a. Pretty a => a -> MsgDoc
pretty ModuleName
mod_name) MsgDoc -> MsgDoc -> MsgDoc
<+>
ModuleSource -> MsgDoc
in_scope_by (forall a. WithSource a -> ModuleSource
getSource ModuleWithSourceU s
req) MsgDoc -> MsgDoc -> MsgDoc
$$
String -> MsgDoc
text String
"with locally defined module" MsgDoc -> MsgDoc -> MsgDoc
<+> ModuleSource -> MsgDoc
in_scope_by (forall a. WithSource a -> ModuleSource
getSource ModuleWithSourceU s
prov) MsgDoc -> MsgDoc -> MsgDoc
$$
String -> MsgDoc
text String
"as this would create a cyclic dependency, which GHC does not support." MsgDoc -> MsgDoc -> MsgDoc
$$
String -> MsgDoc
text String
"Try moving this module to a separate library, e.g.," MsgDoc -> MsgDoc -> MsgDoc
$$
String -> MsgDoc
text String
"create a new stanza: library 'sublib'."
OpenModule
_ -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
Maybe ()
r <- forall {s}.
WithSource (ModuleU s)
-> WithSource (ModuleU s) -> UnifyM s (Maybe ())
unify ModuleWithSourceU s
prov ModuleWithSourceU s
req
case Maybe ()
r of
Just () -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
Maybe ()
Nothing -> do
forall s. MsgDoc -> UnifyM s ()
addErr forall a b. (a -> b) -> a -> b
$ String -> MsgDoc
text String
"Could not instantiate requirement" MsgDoc -> MsgDoc -> MsgDoc
<+> MsgDoc -> MsgDoc
quotes (forall a. Pretty a => a -> MsgDoc
pretty ModuleName
mod_name) MsgDoc -> MsgDoc -> MsgDoc
$$
Int -> MsgDoc -> MsgDoc
nest Int
4 (String -> MsgDoc
text String
"Expected:" MsgDoc -> MsgDoc -> MsgDoc
<+> forall a. Pretty a => a -> MsgDoc
pretty OpenModule
mod MsgDoc -> MsgDoc -> MsgDoc
$$
String -> MsgDoc
text String
"Actual: " MsgDoc -> MsgDoc -> MsgDoc
<+> forall a. Pretty a => a -> MsgDoc
pretty OpenModule
req_mod) MsgDoc -> MsgDoc -> MsgDoc
$$
MsgDoc -> MsgDoc
parens (String -> MsgDoc
text String
"This can occur if an exposed module of" MsgDoc -> MsgDoc -> MsgDoc
<+>
String -> MsgDoc
text String
"a libraries shares a name with another module.") MsgDoc -> MsgDoc -> MsgDoc
$$
MsgDoc
link_doc
forall (m :: * -> *) a. Monad m => a -> m a
return [ModuleWithSourceU s]
ret
where
unify :: WithSource (ModuleU s)
-> WithSource (ModuleU s) -> UnifyM s (Maybe ())
unify WithSource (ModuleU s)
s1 WithSource (ModuleU s)
s2 = forall s a. UnifyM s a -> UnifyM s (Maybe a)
tryM forall a b. (a -> b) -> a -> b
$ forall s a. MsgDoc -> UnifyM s a -> UnifyM s a
addErrContext MsgDoc
short_link_doc
forall a b. (a -> b) -> a -> b
$ forall s. ModuleU s -> ModuleU s -> UnifyM s ()
unifyModule (forall a. WithSource a -> a
unWithSource WithSource (ModuleU s)
s1) (forall a. WithSource a -> a
unWithSource WithSource (ModuleU s)
s2)
in_scope_by :: ModuleSource -> MsgDoc
in_scope_by ModuleSource
s = String -> MsgDoc
text String
"brought into scope by" MsgDoc -> MsgDoc -> MsgDoc
<+> ModuleSource -> MsgDoc
dispModuleSource ModuleSource
s
short_link_doc :: MsgDoc
short_link_doc = String -> MsgDoc
text String
"While filling requirement" MsgDoc -> MsgDoc -> MsgDoc
<+> MsgDoc -> MsgDoc
quotes (forall a. Pretty a => a -> MsgDoc
pretty ModuleName
mod_name)
link_doc :: MsgDoc
link_doc = String -> MsgDoc
text String
"While filling requirements of" MsgDoc -> MsgDoc -> MsgDoc
<+> MsgDoc
reqs_doc
reqs_doc :: MsgDoc
reqs_doc
| forall (t :: * -> *) a. Foldable t => t a -> Bool
null [ModuleWithSourceU s]
reqs = ModuleSource -> MsgDoc
dispModuleSource (forall a. WithSource a -> ModuleSource
getSource ModuleWithSourceU s
req)
| Bool
otherwise = ( String -> MsgDoc
text String
" " MsgDoc -> MsgDoc -> MsgDoc
<+> ModuleSource -> MsgDoc
dispModuleSource (forall a. WithSource a -> ModuleSource
getSource ModuleWithSourceU s
req) MsgDoc -> MsgDoc -> MsgDoc
$$
[MsgDoc] -> MsgDoc
vcat [ String -> MsgDoc
text String
"and" MsgDoc -> MsgDoc -> MsgDoc
<+> ModuleSource -> MsgDoc
dispModuleSource (forall a. WithSource a -> ModuleSource
getSource ModuleWithSourceU s
r) | ModuleWithSourceU s
r <- [ModuleWithSourceU s]
reqs])
linkProvision ModuleName
_ [ModuleWithSourceU s]
_ [ModuleWithSourceU s]
_ = forall a. HasCallStack => String -> a
error String
"linkProvision"
unifyUnitId :: UnitIdU s -> UnitIdU s -> UnifyM s ()
unifyUnitId :: forall s. UnitIdU s -> UnitIdU s -> UnifyM s ()
unifyUnitId UnitIdU s
uid1_u UnitIdU s
uid2_u
| UnitIdU s
uid1_u forall a. Eq a => a -> a -> Bool
== UnitIdU s
uid2_u = forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise = do
UnitIdU' s
xuid1 <- forall s a. ST s a -> UnifyM s a
liftST forall a b. (a -> b) -> a -> b
$ forall s a. Point s a -> ST s a
UnionFind.find UnitIdU s
uid1_u
UnitIdU' s
xuid2 <- forall s a. ST s a -> UnifyM s a
liftST forall a b. (a -> b) -> a -> b
$ forall s a. Point s a -> ST s a
UnionFind.find UnitIdU s
uid2_u
case (UnitIdU' s
xuid1, UnitIdU' s
xuid2) of
(UnitIdThunkU DefUnitId
u1, UnitIdThunkU DefUnitId
u2)
| DefUnitId
u1 forall a. Eq a => a -> a -> Bool
== DefUnitId
u2 -> forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise ->
forall s a. MsgDoc -> UnifyM s a
failWith forall a b. (a -> b) -> a -> b
$ MsgDoc -> Int -> MsgDoc -> MsgDoc
hang (String -> MsgDoc
text String
"Couldn't match unit IDs:") Int
4
(String -> MsgDoc
text String
" " MsgDoc -> MsgDoc -> MsgDoc
<+> forall a. Pretty a => a -> MsgDoc
pretty DefUnitId
u1 MsgDoc -> MsgDoc -> MsgDoc
$$
String -> MsgDoc
text String
"and" MsgDoc -> MsgDoc -> MsgDoc
<+> forall a. Pretty a => a -> MsgDoc
pretty DefUnitId
u2)
(UnitIdThunkU DefUnitId
uid1, UnitIdU Int
_ ComponentId
cid2 Map ModuleName (ModuleU s)
insts2)
-> forall s.
ComponentId
-> Map ModuleName (ModuleU s)
-> UnitIdU s
-> DefUnitId
-> UnitIdU s
-> UnifyM s ()
unifyThunkWith ComponentId
cid2 Map ModuleName (ModuleU s)
insts2 UnitIdU s
uid2_u DefUnitId
uid1 UnitIdU s
uid1_u
(UnitIdU Int
_ ComponentId
cid1 Map ModuleName (ModuleU s)
insts1, UnitIdThunkU DefUnitId
uid2)
-> forall s.
ComponentId
-> Map ModuleName (ModuleU s)
-> UnitIdU s
-> DefUnitId
-> UnitIdU s
-> UnifyM s ()
unifyThunkWith ComponentId
cid1 Map ModuleName (ModuleU s)
insts1 UnitIdU s
uid1_u DefUnitId
uid2 UnitIdU s
uid2_u
(UnitIdU Int
_ ComponentId
cid1 Map ModuleName (ModuleU s)
insts1, UnitIdU Int
_ ComponentId
cid2 Map ModuleName (ModuleU s)
insts2)
-> forall s.
ComponentId
-> Map ModuleName (ModuleU s)
-> UnitIdU s
-> ComponentId
-> Map ModuleName (ModuleU s)
-> UnitIdU s
-> UnifyM s ()
unifyInner ComponentId
cid1 Map ModuleName (ModuleU s)
insts1 UnitIdU s
uid1_u ComponentId
cid2 Map ModuleName (ModuleU s)
insts2 UnitIdU s
uid2_u
unifyThunkWith :: ComponentId
-> Map ModuleName (ModuleU s)
-> UnitIdU s
-> DefUnitId
-> UnitIdU s
-> UnifyM s ()
unifyThunkWith :: forall s.
ComponentId
-> Map ModuleName (ModuleU s)
-> UnitIdU s
-> DefUnitId
-> UnitIdU s
-> UnifyM s ()
unifyThunkWith ComponentId
cid1 Map ModuleName (ModuleU s)
insts1 UnitIdU s
uid1_u DefUnitId
uid2 UnitIdU s
uid2_u = do
FullDb
db <- forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall s. UnifEnv s -> FullDb
unify_db forall s. UnifyM s (UnifEnv s)
getUnifEnv
let FullUnitId ComponentId
cid2 OpenModuleSubst
insts2' = FullDb -> FullDb
expandUnitId FullDb
db DefUnitId
uid2
Map ModuleName (ModuleU s)
insts2 <- forall s. OpenModuleSubst -> UnifyM s (Map ModuleName (ModuleU s))
convertModuleSubst OpenModuleSubst
insts2'
forall s.
ComponentId
-> Map ModuleName (ModuleU s)
-> UnitIdU s
-> ComponentId
-> Map ModuleName (ModuleU s)
-> UnitIdU s
-> UnifyM s ()
unifyInner ComponentId
cid1 Map ModuleName (ModuleU s)
insts1 UnitIdU s
uid1_u ComponentId
cid2 Map ModuleName (ModuleU s)
insts2 UnitIdU s
uid2_u
unifyInner :: ComponentId
-> Map ModuleName (ModuleU s)
-> UnitIdU s
-> ComponentId
-> Map ModuleName (ModuleU s)
-> UnitIdU s
-> UnifyM s ()
unifyInner :: forall s.
ComponentId
-> Map ModuleName (ModuleU s)
-> UnitIdU s
-> ComponentId
-> Map ModuleName (ModuleU s)
-> UnitIdU s
-> UnifyM s ()
unifyInner ComponentId
cid1 Map ModuleName (ModuleU s)
insts1 UnitIdU s
uid1_u ComponentId
cid2 Map ModuleName (ModuleU s)
insts2 UnitIdU s
uid2_u = do
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ComponentId
cid1 forall a. Eq a => a -> a -> Bool
/= ComponentId
cid2) forall a b. (a -> b) -> a -> b
$
forall s a. MsgDoc -> UnifyM s a
failWith forall a b. (a -> b) -> a -> b
$
MsgDoc -> Int -> MsgDoc -> MsgDoc
hang (String -> MsgDoc
text String
"Couldn't match component IDs:") Int
4
(String -> MsgDoc
text String
" " MsgDoc -> MsgDoc -> MsgDoc
<+> forall a. Pretty a => a -> MsgDoc
pretty ComponentId
cid1 MsgDoc -> MsgDoc -> MsgDoc
$$
String -> MsgDoc
text String
"and" MsgDoc -> MsgDoc -> MsgDoc
<+> forall a. Pretty a => a -> MsgDoc
pretty ComponentId
cid2)
forall s a. ST s a -> UnifyM s a
liftST forall a b. (a -> b) -> a -> b
$ forall s a. Point s a -> Point s a -> ST s ()
UnionFind.union UnitIdU s
uid1_u UnitIdU s
uid2_u
forall (t :: * -> *) (f :: * -> *) a.
(Foldable t, Applicative f) =>
t (f a) -> f ()
F.sequenceA_ forall a b. (a -> b) -> a -> b
$ forall k a b c.
Ord k =>
(a -> b -> c) -> Map k a -> Map k b -> Map k c
Map.intersectionWith forall s. ModuleU s -> ModuleU s -> UnifyM s ()
unifyModule Map ModuleName (ModuleU s)
insts1 Map ModuleName (ModuleU s)
insts2
unifyModule :: ModuleU s -> ModuleU s -> UnifyM s ()
unifyModule :: forall s. ModuleU s -> ModuleU s -> UnifyM s ()
unifyModule ModuleU s
mod1_u ModuleU s
mod2_u
| ModuleU s
mod1_u forall a. Eq a => a -> a -> Bool
== ModuleU s
mod2_u = forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool
otherwise = do
ModuleU' s
mod1 <- forall s a. ST s a -> UnifyM s a
liftST forall a b. (a -> b) -> a -> b
$ forall s a. Point s a -> ST s a
UnionFind.find ModuleU s
mod1_u
ModuleU' s
mod2 <- forall s a. ST s a -> UnifyM s a
liftST forall a b. (a -> b) -> a -> b
$ forall s a. Point s a -> ST s a
UnionFind.find ModuleU s
mod2_u
case (ModuleU' s
mod1, ModuleU' s
mod2) of
(ModuleVarU ModuleName
_, ModuleU' s
_) -> forall s a. ST s a -> UnifyM s a
liftST forall a b. (a -> b) -> a -> b
$ forall s a. Point s a -> Point s a -> ST s ()
UnionFind.union ModuleU s
mod1_u ModuleU s
mod2_u
(ModuleU' s
_, ModuleVarU ModuleName
_) -> forall s a. ST s a -> UnifyM s a
liftST forall a b. (a -> b) -> a -> b
$ forall s a. Point s a -> Point s a -> ST s ()
UnionFind.union ModuleU s
mod2_u ModuleU s
mod1_u
(ModuleU UnitIdU s
uid1 ModuleName
mod_name1, ModuleU UnitIdU s
uid2 ModuleName
mod_name2) -> do
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (ModuleName
mod_name1 forall a. Eq a => a -> a -> Bool
/= ModuleName
mod_name2) forall a b. (a -> b) -> a -> b
$
forall s a. MsgDoc -> UnifyM s a
failWith forall a b. (a -> b) -> a -> b
$
MsgDoc -> Int -> MsgDoc -> MsgDoc
hang (String -> MsgDoc
text String
"Cannot match module names") Int
4 forall a b. (a -> b) -> a -> b
$
String -> MsgDoc
text String
" " MsgDoc -> MsgDoc -> MsgDoc
<+> forall a. Pretty a => a -> MsgDoc
pretty ModuleName
mod_name1 MsgDoc -> MsgDoc -> MsgDoc
$$
String -> MsgDoc
text String
"and" MsgDoc -> MsgDoc -> MsgDoc
<+> forall a. Pretty a => a -> MsgDoc
pretty ModuleName
mod_name2
forall s a. ST s a -> UnifyM s a
liftST forall a b. (a -> b) -> a -> b
$ forall s a. Point s a -> Point s a -> ST s ()
UnionFind.union ModuleU s
mod1_u ModuleU s
mod2_u
forall s. UnitIdU s -> UnitIdU s -> UnifyM s ()
unifyUnitId UnitIdU s
uid1 UnitIdU s
uid2