diff --git a/cabal-install/Distribution/Client/Config.hs b/cabal-install/Distribution/Client/Config.hs
index 2768c13f3f82cb5200ddab0ef4f5ec0833d2a72e..39f309172b6e77cc62f1082d81d1e337a86b2eb4 100644
--- a/cabal-install/Distribution/Client/Config.hs
+++ b/cabal-install/Distribution/Client/Config.hs
@@ -44,6 +44,8 @@ import Distribution.Client.Types
          ( RemoteRepo(..), Username(..), Password(..), emptyRemoteRepo )
 import Distribution.Client.BuildReports.Types
          ( ReportLevel(..) )
+import Distribution.Client.Dependency.Types
+         ( ConstraintSource(..) )
 import Distribution.Client.Setup
          ( GlobalFlags(..), globalCommand, defaultGlobalFlags
          , ConfigExFlags(..), configureExOptions, defaultConfigExFlags
@@ -676,7 +678,7 @@ configFieldDescriptions =
        ]
 
   ++ toSavedConfig liftConfigExFlag
-       (configureExOptions ParseArgs)
+       (configureExOptions ParseArgs ConstraintSourceMainConfig)
        [] []
 
   ++ toSavedConfig liftInstallFlag
diff --git a/cabal-install/Distribution/Client/Configure.hs b/cabal-install/Distribution/Client/Configure.hs
index 8c098220d63a45fe684b7cefa26930e0c0291be5..b80a2755ccd1f002c731a96c83b794b991f3c987 100644
--- a/cabal-install/Distribution/Client/Configure.hs
+++ b/cabal-install/Distribution/Client/Configure.hs
@@ -18,7 +18,8 @@ module Distribution.Client.Configure (
   ) where
 
 import Distribution.Client.Dependency
-import Distribution.Client.Dependency.Types (AllowNewer(..), isAllowNewer)
+import Distribution.Client.Dependency.Types
+         ( AllowNewer(..), isAllowNewer, LabeledPackageConstraint(..) )
 import qualified Distribution.Client.InstallPlan as InstallPlan
 import Distribution.Client.InstallPlan (InstallPlan)
 import Distribution.Client.IndexUtils as IndexUtils
@@ -262,19 +263,22 @@ planLocalPackage verbosity comp platform configFlags configExFlags
             -- version constraints from the config file or command line
             -- TODO: should warn or error on constraints that are not on direct
             -- deps or flag constraints not on the package in question.
-            (map userToPackageConstraint (configExConstraints configExFlags))
+            [ LabeledPackageConstraint (userToPackageConstraint uc) (Just src)
+            | (uc, src) <- configExConstraints configExFlags ]
 
         . addConstraints
             -- package flags from the config file or command line
-            [ PackageConstraintFlags (packageName pkg)
-                                     (configConfigurationsFlags configFlags) ]
+            [ let pc = PackageConstraintFlags (packageName pkg)
+                       (configConfigurationsFlags configFlags)
+              in LabeledPackageConstraint pc Nothing ]
 
         . addConstraints
             -- '--enable-tests' and '--enable-benchmarks' constraints from
             -- command line
