diff --git a/cabal-install/Distribution/Client/ProjectBuilding.hs b/cabal-install/Distribution/Client/ProjectBuilding.hs
index ba6ebcb0dbe34e2a33900b02e9f52d114b4eeb6c..75216a54687e83cabdba9341bc62ebb8c2e73f27 100644
--- a/cabal-install/Distribution/Client/ProjectBuilding.hs
+++ b/cabal-install/Distribution/Client/ProjectBuilding.hs
@@ -146,6 +146,10 @@ data BuildStatus =
      --   need building.
      BuildStatusPreExisting
 
+     -- | The package is in the 'InstallPlan.Installed' state, so does not
+     --   need building.
+   | BuildStatusInstalled
+
      -- | The package has not been downloaded yet, so it will have to be
      --   downloaded, unpacked and built.
    | BuildStatusDownload
@@ -166,6 +170,7 @@ data BuildStatus =
 
 buildStatusToString :: BuildStatus -> String
 buildStatusToString BuildStatusPreExisting      = "BuildStatusPreExisting"
+buildStatusToString BuildStatusInstalled        = "BuildStatusInstalled"
 buildStatusToString BuildStatusDownload         = "BuildStatusDownload"
 buildStatusToString (BuildStatusUnpack fp)      = "BuildStatusUnpack " ++ show fp
 buildStatusToString (BuildStatusRebuild fp _)   = "BuildStatusRebuild " ++ show fp
@@ -229,6 +234,7 @@ data BuildReason =
 --
 buildStatusRequiresBuild :: BuildStatus -> Bool
 buildStatusRequiresBuild BuildStatusPreExisting = False
+buildStatusRequiresBuild BuildStatusInstalled   = False
 buildStatusRequiresBuild BuildStatusUpToDate {} = False
 buildStatusRequiresBuild _                      = True
 
@@ -263,7 +269,7 @@ rebuildTargetsDryRun verbosity distDirLayout@DistDirLayout{..} shared = \install
       return BuildStatusPreExisting
 
     dryRunPkg (InstallPlan.Installed _pkg) _depsBuildStatus =
-      return BuildStatusPreExisting --TODO: distinguish installed state
+      return BuildStatusInstalled
 
     dryRunPkg (InstallPlan.Configured pkg) depsBuildStatus = do
       mloc <- checkFetched (elabPkgSourceLocation pkg)
@@ -743,6 +749,7 @@ rebuildTarget verbosity
 
       -- TODO: perhaps re-nest the types to make these impossible
       BuildStatusPreExisting {} -> unexpectedState
+      BuildStatusInstalled   {} -> unexpectedState
       BuildStatusUpToDate    {} -> unexpectedState
   where
     unexpectedState = error "rebuildTarget: unexpected package status"
diff --git a/cabal-install/Distribution/Client/ProjectOrchestration.hs b/cabal-install/Distribution/Client/ProjectOrchestration.hs
index 6141059f7b7e78af08713790b49671cbc3542f14..548fe1b9df8fe9034b0797887a047d96c26fc262 100644
--- a/cabal-install/Distribution/Client/ProjectOrchestration.hs
+++ b/cabal-install/Distribution/Client/ProjectOrchestration.hs
@@ -492,7 +492,8 @@ printPlan verbosity
     showFlagName (PD.FlagName f) = f
 
     showBuildStatus status = case status of
-      BuildStatusPreExisting -> "already installed"
+      BuildStatusPreExisting -> "existing package"
+      BuildStatusInstalled   -> "already installed"
       BuildStatusDownload {} -> "requires download & build"
       BuildStatusUnpack   {} -> "requires build"
       BuildStatusRebuild _ rebuild -> case rebuild of