From e75396b81fd456345bc74ca6a9829201ce71f2fe Mon Sep 17 00:00:00 2001
From: Edsko de Vries <edsko@well-typed.com>
Date: Mon, 1 Jun 2015 10:26:54 +0100
Subject: [PATCH] Document addLinking

Addresses https://github.com/haskell/cabal/pull/2500#commitcomment-10455653
Addresses https://github.com/haskell/cabal/pull/2500#commitcomment-10797900
---
 .../Client/Dependency/Modular/Linking.hs      | 24 +++++++++++++------
 1 file changed, 17 insertions(+), 7 deletions(-)

diff --git a/cabal-install/Distribution/Client/Dependency/Modular/Linking.hs b/cabal-install/Distribution/Client/Dependency/Modular/Linking.hs
index 2f3d25b803..d0dc94f3c9 100644
--- a/cabal-install/Distribution/Client/Dependency/Modular/Linking.hs
+++ b/cabal-install/Distribution/Client/Dependency/Modular/Linking.hs
@@ -39,6 +39,21 @@ import Distribution.Client.ComponentDeps (Component)
 type RelatedGoals = Map (PN, I) [PP]
 type Linker       = Reader RelatedGoals
 
+-- | Introduce link nodes into tree tree
+--
+-- Linking is a traversal of the solver tree that adapts package choice nodes
+-- and adds the option to link wherever appropriate: Package goals are called
+-- "related" if they are for the same version of the same package (but have
+-- different prefixes). A link option is available in a package choice node
+-- whenever we can choose an instance that has already been chosen for a related
+-- goal at a higher position in the tree.
+--
+-- The code here proceeds by maintaining a finite map recording choices that
+-- have been made at higher positions in the tree. For each pair of package name
+-- and instance, it stores the prefixes at which we have made a choice for this
+-- package instance. Whenever we make a choice, we extend the map. Whenever we
+-- find a choice, we look into the map in order to find out what link options we
+-- have to add.
 addLinking :: Tree QGoalReasonChain -> Tree QGoalReasonChain
 addLinking = (`runReader` M.empty) .  cata go
   where
@@ -50,13 +65,8 @@ addLinking = (`runReader` M.empty) .  cata go
       cs' <- T.sequence $ P.mapWithKey (goP qpn) cs
       let newCs = concatMap (linkChoices env qpn) (P.toList cs')
       return $ PChoice qpn gr (cs' `P.union` P.fromList newCs)
-
-    -- For all other nodes we just recurse
-    go (FChoiceF qfn gr t m cs)       = FChoice qfn gr t m  <$> T.sequence cs
-    go (SChoiceF qsn gr t   cs)       = SChoice qsn gr t    <$> T.sequence cs
-    go (GoalChoiceF         cs)       = GoalChoice          <$> T.sequence cs
-    go (DoneF revDepMap)              = return $ Done revDepMap
-    go (FailF conflictSet failReason) = return $ Fail conflictSet failReason
+    go _otherwise =
+      innM _otherwise
 
     -- Recurse underneath package choices. Here we just need to make sure
     -- that we record the package choice so that it is available below
-- 
GitLab