-            [ PackageConstraintStanzas (packageName pkg) $
-                [ TestStanzas  | testsEnabled ] ++
-                [ BenchStanzas | benchmarksEnabled ]
+            [ let pc = PackageConstraintStanzas (packageName pkg) $
+                       [ TestStanzas  | testsEnabled ] ++
+                       [ BenchStanzas | benchmarksEnabled ]
+              in LabeledPackageConstraint pc Nothing
             ]
 
         $ standardInstallPolicy
diff --git a/cabal-install/Distribution/Client/Dependency.hs b/cabal-install/Distribution/Client/Dependency.hs
index e34be5e16f0e2ca63688dbea47c47232984a0614..ceb2123cb341ee32ddfc5bf515231b0fb57d83ed 100644
--- a/cabal-install/Distribution/Client/Dependency.hs
+++ b/cabal-install/Distribution/Client/Dependency.hs
@@ -74,6 +74,8 @@ import Distribution.Client.Types
 import Distribution.Client.Dependency.Types
          ( PreSolver(..), Solver(..), DependencyResolver, ResolverPackage(..)
          , PackageConstraint(..), debugPackageConstraint
+         , LabeledPackageConstraint(..), unlabelPackageConstraint
+         , ConstraintSource(..), debugConstraintSource
          , AllowNewer(..), PackagePreferences(..), InstalledPreference(..)
          , PackagesPreferenceDefault(..)
          , Progress(..), foldProgress )
@@ -134,7 +136,7 @@ import Control.Exception
 --
 data DepResolverParams = DepResolverParams {
        depResolverTargets           :: [PackageName],
-       depResolverConstraints       :: [PackageConstraint],
+       depResolverConstraints       :: [LabeledPackageConstraint],
        depResolverPreferences       :: [PackagePreference],
        depResolverPreferenceDefault :: PackagesPreferenceDefault,
        depResolverInstalledPkgIndex :: InstalledPackageIndex,
@@ -151,12 +153,16 @@ debugDepResolverParams :: DepResolverParams -> String
 debugDepResolverParams p =
      "targets: " ++ intercalate ", " (map display (depResolverTargets p))
   ++ "\nconstraints: "
-  ++   concatMap (("\n  " ++) . debugPackageConstraint)
+  ++   concatMap (("\n  " ++) . debugLabeledConstraint)
        (depResolverConstraints p)
   ++ "\npreferences: "
   ++   concatMap (("\n  " ++) . debugPackagePreference)
        (depResolverPreferences p)
   ++ "\nstrategy: " ++ show (depResolverPreferenceDefault p)
+  where
+    debugLabeledConstraint (LabeledPackageConstraint pc src) =
+        debugPackageConstraint pc ++ maybe "" showSrc src
+    showSrc src = " (" ++ debugConstraintSource src ++ ")"
 
 -- | A package selection preference for a particular package.
 --
@@ -207,7 +213,7 @@ addTargets extraTargets params =
       depResolverTargets = extraTargets ++ depResolverTargets params
     }
 
-addConstraints :: [PackageConstraint]
+addConstraints :: [LabeledPackageConstraint]
                -> DepResolverParams -> DepResolverParams
 addConstraints extraConstraints params =
     params {
@@ -273,7 +279,9 @@ dontUpgradeNonUpgradeablePackages params =
     addConstraints extraConstraints params
   where
     extraConstraints =
-      [ PackageConstraintInstalled pkgname
+      [ LabeledPackageConstraint
+        (PackageConstraintInstalled pkgname)
+        (Just ConstraintSourceNonUpgradeablePackage)
       | all (/=PackageName "base") (depResolverTargets params)
       , pkgname <- map PackageName [ "base", "ghc-prim", "integer-gmp"
                                    , "integer-simple" ]
@@ -474,8 +482,11 @@ applySandboxInstallPolicy
         (thisVersion (packageVersion pkg)) | pkg <- otherDeps ]
 
   . addConstraints
-      [ PackageConstraintVersion (packageName pkg)
-        (thisVersion (packageVersion pkg)) | pkg <- modifiedDeps ]
+      [ let pc = PackageConstraintVersion (packageName pkg)
+                 (thisVersion (packageVersion pkg))
+        in LabeledPackageConstraint pc
+           (Just ConstraintSourceModifiedAddSourceDep)
+      | pkg <- modifiedDeps ]
 
   . addTargets [ packageName pkg | pkg <- modifiedDeps ]
 
@@ -814,8 +825,9 @@ resolveWithoutDependencies (DepResolverParams targets constraints
     packageConstraints pkgname =
       Map.findWithDefault anyVersion pkgname packageVersionConstraintMap
     packageVersionConstraintMap =
-      Map.fromList [ (name, range)
-                   | PackageConstraintVersion name range <- constraints ]
+      let pcs = map unlabelPackageConstraint constraints
+      in Map.fromList [ (name, range)
+                      | PackageConstraintVersion name range <- pcs ]
 
     packagePreferences :: PackageName -> PackagePreferences
     packagePreferences = interpretPackagesPreference
diff --git a/cabal-install/Distribution/Client/Dependency/Modular.hs b/cabal-install/Distribution/Client/Dependency/Modular.hs
index b2be4fc2fe1429574ce07e7610a3b9c69726ac5b..60fde9aed74f9d5f46fca64bad4d04b5d3481aaa 100644
--- a/cabal-install/Distribution/Client/Dependency/Modular.hs
+++ b/cabal-install/Distribution/Client/Dependency/Modular.hs
@@ -26,7 +26,8 @@ import Distribution.Client.Dependency.Modular.Package
 import Distribution.Client.Dependency.Modular.Solver
          ( SolverConfig(..), solve )
 import Distribution.Client.Dependency.Types
-         ( DependencyResolver, ResolverPackage, PackageConstraint(..) )
+         ( DependencyResolver, ResolverPackage
+         , PackageConstraint(..), unlabelPackageConstraint )
 import Distribution.System
          ( Platform(..) )
 
@@ -41,7 +42,9 @@ modularResolver sc (Platform arch os) cinfo iidx sidx pprefs pcs pns =
       -- Indices have to be converted into solver-specific uniform index.
       idx    = convPIs os arch cinfo (shadowPkgs sc) (strongFlags sc) iidx sidx
       -- Constraints have to be converted into a finite map indexed by PN.
-      gcs    = M.fromListWith (++) (map (\ pc -> (pcName pc, [pc])) pcs)
+      gcs    = M.fromListWith (++) (map pair pcs)
+        where
+          pair lpc = (pcName $ unlabelPackageConstraint lpc, [lpc])
 
       -- Results have to be converted into an install plan.
       postprocess :: Assignment -> RevDepMap -> [ResolverPackage]
diff --git a/cabal-install/Distribution/Client/Dependency/Modular/Message.hs b/cabal-install/Distribution/Client/Dependency/Modular/Message.hs
index cf5dcd7a3d49971051156f6a5a551a0b985b6563..df006aa10ea53546ae8bcd9ceb74412850ef2db2 100644
--- a/cabal-install/Distribution/Client/Dependency/Modular/Message.hs
+++ b/cabal-install/Distribution/Client/Dependency/Modular/Message.hs
@@ -1,4 +1,7 @@
-module Distribution.Client.Dependency.Modular.Message where
+module Distribution.Client.Dependency.Modular.Message (
+    Message(..),
+    showMessages
+  ) where
 
 import qualified Data.List as L
 import Prelude hiding (pi)
@@ -9,6 +12,8 @@ import Distribution.Client.Dependency.Modular.Dependency
 import Distribution.Client.Dependency.Modular.Flag
 import Distribution.Client.Dependency.Modular.Package
 import Distribution.Client.Dependency.Modular.Tree
+import Distribution.Client.Dependency.Types
+         ( ConstraintSource(..), debugConstraintSource )
 
 data Message =
     Enter           -- ^ increase indentation level
@@ -86,24 +91,28 @@ showGR (FDependency qfn b) = " (dependency of " ++ showQFNBool qfn b    ++ ")"
 showGR (SDependency qsn)   = " (dependency of " ++ showQSNBool qsn True ++ ")"
 
 showFR :: ConflictSet QPN -> FailReason -> String
-showFR _ InconsistentInitialConstraints = " (inconsistent initial constraints)"
-showFR _ (Conflicting ds)               = " (conflict: " ++ L.intercalate ", " (map showDep ds) ++ ")"
-showFR _ CannotInstall                  = " (only already installed instances can be used)"
-showFR _ CannotReinstall                = " (avoiding to reinstall a package with same version but new dependencies)"
-showFR _ Shadowed                       = " (shadowed by another installed package with same version)"
-showFR _ Broken                         = " (package is broken)"
-showFR _ (GlobalConstraintVersion vr)   = " (global constraint requires " ++ display vr ++ ")"
-showFR _ GlobalConstraintInstalled      = " (global constraint requires installed instance)"
-showFR _ GlobalConstraintSource         = " (global constraint requires source instance)"
-showFR _ GlobalConstraintFlag           = " (global constraint requires opposite flag selection)"
-showFR _ ManualFlag                     = " (manual flag can only be changed explicitly)"
-showFR _ (BuildFailureNotInIndex pn)    = " (unknown package: " ++ display pn ++ ")"
-showFR c Backjump                       = " (backjumping, conflict set: " ++ showCS c ++ ")"
-showFR _ MultipleInstances              = " (multiple instances)"
-showFR c (DependenciesNotLinked msg)    = " (dependencies not linked: " ++ msg ++ "; conflict set: " ++ showCS c ++ ")"
+showFR _ InconsistentInitialConstraints   = " (inconsistent initial constraints)"
+showFR _ (Conflicting ds)                 = " (conflict: " ++ L.intercalate ", " (map showDep ds) ++ ")"
+showFR _ CannotInstall                    = " (only already installed instances can be used)"
+showFR _ CannotReinstall                  = " (avoiding to reinstall a package with same version but new dependencies)"
+showFR _ Shadowed                         = " (shadowed by another installed package with same version)"
+showFR _ Broken                           = " (package is broken)"
+showFR _ (GlobalConstraintVersion vr src) = " (" ++ showConstraintSource src ++ " requires " ++ display vr ++ ")"
+showFR _ (GlobalConstraintInstalled src)  = " (" ++ showConstraintSource src ++ " requires installed instance)"
+showFR _ (GlobalConstraintSource src)     = " (" ++ showConstraintSource src ++ " requires source instance)"
+showFR _ (GlobalConstraintFlag src)       = " (" ++ showConstraintSource src ++ " requires opposite flag selection)"
+showFR _ ManualFlag                       = " (manual flag can only be changed explicitly)"
+showFR _ (BuildFailureNotInIndex pn)      = " (unknown package: " ++ display pn ++ ")"
+showFR c Backjump                         = " (backjumping, conflict set: " ++ showCS c ++ ")"
+showFR _ MultipleInstances                = " (multiple instances)"
+showFR c (DependenciesNotLinked msg)      = " (dependencies not linked: " ++ msg ++ "; conflict set: " ++ showCS c ++ ")"
 -- The following are internal failures. They should not occur. In the
 -- interest of not crashing unnecessarily, we still just print an error
 -- message though.
-showFR _ (MalformedFlagChoice qfn)      = " (INTERNAL ERROR: MALFORMED FLAG CHOICE: " ++ showQFN qfn ++ ")"
-showFR _ (MalformedStanzaChoice qsn)    = " (INTERNAL ERROR: MALFORMED STANZA CHOICE: " ++ showQSN qsn ++ ")"
-showFR _ EmptyGoalChoice                = " (INTERNAL ERROR: EMPTY GOAL CHOICE)"
+showFR _ (MalformedFlagChoice qfn)        = " (INTERNAL ERROR: MALFORMED FLAG CHOICE: " ++ showQFN qfn ++ ")"
+showFR _ (MalformedStanzaChoice qsn)      = " (INTERNAL ERROR: MALFORMED STANZA CHOICE: " ++ showQSN qsn ++ ")"
+showFR _ EmptyGoalChoice                  = " (INTERNAL ERROR: EMPTY GOAL CHOICE)"
+
+showConstraintSource :: Maybe ConstraintSource -> String
+showConstraintSource Nothing    = "global constraint"
+showConstraintSource (Just src) = "global constraint from " ++ debugConstraintSource src
diff --git a/cabal-install/Distribution/Client/Dependency/Modular/Preference.hs b/cabal-install/Distribution/Client/Dependency/Modular/Preference.hs
index 6b6ca343df6330be4f962487acc32fee4d3fb343..92970bc4f7e25760a3a3e6323923d02f8ac1be51 100644
--- a/cabal-install/Distribution/Client/Dependency/Modular/Preference.hs
+++ b/cabal-install/Distribution/Client/Dependency/Modular/Preference.hs
@@ -17,7 +17,8 @@ import Data.Map (Map)
 import Data.Traversable (sequence)
 
 import Distribution.Client.Dependency.Types
-  ( PackageConstraint(..), PackagePreferences(..), InstalledPreference(..) )
+  ( PackageConstraint(..), LabeledPackageConstraint(..)
+  , PackagePreferences(..), InstalledPreference(..) )
 import Distribution.Client.Types
   ( OptionalStanza(..) )
 
@@ -95,44 +96,66 @@ preferLatestOrdering (I v1 _) (I v2 _) = compare v1 v2
 -- given instance for a P-node. Translates the constraint into a
 -- tree-transformer that either leaves the subtree untouched, or replaces it
 -- with an appropriate failure node.
-processPackageConstraintP :: ConflictSet QPN -> I -> PackageConstraint -> Tree a -> Tree a
-processPackageConstraintP c (I v _) (PackageConstraintVersion _ vr) r
-  | checkVR vr v  = r
-  | otherwise     = Fail c (GlobalConstraintVersion vr)
-processPackageConstraintP c i       (PackageConstraintInstalled _)  r
-  | instI i       = r
-  | otherwise     = Fail c GlobalConstraintInstalled
-processPackageConstraintP c i       (PackageConstraintSource    _)  r
-  | not (instI i) = r
-  | otherwise     = Fail c GlobalConstraintSource
-processPackageConstraintP _ _       _                               r = r
+processPackageConstraintP :: ConflictSet QPN
+                          -> I
+                          -> LabeledPackageConstraint
+                          -> Tree a
+                          -> Tree a
+processPackageConstraintP c i (LabeledPackageConstraint pc src) r =
+    case (i, pc) of
+      (I v _, PackageConstraintVersion _ vr)
+          | checkVR vr v  -> r
+          | otherwise     -> Fail c (GlobalConstraintVersion vr src)
+      (_,     PackageConstraintInstalled _)
+          | instI i       -> r
+          | otherwise     -> Fail c (GlobalConstraintInstalled src)
+      (_,     PackageConstraintSource    _)
+          | not (instI i) -> r
+          | otherwise     -> Fail c (GlobalConstraintSource src)
+      (_,     _) -> r
 
 -- | Helper function that tries to enforce a single package constraint on a
 -- given flag setting for an F-node. Translates the constraint into a
 -- tree-transformer that either leaves the subtree untouched, or replaces it
 -- with an appropriate failure node.
-processPackageConstraintF :: Flag -> ConflictSet QPN -> Bool -> PackageConstraint -> Tree a -> Tree a
-processPackageConstraintF f c b' (PackageConstraintFlags _ fa) r =
-  case L.lookup f fa of
-    Nothing            -> r
-    Just b | b == b'   -> r
-           | otherwise -> Fail c GlobalConstraintFlag
-processPackageConstraintF _ _ _  _                             r = r
+processPackageConstraintF :: Flag
+                          -> ConflictSet QPN
+                          -> Bool
+                          -> LabeledPackageConstraint
+                          -> Tree a
+                          -> Tree a
+processPackageConstraintF f c b' (LabeledPackageConstraint pc src) r =
+    case pc of
+      PackageConstraintFlags _ fa ->
+          case L.lookup f fa of
+            Nothing            -> r
+            Just b | b == b'   -> r
+                   | otherwise -> Fail c (GlobalConstraintFlag src)
+      _                           -> r
 
 -- | Helper function that tries to enforce a single package constraint on a
 -- given flag setting for an F-node. Translates the constraint into a
 -- tree-transformer that either leaves the subtree untouched, or replaces it
 -- with an appropriate failure node.
-processPackageConstraintS :: OptionalStanza -> ConflictSet QPN -> Bool -> PackageConstraint -> Tree a -> Tree a
-processPackageConstraintS s c b' (PackageConstraintStanzas _ ss) r =
-  if not b' && s `elem` ss then Fail c GlobalConstraintFlag
-                           else r
-processPackageConstraintS _ _ _  _                             r = r
+processPackageConstraintS :: OptionalStanza
+                          -> ConflictSet QPN
+                          -> Bool
+                          -> LabeledPackageConstraint
+                          -> Tree a
+                          -> Tree a
+processPackageConstraintS s c b' (LabeledPackageConstraint pc src) r =
+    case pc of
+      PackageConstraintStanzas _ ss ->
+          if not b' && s `elem` ss then Fail c (GlobalConstraintFlag src)
+                                   else r
+      _                             -> r
 
 -- | Traversal that tries to establish various kinds of user constraints. Works
 -- by selectively disabling choices that have been ruled out by global user
 -- constraints.
-enforcePackageConstraints :: M.Map PN [PackageConstraint] -> Tree QGoalReasonChain -> Tree QGoalReasonChain
+enforcePackageConstraints :: M.Map PN [LabeledPackageConstraint]
+                          -> Tree QGoalReasonChain
+                          -> Tree QGoalReasonChain
 enforcePackageConstraints pcs = trav go
   where
     go (PChoiceF qpn@(Q _ pn)               gr      ts) =
@@ -169,8 +192,8 @@ enforceManualFlags = trav go
             ([], y : ys) -> P.fromList (y : L.map (\ (b, _) -> (b, Fail c ManualFlag)) ys)
             _            -> ts -- something has been manually selected, leave things alone
       where
-        isDisabled (_, Fail _ GlobalConstraintFlag) = True
-        isDisabled _                                = False
+        isDisabled (_, Fail _ (GlobalConstraintFlag _)) = True
+        isDisabled _                                    = False
     go x                                                   = x
 
 -- | Prefer installed packages over non-installed packages, generally.
diff --git a/cabal-install/Distribution/Client/Dependency/Modular/Solver.hs b/cabal-install/Distribution/Client/Dependency/Modular/Solver.hs
index 4e489a44beea27c66be0387a8ad894c47e06ab6d..af5901f62816a098756bd1940ddec4ea7a0be075 100644
--- a/cabal-install/Distribution/Client/Dependency/Modular/Solver.hs
+++ b/cabal-install/Distribution/Client/Dependency/Modular/Solver.hs
@@ -26,11 +26,11 @@ data SolverConfig = SolverConfig {
   maxBackjumps          :: Maybe Int
 }
 
-solve :: SolverConfig ->   -- solver parameters
-         Index ->          -- all available packages as an index
-         (PN -> PackagePreferences) -> -- preferences
-         Map PN [PackageConstraint] -> -- global constraints
-         [PN] ->                       -- global goals
+solve :: SolverConfig ->          -- solver parameters
+         Index ->                 -- all available packages as an index
+         (PN -> PackagePreferences) ->        -- preferences
+         Map PN [LabeledPackageConstraint] -> -- global constraints
+         [PN] ->                              -- global goals
          Log Message (Assignment, RevDepMap)
 solve sc idx userPrefs userConstraints userGoals =
   explorePhase     $
diff --git a/cabal-install/Distribution/Client/Dependency/Modular/Tree.hs b/cabal-install/Distribution/Client/Dependency/Modular/Tree.hs
index 01ba37a67837514a57a5c356388f8f8f10fb00f7..ac9766b43cc02d6217fdbcfe315001d28e2e74cb 100644
--- a/cabal-install/Distribution/Client/Dependency/Modular/Tree.hs
+++ b/cabal-install/Distribution/Client/Dependency/Modular/Tree.hs
@@ -11,6 +11,7 @@ import Distribution.Client.Dependency.Modular.Flag
 import Distribution.Client.Dependency.Modular.Package
 import Distribution.Client.Dependency.Modular.PSQ as P
 import Distribution.Client.Dependency.Modular.Version
+import Distribution.Client.Dependency.Types ( ConstraintSource(..) )
 
 -- | Type of the search tree. Inlining the choice nodes for now.
 data Tree a =
@@ -55,10 +56,10 @@ data FailReason = InconsistentInitialConstraints
                 | CannotReinstall
                 | Shadowed
                 | Broken
-                | GlobalConstraintVersion VR
-                | GlobalConstraintInstalled
-                | GlobalConstraintSource
-                | GlobalConstraintFlag
+                | GlobalConstraintVersion VR (Maybe ConstraintSource)
+                | GlobalConstraintInstalled (Maybe ConstraintSource)
+                | GlobalConstraintSource (Maybe ConstraintSource)
+                | GlobalConstraintFlag (Maybe ConstraintSource)
                 | ManualFlag
                 | BuildFailureNotInIndex PN
                 | MalformedFlagChoice QFN
diff --git a/cabal-install/Distribution/Client/Dependency/TopDown.hs b/cabal-install/Distribution/Client/Dependency/TopDown.hs
index 32a53b130ab1b15792aae496533a12c442c57f52..52f8fa5822c7d4988f0d31b911027e1795f87447 100644
--- a/cabal-install/Distribution/Client/Dependency/TopDown.hs
+++ b/cabal-install/Distribution/Client/Dependency/TopDown.hs
@@ -23,7 +23,8 @@ import Distribution.Client.Types
          ( SourcePackage(..), ConfiguredPackage(..)
          , enableStanzas, ConfiguredId(..), fakeInstalledPackageId )
 import Distribution.Client.Dependency.Types
-         ( DependencyResolver, ResolverPackage(..), PackageConstraint(..)
+         ( DependencyResolver, ResolverPackage(..)
+         , PackageConstraint(..), unlabelPackageConstraint
          , PackagePreferences(..), InstalledPreference(..)
          , Progress(..), foldProgress )
 
@@ -254,7 +255,8 @@ topDownResolver platform cinfo installedPkgIndex sourcePkgIndex
                     platform cinfo
                     (convertInstalledPackageIndex installedPkgIndex)
                     sourcePkgIndex
-                    preferences constraints
+                    preferences
+                    (map unlabelPackageConstraint constraints)
                     targets
   where
     mapMessages :: Progress Log Failure a -> Progress String String a
diff --git a/cabal-install/Distribution/Client/Dependency/Types.hs b/cabal-install/Distribution/Client/Dependency/Types.hs
index 87dde8c903d13f6208c9d0d7477efddb78c9c0b3..6b765f2f8fd6a0de9d3c11e644495a1077035592 100644
--- a/cabal-install/Distribution/Client/Dependency/Types.hs
+++ b/cabal-install/Distribution/Client/Dependency/Types.hs
@@ -27,6 +27,11 @@ module Distribution.Client.Dependency.Types (
 
     Progress(..),
     foldProgress,
+
+    LabeledPackageConstraint(..),
+    ConstraintSource(..),
+    unlabelPackageConstraint,
+    debugConstraintSource
   ) where
 
 #if !MIN_VERSION_base(4,8,0)
@@ -105,7 +110,7 @@ type DependencyResolver = Platform
                        -> InstalledPackageIndex
                        ->          PackageIndex.PackageIndex SourcePackage
                        -> (PackageName -> PackagePreferences)
-                       -> [PackageConstraint]
+                       -> [LabeledPackageConstraint]
                        -> [PackageName]
                        -> Progress String String [ResolverPackage]
 
@@ -250,3 +255,34 @@ instance Applicative (Progress step fail) where
 instance Monoid fail => Alternative (Progress step fail) where
   empty   = Fail mempty
   p <|> q = foldProgress Step (const q) Done p
+
+-- | 'PackageConstraint' labeled with its source. The source is optional
+-- because not all constraints are tracked currently.
+data LabeledPackageConstraint
+   = LabeledPackageConstraint PackageConstraint (Maybe ConstraintSource)
+
+unlabelPackageConstraint :: LabeledPackageConstraint -> PackageConstraint
+unlabelPackageConstraint (LabeledPackageConstraint pc _) = pc
+
+-- | Source of a 'PackageConstraint'.
+data ConstraintSource
+   = ConstraintSourceMainConfig
+   | ConstraintSourceSandboxConfig
+   | ConstraintSourceUserConfig
+   | ConstraintSourceCommandlineFlag
+   | ConstraintSourceUserTarget
+   | ConstraintSourceNonUpgradeablePackage
+   | ConstraintSourceModifiedAddSourceDep
+  deriving (Eq, Show)
+
+-- | Description of a 'ConstraintSource'.
+debugConstraintSource :: ConstraintSource -> String
+debugConstraintSource ConstraintSourceMainConfig = "main config file"
+debugConstraintSource ConstraintSourceSandboxConfig = "sandbox config file"
+debugConstraintSource ConstraintSourceUserConfig = "cabal.config"
+debugConstraintSource ConstraintSourceCommandlineFlag = "command line flag"
+debugConstraintSource ConstraintSourceUserTarget = "user target"
+debugConstraintSource ConstraintSourceNonUpgradeablePackage =
+    "non-upgradeable package"
+debugConstraintSource ConstraintSourceModifiedAddSourceDep =
+    "modified add-source dependency"
diff --git a/cabal-install/Distribution/Client/Freeze.hs b/cabal-install/Distribution/Client/Freeze.hs
index 197490a9823793adc283076d145fe760b08162ca..e850761f9e16eab51cfc6e4c067caabf67bfb18a 100644
--- a/cabal-install/Distribution/Client/Freeze.hs
+++ b/cabal-install/Distribution/Client/Freeze.hs
@@ -20,6 +20,8 @@ import Distribution.Client.Config ( SavedConfig(..) )
 import Distribution.Client.Types
 import Distribution.Client.Targets
 import Distribution.Client.Dependency
+import Distribution.Client.Dependency.Types
+         ( ConstraintSource(..), LabeledPackageConstraint(..) )
 import Distribution.Client.IndexUtils as IndexUtils
          ( getSourcePackages, getInstalledPackages )
 import Distribution.Client.InstallPlan
@@ -162,7 +164,9 @@ planPackages verbosity comp platform mSandboxPkgInfo freezeFlags
       . setStrongFlags strongFlags
 
       . addConstraints
-          [ PackageConstraintStanzas (pkgSpecifierTarget pkgSpecifier) stanzas
+          [ let pkg = pkgSpecifierTarget pkgSpecifier
+                pc = PackageConstraintStanzas pkg stanzas
+            in LabeledPackageConstraint pc Nothing
           | pkgSpecifier <- pkgSpecifiers ]
 
       . maybe id applySandboxInstallPolicy mSandboxPkgInfo
@@ -218,14 +222,15 @@ freezePackages verbosity pkgs = do
     addFrozenConstraints config =
         config {
             savedConfigureExFlags = (savedConfigureExFlags config) {
-                configExConstraints = constraints pkgs
+                configExConstraints = map constraint pkgs
             }
         }
-    constraints = map $ pkgIdToConstraint . packageId
+    constraint pkg =
+        (pkgIdToConstraint $ packageId pkg, ConstraintSourceUserConfig)
       where
-        pkgIdToConstraint pkg =
-            UserConstraintVersion (packageName pkg)
-                                  (thisVersion $ packageVersion pkg)
+        pkgIdToConstraint pkgId =
+            UserConstraintVersion (packageName pkgId)
+                                  (thisVersion $ packageVersion pkgId)
     createPkgEnv config = mempty { pkgEnvSavedConfig = config }
     showPkgEnv = BS.Char8.pack . showPackageEnvironment
 
diff --git a/cabal-install/Distribution/Client/Install.hs b/cabal-install/Distribution/Client/Install.hs
index 839b7f4656ee1b93ca12ac4b3e0125ce35883b34..66f4622a826af973094f8b6c8e62711feeba8339 100644
--- a/cabal-install/Distribution/Client/Install.hs
+++ b/cabal-install/Distribution/Client/Install.hs
@@ -70,7 +70,7 @@ import Distribution.Client.Configure
          ( chooseCabalVersion, configureSetupScript )
 import Distribution.Client.Dependency
 import Distribution.Client.Dependency.Types
-         ( Solver(..) )
+         ( Solver(..), LabeledPackageConstraint(..) )
 import Distribution.Client.FetchUtils
 import Distribution.Client.HttpUtils
          ( configureTransport, HttpTransport (..) )
@@ -372,18 +372,23 @@ planPackages comp platform mSandboxPkgInfo solver
 
       . addConstraints
           -- version constraints from the config file or command line
-            (map userToPackageConstraint (configExConstraints configExFlags))
+            [ LabeledPackageConstraint (userToPackageConstraint pc) (Just src)
+            | (pc, src) <- configExConstraints configExFlags ]
 
       . addConstraints
           --FIXME: this just applies all flags to all targets which
           -- is silly. We should check if the flags are appropriate
-          [ PackageConstraintFlags (pkgSpecifierTarget pkgSpecifier) flags
+          [ let pc = PackageConstraintFlags
+                     (pkgSpecifierTarget pkgSpecifier) flags
+            in LabeledPackageConstraint pc Nothing
           | let flags = configConfigurationsFlags configFlags
           , not (null flags)
           , pkgSpecifier <- pkgSpecifiers ]
 
       . addConstraints
-          [ PackageConstraintStanzas (pkgSpecifierTarget pkgSpecifier) stanzas
+          [ let pc = PackageConstraintStanzas
+                     (pkgSpecifierTarget pkgSpecifier) stanzas
+            in LabeledPackageConstraint pc Nothing
           | pkgSpecifier <- pkgSpecifiers ]
 
       . maybe id applySandboxInstallPolicy mSandboxPkgInfo
diff --git a/cabal-install/Distribution/Client/Sandbox/PackageEnvironment.hs b/cabal-install/Distribution/Client/Sandbox/PackageEnvironment.hs
index dffa98aaf888bf6a02edaa72f87d2e40d49e8d7d..7e9061915ad4261251c969d940f79f9c03ecbec7 100644
--- a/cabal-install/Distribution/Client/Sandbox/PackageEnvironment.hs
+++ b/cabal-install/Distribution/Client/Sandbox/PackageEnvironment.hs
@@ -36,6 +36,7 @@ import Distribution.Client.Config      ( SavedConfig(..), commentSavedConfig
                                        , installDirsFields, withProgramsFields
                                        , withProgramOptionsFields
                                        , defaultCompiler )
+import Distribution.Client.Dependency.Types ( ConstraintSource (..) )
 import Distribution.Client.ParseUtils  ( parseFields, ppFields, ppSection )
 import Distribution.Client.Setup       ( GlobalFlags(..), ConfigExFlags(..)
                                        , InstallFlags(..)
@@ -284,7 +285,7 @@ inheritedPackageEnvironment verbosity pkgEnv = do
 userPackageEnvironment :: Verbosity -> FilePath -> IO PackageEnvironment
 userPackageEnvironment verbosity pkgEnvDir = do
   let path = pkgEnvDir </> userPackageEnvironmentFile
-  minp <- readPackageEnvironmentFile mempty path
+  minp <- readPackageEnvironmentFile ConstraintSourceUserConfig mempty path
   case minp of
     Nothing -> return mempty
     Just (ParseOk warns parseResult) -> do
@@ -327,7 +328,8 @@ tryLoadSandboxPackageEnvironmentFile :: Verbosity -> FilePath -> (Flag FilePath)
                                         -> IO (FilePath, PackageEnvironment)
 tryLoadSandboxPackageEnvironmentFile verbosity pkgEnvFile configFileFlag = do
   let pkgEnvDir = takeDirectory pkgEnvFile
-  minp   <- readPackageEnvironmentFile mempty pkgEnvFile
+  minp   <- readPackageEnvironmentFile
+            ConstraintSourceSandboxConfig mempty pkgEnvFile
   pkgEnv <- handleParseResult verbosity pkgEnvFile minp
 
   -- Get the saved sandbox directory.
@@ -401,15 +403,15 @@ createPackageEnvironmentFile verbosity sandboxDir pkgEnvFile incComments
   writePackageEnvironmentFile pkgEnvFile incComments commentPkgEnv initialPkgEnv
 
 -- | Descriptions of all fields in the package environment file.
-pkgEnvFieldDescrs :: [FieldDescr PackageEnvironment]
-pkgEnvFieldDescrs = [
+pkgEnvFieldDescrs :: ConstraintSource -> [FieldDescr PackageEnvironment]
+pkgEnvFieldDescrs src = [
   simpleField "inherit"
     (fromFlagOrDefault Disp.empty . fmap Disp.text) (optional parseFilePathQ)
     pkgEnvInherit (\v pkgEnv -> pkgEnv { pkgEnvInherit = v })
 
     -- FIXME: Should we make these fields part of ~/.cabal/config ?
   , commaNewLineListField "constraints"
-    Text.disp Text.parse
+    (Text.disp . fst) ((\pc -> (pc, src)) `fmap` Text.parse)
     (configExConstraints . savedConfigureExFlags . pkgEnvSavedConfig)
     (\v pkgEnv -> updateConfigureExFlags pkgEnv
                   (\flags -> flags { configExConstraints = v }))
@@ -446,11 +448,11 @@ pkgEnvFieldDescrs = [
       }
 
 -- | Read the package environment file.
-readPackageEnvironmentFile :: PackageEnvironment -> FilePath
+readPackageEnvironmentFile :: ConstraintSource -> PackageEnvironment -> FilePath
                               -> IO (Maybe (ParseResult PackageEnvironment))
-readPackageEnvironmentFile initial file =
+readPackageEnvironmentFile src initial file =
   handleNotExists $
-  fmap (Just . parsePackageEnvironment initial) (readFile file)
+  fmap (Just . parsePackageEnvironment src initial) (readFile file)
   where
     handleNotExists action = catchIO action $ \ioe ->
       if isDoesNotExistError ioe
@@ -458,9 +460,9 @@ readPackageEnvironmentFile initial file =
         else ioError ioe
 
 -- | Parse the package environment file.
-parsePackageEnvironment :: PackageEnvironment -> String
+parsePackageEnvironment :: ConstraintSource -> PackageEnvironment -> String
                            -> ParseResult PackageEnvironment
-parsePackageEnvironment initial str = do
+parsePackageEnvironment src initial str = do
   fields <- readFields str
   let (knownSections, others) = partition isKnownSection fields
   pkgEnv <- parse others
@@ -491,7 +493,7 @@ parsePackageEnvironment initial str = do
     isKnownSection _                                                    = False
 
     parse :: [ParseUtils.Field] -> ParseResult PackageEnvironment
-    parse = parseFields pkgEnvFieldDescrs initial
+    parse = parseFields (pkgEnvFieldDescrs src) initial
 
     parseSections :: SectionsAccum -> ParseUtils.Field
                      -> ParseResult SectionsAccum
@@ -564,7 +566,8 @@ showPackageEnvironmentWithComments :: (Maybe PackageEnvironment)
                                       -> PackageEnvironment
                                       -> String
 showPackageEnvironmentWithComments mdefPkgEnv pkgEnv = Disp.render $
-      ppFields pkgEnvFieldDescrs mdefPkgEnv pkgEnv
+      ppFields (pkgEnvFieldDescrs ConstraintSourceSandboxConfig)
+               mdefPkgEnv pkgEnv
   $+$ Disp.text ""
   $+$ ppSection "install-dirs" "" installDirsFields
                 (fmap installDirsSection mdefPkgEnv) (installDirsSection pkgEnv)
diff --git a/cabal-install/Distribution/Client/Setup.hs b/cabal-install/Distribution/Client/Setup.hs
index 759b13bc0123c740b131a8d38f47bb64f6f049ca..f189fe960645d2317cea35df58c9a991aa3c0892 100644
--- a/cabal-install/Distribution/Client/Setup.hs
+++ b/cabal-install/Distribution/Client/Setup.hs
@@ -52,7 +52,7 @@ import Distribution.Client.Types
 import Distribution.Client.BuildReports.Types
          ( ReportLevel(..) )
 import Distribution.Client.Dependency.Types
-         ( AllowNewer(..), PreSolver(..) )
+         ( AllowNewer(..), PreSolver(..), ConstraintSource(..) )
 import qualified Distribution.Client.Init.Types as IT
          ( InitFlags(..), PackageType(..) )
 import Distribution.Client.Targets
@@ -453,7 +453,7 @@ filterConfigureFlags flags cabalLibVersion
 --
 data ConfigExFlags = ConfigExFlags {
     configCabalVersion :: Flag Version,
-    configExConstraints:: [UserConstraint],
+    configExConstraints:: [(UserConstraint, ConstraintSource)],
     configPreferences  :: [Dependency],
     configSolver       :: Flag PreSolver,
     configAllowNewer   :: Flag AllowNewer
@@ -470,14 +470,17 @@ configureExCommand = configureCommand {
          liftOptions fst setFst
          (filter ((`notElem` ["constraint", "dependency", "exact-configuration"])
                   . optionName) $ configureOptions  showOrParseArgs)
-      ++ liftOptions snd setSnd (configureExOptions showOrParseArgs)
+      ++ liftOptions snd setSnd
+         (configureExOptions showOrParseArgs ConstraintSourceCommandlineFlag)
   }
   where
     setFst a (_,b) = (a,b)
     setSnd b (a,_) = (a,b)
 
-configureExOptions ::  ShowOrParseArgs -> [OptionField ConfigExFlags]
-configureExOptions _showOrParseArgs =
+configureExOptions :: ShowOrParseArgs
+                   -> ConstraintSource
+                   -> [OptionField ConfigExFlags]
+configureExOptions _showOrParseArgs src =
   [ option [] ["cabal-lib-version"]
       ("Select which version of the Cabal lib to use to build packages "
       ++ "(useful for testing).")
@@ -489,8 +492,8 @@ configureExOptions _showOrParseArgs =
       "Specify constraints on a package (version, installed/source, flags)"
       configExConstraints (\v flags -> flags { configExConstraints = v })
       (reqArg "CONSTRAINT"
-              (fmap (\x -> [x]) (ReadE readUserConstraint))
-              (map display))
+              ((\x -> [(x, src)]) `fmap` ReadE readUserConstraint)
+              (map $ display . fst))
 
   , option [] ["preference"]
       "Specify preferences (soft constraints) on the version of a package"
@@ -1332,7 +1335,7 @@ installCommand = CommandUI {
                            , "exact-configuration"])
                 . optionName) $
                               configureOptions   showOrParseArgs)
-    ++ liftOptions get2 set2 (configureExOptions showOrParseArgs)
+    ++ liftOptions get2 set2 (configureExOptions showOrParseArgs ConstraintSourceCommandlineFlag)
     ++ liftOptions get3 set3 (installOptions     showOrParseArgs)
     ++ liftOptions get4 set4 (haddockOptions     showOrParseArgs)
   }
diff --git a/cabal-install/Distribution/Client/Targets.hs b/cabal-install/Distribution/Client/Targets.hs
index 25b3ec2f61d42fcb41645194b2745fcfbb727679..1890145c3b966e38c4aae019af259766355ab6fb 100644
--- a/cabal-install/Distribution/Client/Targets.hs
+++ b/cabal-install/Distribution/Client/Targets.hs
@@ -52,7 +52,8 @@ import Distribution.Package
 import Distribution.Client.Types
          ( SourcePackage(..), PackageLocation(..), OptionalStanza(..) )
 import Distribution.Client.Dependency.Types
-         ( PackageConstraint(..) )
+         ( PackageConstraint(..), ConstraintSource(..)
+         , LabeledPackageConstraint(..) )
 
 import qualified Distribution.Client.World as World
 import Distribution.Client.PackageIndex (PackageIndex)
@@ -187,12 +188,15 @@ pkgSpecifierTarget (NamedPackage name _)       = name
 pkgSpecifierTarget (SpecificSourcePackage pkg) = packageName pkg
 
 pkgSpecifierConstraints :: Package pkg
-                        => PackageSpecifier pkg -> [PackageConstraint]
-pkgSpecifierConstraints (NamedPackage _ constraints) = constraints
+                        => PackageSpecifier pkg -> [LabeledPackageConstraint]
+pkgSpecifierConstraints (NamedPackage _ constraints) = map toLpc constraints
+  where
+    toLpc pc = LabeledPackageConstraint pc (Just ConstraintSourceUserTarget)
 pkgSpecifierConstraints (SpecificSourcePackage pkg)  =
-  [PackageConstraintVersion (packageName pkg)
-                            (thisVersion (packageVersion pkg))]
-
+    [LabeledPackageConstraint pc (Just ConstraintSourceUserTarget)]
+  where
+    pc = PackageConstraintVersion (packageName pkg)
+         (thisVersion (packageVersion pkg))
 
 -- ------------------------------------------------------------
 -- * Parsing and checking user targets
diff --git a/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/DSL.hs b/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/DSL.hs
index b5e67bb28a5f10a1564e3e0a846860bbafe98fb4..8066a7c5b5e3f53f8334e89f7115fddad2db547a 100644
--- a/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/DSL.hs
+++ b/cabal-install/tests/UnitTests/Distribution/Client/Dependency/Modular/DSL.hs
@@ -287,7 +287,8 @@ exResolve db targets indepGoals = runProgress $
                               (C.PackageName p) [TestStanzas])
                        (exDbPkgs db)
     targets'     = map (\p -> NamedPackage (C.PackageName p) []) targets
-    params       = addConstraints enableTests
+    params       = addConstraints
+                   (map (\pc -> LabeledPackageConstraint pc Nothing) enableTests)
                  $ (standardInstallPolicy instIdx avaiIdx targets') {
                        depResolverIndependentGoals = indepGoals
                      }