Fix warnings in main/InteractiveEval
[ghc-hetmet.git] / compiler / main / InteractiveEval.hs
index b53e015..c006752 100644 (file)
@@ -14,6 +14,8 @@ module InteractiveEval (
         abandon, abandonAll,
         getResumeContext,
         getHistorySpan,
+        getModBreaks,
+        getHistoryModule,
         back, forward,
        setContext, getContext, 
         nameSetToGlobalRdrEnv,
@@ -28,7 +30,8 @@ module InteractiveEval (
         isModuleInterpreted,
        compileExpr, dynCompileExpr,
        lookupName,
-        obtainTerm, obtainTerm1
+        Term(..), obtainTerm, obtainTerm1, obtainTermB, reconstructType,
+        skolemiseSubst, skolemiseTy
 #endif
         ) where
 
@@ -54,26 +57,30 @@ import ByteCodeInstr
 import Linker
 import DynFlags
 import Unique
+import UniqSupply
 import Module
 import Panic
-import UniqFM
+import LazyUniqFM
 import Maybes
 import ErrUtils
 import Util
 import SrcLoc
 import BreakArray
 import RtClosureInspect
-import Packages
 import BasicTypes
 import Outputable
+import FastString
 
 import Data.Dynamic
+import Data.List (find)
 import Control.Monad
 import Foreign
+import Foreign.C
 import GHC.Exts
 import Data.Array
 import Control.Exception as Exception
 import Control.Concurrent
+import Data.List (sortBy)
 import Data.IORef
 import Foreign.StablePtr
 
@@ -84,11 +91,11 @@ data RunResult
   = RunOk [Name]               -- ^ names bound by this evaluation
   | RunFailed                  -- ^ statement failed compilation
   | RunException Exception     -- ^ statement raised an exception
-  | RunBreak ThreadId [Name] BreakInfo
+  | RunBreak ThreadId [Name] (Maybe BreakInfo)
 
 data Status
-   = Break HValue BreakInfo ThreadId
-          -- ^ the computation hit a breakpoint
+   = Break Bool HValue BreakInfo ThreadId
+          -- ^ the computation hit a breakpoint (Bool <=> was an exception)
    | Complete (Either Exception [HValue])
           -- ^ the computation completed with either an exception or a value
 
@@ -102,7 +109,9 @@ data Resume
        resumeFinalIds  :: [Id],         -- [Id] to bind on completion
        resumeApStack   :: HValue,       -- The object from which we can get
                                         -- value of the free variables.
-       resumeBreakInfo :: BreakInfo,    -- the breakpoint we stopped at.
+       resumeBreakInfo :: Maybe BreakInfo,    
+                                        -- the breakpoint we stopped at
+                                        -- (Nothing <=> exception)
        resumeSpan      :: SrcSpan,      -- just a cache, otherwise it's a pain
                                         -- to fetch the ModDetails & ModBreaks
                                         -- to get this.
@@ -118,44 +127,60 @@ data SingleStep
    | SingleStep
    | RunAndLogSteps
 
+isStep :: SingleStep -> Bool
 isStep RunToCompletion = False
 isStep _ = True
 
 data History
    = History {
         historyApStack   :: HValue,
-        historyBreakInfo :: BreakInfo
+        historyBreakInfo :: BreakInfo,
+        historyEnclosingDecl :: Id
+         -- ^^ A cache of the enclosing top level declaration, for convenience
    }
 
-getHistorySpan :: Session -> History -> IO SrcSpan
-getHistorySpan s hist = withSession s $ \hsc_env -> do
-   let inf = historyBreakInfo hist 
+mkHistory :: HscEnv -> HValue -> BreakInfo -> History
+mkHistory hsc_env hval bi = let
+    h    = History hval bi decl
+    decl = findEnclosingDecl hsc_env (getHistoryModule h)
+                                     (getHistorySpan hsc_env h)
+    in h
+
+getHistoryModule :: History -> Module
+getHistoryModule = breakInfo_module . historyBreakInfo
+
+getHistorySpan :: HscEnv -> History -> SrcSpan
+getHistorySpan hsc_env hist =
+   let inf = historyBreakInfo hist
        num = breakInfo_number inf
-   case lookupUFM (hsc_HPT hsc_env) (moduleName (breakInfo_module inf)) of
-       Just hmi -> return (modBreaks_locs (md_modBreaks (hm_details hmi)) ! num)
+   in case lookupUFM (hsc_HPT hsc_env) (moduleName (breakInfo_module inf)) of
+       Just hmi -> modBreaks_locs (getModBreaks hmi) ! num
        _ -> panic "getHistorySpan"
 
-{-
- [Main.hs:42:(1,0)-(3,52)] *Main> :history 2
- Foo.hs:1:3-5
- Bar.hs:5:23-48
- [Main.hs:42:(1,0)-(3,52)] *Main> :back
- Logged breakpoint at Foo.hs:1:3-5
- x :: Int
- y :: a
- _result :: [Char]
- [-1: Foo.hs:1:3-5] *Main> :back
- Logged breakpoint at Bar.hs:5:23-48
- z :: a
- _result :: Float
- [-2: Bar.hs:5:23-48] *Main> :forward
- Logged breakpoint at Foo.hs:1:3-5
- x :: Int
- y :: a
- _result :: [Char]
- [-1: Foo.hs:1:3-5] *Main> :cont
- .. continues
--} 
+getModBreaks :: HomeModInfo -> ModBreaks
+getModBreaks hmi
+  | Just linkable <- hm_linkable hmi, 
+    [BCOs _ modBreaks] <- linkableUnlinked linkable
+  = modBreaks
+  | otherwise
+  = emptyModBreaks -- probably object code
+
+{- | Finds the enclosing top level function name -}
+-- ToDo: a better way to do this would be to keep hold of the decl_path computed
+-- by the coverage pass, which gives the list of lexically-enclosing bindings
+-- for each tick.
+findEnclosingDecl :: HscEnv -> Module -> SrcSpan -> Id
+findEnclosingDecl hsc_env mod span =
+   case lookupUFM (hsc_HPT hsc_env) (moduleName mod) of
+         Nothing -> panic "findEnclosingDecl"
+         Just hmi -> let
+             globals   = typeEnvIds (md_types (hm_details hmi))
+             Just decl = 
+                 find (\id -> let n = idName id in 
+                               nameSrcSpan n < span && isExternalName n)
+                      (reverse$ sortBy (compare `on` (nameSrcSpan.idName))
+                                       globals)
+           in decl
 
 -- | Run a statement in the current interactive context.  Statement
 -- may bind multple values.
@@ -178,17 +203,11 @@ runStmt (Session ref) expr step
           Nothing -> return RunFailed
           Just (ids, hval) -> do
 
-              when (isStep step) $ setStepFlag
-
-              -- set the onBreakAction to be performed when we hit a
-              -- breakpoint this is visible in the Byte Code
-              -- Interpreter, thus it is a global variable,
-              -- implemented with stable pointers
-              withBreakAction breakMVar statusMVar $ do
-
-              let thing_to_run = unsafeCoerce# hval :: IO [HValue]
-              status <- sandboxIO statusMVar thing_to_run
-
+              status <- 
+                withBreakAction (isStep step) dflags' breakMVar statusMVar $ do
+                      let thing_to_run = unsafeCoerce# hval :: IO [HValue]
+                      sandboxIO dflags' statusMVar thing_to_run
+              
               let ic = hsc_IC hsc_env
                   bindings = (ic_tmp_ids ic, ic_tyvars ic)
 
@@ -200,24 +219,30 @@ runStmt (Session ref) expr step
                         handleRunStatus expr ref bindings ids
                                         breakMVar statusMVar status emptyHistory
 
-
+emptyHistory :: BoundedList History
 emptyHistory = nilBL 50 -- keep a log of length 50
 
+handleRunStatus :: String -> IORef HscEnv -> ([Id], TyVarSet) -> [Id]
+                -> MVar () -> MVar Status -> Status -> BoundedList History
+                -> IO RunResult
 handleRunStatus expr ref bindings final_ids breakMVar statusMVar status 
                 history =
    case status of  
       -- did we hit a breakpoint or did we complete?
-      (Break apStack info tid) -> do
+      (Break is_exception apStack info tid) -> do
         hsc_env <- readIORef ref
-        (hsc_env1, names, span) <- bindLocalsAtBreakpoint hsc_env apStack info
+        let mb_info | is_exception = Nothing
+                    | otherwise    = Just info
+        (hsc_env1, names, span) <- bindLocalsAtBreakpoint hsc_env 
+                                                          apStack mb_info
         let
             resume = Resume expr tid breakMVar statusMVar 
-                              bindings final_ids apStack info span 
+                              bindings final_ids apStack mb_info span 
                               (toListBL history) 0
             hsc_env2 = pushResume hsc_env1 resume
         --
         writeIORef ref hsc_env2
-        return (RunBreak tid names info)
+        return (RunBreak tid names mb_info)
       (Complete either_hvals) ->
        case either_hvals of
            Left e -> return (RunException e)
@@ -227,32 +252,34 @@ handleRunStatus expr ref bindings final_ids breakMVar statusMVar status
                                         final_ids emptyVarSet
                         -- the bound Ids never have any free TyVars
                     final_names = map idName final_ids
-                writeIORef ref hsc_env{hsc_IC=final_ic}
                 Linker.extendLinkEnv (zip final_names hvals)
+                hsc_env' <- rttiEnvironment hsc_env{hsc_IC=final_ic}
+                writeIORef ref hsc_env' 
                 return (RunOk final_names)
 
-
+traceRunStatus :: String -> IORef HscEnv -> ([Id], TyVarSet) -> [Id]
+               -> MVar () -> MVar Status -> Status -> BoundedList History
+               -> IO RunResult
 traceRunStatus expr ref bindings final_ids
                breakMVar statusMVar status history = do
   hsc_env <- readIORef ref
   case status of
      -- when tracing, if we hit a breakpoint that is not explicitly
      -- enabled, then we just log the event in the history and continue.
-     (Break apStack info tid) -> do
+     (Break is_exception apStack info tid) | not is_exception -> do
         b <- isBreakEnabled hsc_env info
         if b
            then handle_normally
            else do
-             let history' = consBL (History apStack info) history
+             let history' = mkHistory hsc_env apStack info `consBL` history
                 -- probably better make history strict here, otherwise
                 -- our BoundedList will be pointless.
              evaluate history'
-             setStepFlag
-             status <- withBreakAction breakMVar statusMVar $ do
-                       withInterruptsSentTo
-                         (do putMVar breakMVar ()  -- awaken the stopped thread
-                             return tid)
-                         (takeMVar statusMVar)     -- and wait for the result
+             status <- withBreakAction True (hsc_dflags hsc_env)
+                                 breakMVar statusMVar $ do
+                       withInterruptsSentTo tid $ do
+                           putMVar breakMVar ()  -- awaken the stopped thread
+                           takeMVar statusMVar   -- and wait for the result
              traceRunStatus expr ref bindings final_ids 
                             breakMVar statusMVar status history'
      _other ->
@@ -266,56 +293,112 @@ isBreakEnabled :: HscEnv -> BreakInfo -> IO Bool
 isBreakEnabled hsc_env inf =
    case lookupUFM (hsc_HPT hsc_env) (moduleName (breakInfo_module inf)) of
        Just hmi -> do
-         w <- getBreak (modBreaks_flags (md_modBreaks (hm_details hmi)))
+         w <- getBreak (modBreaks_flags (getModBreaks hmi))
                        (breakInfo_number inf)
          case w of Just n -> return (n /= 0); _other -> return False
        _ ->
          return False
 
 
-foreign import ccall "rts_setStepFlag" setStepFlag :: IO () 
+foreign import ccall "&rts_stop_next_breakpoint" stepFlag      :: Ptr CInt
+foreign import ccall "&rts_stop_on_exception"    exceptionFlag :: Ptr CInt
+
+setStepFlag :: IO ()
+setStepFlag = poke stepFlag 1
+resetStepFlag :: IO ()
+resetStepFlag = poke stepFlag 0
 
 -- this points to the IO action that is executed when a breakpoint is hit
-foreign import ccall "&breakPointIOAction" 
-        breakPointIOAction :: Ptr (StablePtr (BreakInfo -> HValue -> IO ())) 
+foreign import ccall "&rts_breakpoint_io_action" 
+   breakPointIOAction :: Ptr (StablePtr (Bool -> BreakInfo -> HValue -> IO ())) 
 
 -- When running a computation, we redirect ^C exceptions to the running
 -- thread.  ToDo: we might want a way to continue even if the target
 -- thread doesn't die when it receives the exception... "this thread
 -- is not responding".
-sandboxIO :: MVar Status -> IO [HValue] -> IO Status
-sandboxIO statusMVar thing = 
-  withInterruptsSentTo 
-        (forkIO (do res <- Exception.try thing
-                    putMVar statusMVar (Complete res)))
-        (takeMVar statusMVar)
-
-withInterruptsSentTo :: IO ThreadId -> IO r -> IO r
-withInterruptsSentTo io get_result = do
-  ts <- takeMVar interruptTargetThread
-  child <- io
-  putMVar interruptTargetThread (child:ts)
-  get_result `finally` modifyMVar_ interruptTargetThread (return.tail)
-
-withBreakAction breakMVar statusMVar io
+-- 
+-- Careful here: there may be ^C exceptions flying around, so we start
+-- the new thread blocked (forkIO inherits block from the parent,
+-- #1048), and unblock only while we execute the user's code.  We
+-- can't afford to lose the final putMVar, otherwise deadlock
+-- ensues. (#1583, #1922, #1946)
+sandboxIO :: DynFlags -> MVar Status -> IO [HValue] -> IO Status
+sandboxIO dflags statusMVar thing =
+   block $ do  -- fork starts blocked
+     id <- forkIO $ do res <- Exception.try (unblock $ rethrow dflags thing)
+                       putMVar statusMVar (Complete res) -- empty: can't block
+     withInterruptsSentTo id $ takeMVar statusMVar
+
+
+-- We want to turn ^C into a break when -fbreak-on-exception is on,
+-- but it's an async exception and we only break for sync exceptions.
+-- Idea: if we catch and re-throw it, then the re-throw will trigger
+-- a break.  Great - but we don't want to re-throw all exceptions, because
+-- then we'll get a double break for ordinary sync exceptions (you'd have
+-- to :continue twice, which looks strange).  So if the exception is
+-- not "Interrupted", we unset the exception flag before throwing.
+--
+rethrow :: DynFlags -> IO a -> IO a
+rethrow dflags io = Exception.catch io $ \e -> do -- NB. not catchDyn
+                case e of
+                   -- If -fbreak-on-error, we break unconditionally,
+                   --  but with care of not breaking twice 
+                   _ | dopt Opt_BreakOnError dflags && 
+                       not(dopt Opt_BreakOnException dflags)
+                        -> poke exceptionFlag 1
+
+                   -- If it is an "Interrupted" exception, we allow
+                   --  a possible break by way of -fbreak-on-exception
+                   DynException d | Just Interrupted <- fromDynamic d
+                        -> return ()
+
+                   -- In any other case, we don't want to break
+                   _    -> poke exceptionFlag 0
+
+                Exception.throwIO e
+
+
+withInterruptsSentTo :: ThreadId -> IO r -> IO r
+withInterruptsSentTo thread get_result = do
+  bracket (modifyMVar_ interruptTargetThread (return . (thread:)))
+          (\_ -> modifyMVar_ interruptTargetThread (\tl -> return $! tail tl))
+          (\_ -> get_result)
+
+-- This function sets up the interpreter for catching breakpoints, and
+-- resets everything when the computation has stopped running.  This
+-- is a not-very-good way to ensure that only the interactive
+-- evaluation should generate breakpoints.
+withBreakAction :: Bool -> DynFlags -> MVar () -> MVar Status -> IO a -> IO a
+withBreakAction step dflags breakMVar statusMVar io
  = bracket setBreakAction resetBreakAction (\_ -> io)
  where
    setBreakAction = do
      stablePtr <- newStablePtr onBreak
      poke breakPointIOAction stablePtr
+     when (dopt Opt_BreakOnException dflags) $ poke exceptionFlag 1
+     when step $ setStepFlag
      return stablePtr
+        -- Breaking on exceptions is not enabled by default, since it
+        -- might be a bit surprising.  The exception flag is turned off
+        -- as soon as it is hit, or in resetBreakAction below.
 
-   onBreak info apStack = do
+   onBreak is_exception info apStack = do
      tid <- myThreadId
-     putMVar statusMVar (Break apStack info tid)
+     putMVar statusMVar (Break is_exception apStack info tid)
      takeMVar breakMVar
 
    resetBreakAction stablePtr = do
      poke breakPointIOAction noBreakStablePtr
+     poke exceptionFlag 0
+     resetStepFlag
      freeStablePtr stablePtr
 
+noBreakStablePtr :: StablePtr (Bool -> BreakInfo -> HValue -> IO ())
 noBreakStablePtr = unsafePerformIO $ newStablePtr noBreakAction
-noBreakAction info apStack = putStrLn "*** Ignoring breakpoint"
+
+noBreakAction :: Bool -> BreakInfo -> HValue -> IO ()
+noBreakAction False _ _ = putStrLn "*** Ignoring breakpoint"
+noBreakAction True  _ _ = return () -- exception: just continue
 
 resume :: Session -> SingleStep -> IO RunResult
 resume (Session ref) step
@@ -345,22 +428,26 @@ resume (Session ref) step
         when (isStep step) $ setStepFlag
         case r of 
           Resume expr tid breakMVar statusMVar bindings 
-              final_ids apStack info _ _ _ -> do
-                withBreakAction breakMVar statusMVar $ do
-                status <- withInterruptsSentTo
-                             (do putMVar breakMVar ()
+              final_ids apStack info _ hist _ -> do
+                withBreakAction (isStep step) (hsc_dflags hsc_env) 
+                                        breakMVar statusMVar $ do
+                status <- withInterruptsSentTo tid $ do
+                             putMVar breakMVar ()
                                       -- this awakens the stopped thread...
-                                 return tid)
-                             (takeMVar statusMVar)
-                                      -- and wait for the result
+                             takeMVar statusMVar
+                                      -- and wait for the result 
+                let hist' = 
+                     case info of 
+                       Nothing -> fromListBL 50 hist
+                       Just i -> mkHistory hsc_env apStack i `consBL` 
+                                                        fromListBL 50 hist
                 case step of
                   RunAndLogSteps -> 
                         traceRunStatus expr ref bindings final_ids
-                                       breakMVar statusMVar status emptyHistory
+                                       breakMVar statusMVar status hist'
                   _other ->
                         handleRunStatus expr ref bindings final_ids
-                                        breakMVar statusMVar status emptyHistory
-
+                                        breakMVar statusMVar status hist'
 
 back :: Session -> IO ([Name], Int, SrcSpan)
 back  = moveHist (+1)
@@ -368,6 +455,7 @@ back  = moveHist (+1)
 forward :: Session -> IO ([Name], Int, SrcSpan)
 forward  = moveHist (subtract 1)
 
+moveHist :: (Int -> Int) -> Session -> IO ([Name], Int, SrcSpan)
 moveHist fn (Session ref) = do
   hsc_env <- readIORef ref
   case ic_resume (hsc_IC hsc_env) of
@@ -377,15 +465,15 @@ moveHist fn (Session ref) = do
             history = resumeHistory r
             new_ix = fn ix
         --
-        when (new_ix >= length history) $
+        when (new_ix > length history) $
            throwDyn (ProgramError "no more logged breakpoints")
         when (new_ix < 0) $
            throwDyn (ProgramError "already at the beginning of the history")
 
         let
-          update_ic apStack info = do
+          update_ic apStack mb_info = do
             (hsc_env1, names, span) <- bindLocalsAtBreakpoint hsc_env 
-                                                apStack info 
+                                                apStack mb_info
             let ic = hsc_IC hsc_env1           
                 r' = r { resumeHistoryIx = new_ix }
                 ic' = ic { ic_resume = r':rs }
@@ -400,26 +488,54 @@ moveHist fn (Session ref) = do
         if new_ix == 0
            then case r of 
                    Resume { resumeApStack = apStack, 
-                            resumeBreakInfo = info } ->
-                          update_ic apStack info
+                            resumeBreakInfo = mb_info } ->
+                          update_ic apStack mb_info
            else case history !! (new_ix - 1) of 
-                   History apStack info ->
-                          update_ic apStack info
+                   History apStack info _ ->
+                          update_ic apStack (Just info)
 
 -- -----------------------------------------------------------------------------
 -- After stopping at a breakpoint, add free variables to the environment
+result_fs :: FastString
+result_fs = FSLIT("_result")
 
 bindLocalsAtBreakpoint
         :: HscEnv
         -> HValue
-        -> BreakInfo
+        -> Maybe BreakInfo
         -> IO (HscEnv, [Name], SrcSpan)
-bindLocalsAtBreakpoint hsc_env apStack info = do
+
+-- Nothing case: we stopped when an exception was raised, not at a
+-- breakpoint.  We have no location information or local variables to
+-- bind, all we can do is bind a local variable to the exception
+-- value.
+bindLocalsAtBreakpoint hsc_env apStack Nothing = do
+   let exn_fs    = FSLIT("_exception")
+       exn_name  = mkInternalName (getUnique exn_fs) (mkVarOccFS exn_fs) span
+       e_fs      = FSLIT("e")
+       e_name    = mkInternalName (getUnique e_fs) (mkTyVarOcc e_fs) span
+       e_tyvar   = mkTcTyVar e_name liftedTypeKind (SkolemTv RuntimeUnkSkol)
+       exn_id    = Id.mkGlobalId VanillaGlobal exn_name (mkTyVarTy e_tyvar)
+                                vanillaIdInfo
+       new_tyvars = unitVarSet e_tyvar
+
+       ictxt0 = hsc_IC hsc_env
+       ictxt1 = extendInteractiveContext ictxt0 [exn_id] new_tyvars
+
+       span = mkGeneralSrcSpan FSLIT("<exception thrown>")
+   --
+   Linker.extendLinkEnv [(exn_name, unsafeCoerce# apStack)]
+   return (hsc_env{ hsc_IC = ictxt1 }, [exn_name], span)
+
+-- Just case: we stopped at a breakpoint, we have information about the location
+-- of the breakpoint and the free variables of the expression.
+bindLocalsAtBreakpoint hsc_env apStack (Just info) = do
 
    let 
-       mod_name    = moduleName (breakInfo_module info)
-       mod_details = fmap hm_details (lookupUFM (hsc_HPT hsc_env) mod_name)
-       breaks      = md_modBreaks (expectJust "handlRunStatus" mod_details)
+       mod_name  = moduleName (breakInfo_module info)
+       hmi       = expectJust "bindLocalsAtBreakpoint" $ 
+                        lookupUFM (hsc_HPT hsc_env) mod_name
+       breaks    = getModBreaks hmi
        index     = breakInfo_number info
        vars      = breakInfo_vars info
        result_ty = breakInfo_resty info
@@ -438,7 +554,7 @@ bindLocalsAtBreakpoint hsc_env apStack info = do
    -- So that we don't fall over in a heap when this happens, just don't
    -- bind any free variables instead, and we emit a warning.
    mb_hValues <- mapM (getIdValFromApStack apStack) offsets
-   let filtered_ids = [ id | (id, Just _) <- zip ids mb_hValues ]
+   let filtered_ids = [ id | (id, Just _hv) <- zip ids mb_hValues ]
    when (any isNothing mb_hValues) $
       debugTraceMsg (hsc_dflags hsc_env) 1 $
          text "Warning: _result has been evaluated, some bindings have been lost"
@@ -449,10 +565,10 @@ bindLocalsAtBreakpoint hsc_env apStack info = do
    -- make an Id for _result.  We use the Unique of the FastString "_result";
    -- we don't care about uniqueness here, because there will only be one
    -- _result in scope at any time.
-   let result_fs = FSLIT("_result")
-       result_name = mkInternalName (getUnique result_fs)
-                          (mkVarOccFS result_fs) (srcSpanStart span)
-       result_id   = Id.mkLocalId result_name result_ty
+   let result_name = mkInternalName (getUnique result_fs)
+                          (mkVarOccFS result_fs) span
+       result_id   = Id.mkGlobalId VanillaGlobal result_name result_ty 
+                                   vanillaIdInfo
 
    -- for each Id we're about to bind in the local envt:
    --    - skolemise the type variables in its type, so they can't
@@ -466,24 +582,50 @@ bindLocalsAtBreakpoint hsc_env apStack info = do
        (id_tys, tyvarss) = mapAndUnzip (skolemiseTy.idType) all_ids
        (_,tidy_tys) = tidyOpenTypes emptyTidyEnv id_tys
        new_tyvars = unionVarSets tyvarss             
-       final_ids = zipWith setIdType all_ids tidy_tys
-
-   let   ictxt0 = hsc_IC hsc_env
-         ictxt1 = extendInteractiveContext ictxt0 final_ids new_tyvars
-
+   let final_ids = zipWith setIdType all_ids tidy_tys
+       ictxt0 = hsc_IC hsc_env
+       ictxt1 = extendInteractiveContext ictxt0 final_ids new_tyvars
    Linker.extendLinkEnv [ (name,hval) | (name, Just hval) <- zip names mb_hValues ]
    Linker.extendLinkEnv [(result_name, unsafeCoerce# apStack)]
-   return (hsc_env{ hsc_IC = ictxt1 }, result_name:names, span)
+   hsc_env1 <- rttiEnvironment hsc_env{ hsc_IC = ictxt1 }
+   return (hsc_env1, result_name:names, span)
   where
    mkNewId :: OccName -> Id -> IO Id
    mkNewId occ id = do
-     let uniq = idUnique id
-         loc = nameSrcLoc (idName id)
+     us <- mkSplitUniqSupply 'I'
+        -- we need a fresh Unique for each Id we bind, because the linker
+        -- state is single-threaded and otherwise we'd spam old bindings
+        -- whenever we stop at a breakpoint.  The InteractveContext is properly
+        -- saved/restored, but not the linker state.  See #1743, test break026.
+     let 
+         uniq = uniqFromSupply us
+         loc = nameSrcSpan (idName id)
          name = mkInternalName uniq occ loc
          ty = idType id
          new_id = Id.mkGlobalId VanillaGlobal name ty (idInfo id)
      return new_id
 
+rttiEnvironment :: HscEnv -> IO HscEnv 
+rttiEnvironment hsc_env@HscEnv{hsc_IC=ic} = do
+   let InteractiveContext{ic_tmp_ids=tmp_ids} = ic
+       incompletelyTypedIds = 
+           [id | id <- tmp_ids
+               , not $ null [v | v <- varSetElems$ tyVarsOfType (idType id)
+                              , isSkolemTyVar v]
+               , (occNameFS.nameOccName.idName) id /= result_fs]
+   tys <- reconstructType hsc_env 10 `mapM` incompletelyTypedIds
+          -- map termType `fmap` (obtainTerm hsc_env False `mapM` incompletelyTypedIds)
+   
+   let substs = [unifyRTTI ty ty' 
+                 | (ty, Just ty') <- zip (map idType incompletelyTypedIds) tys]
+       ic'    = foldr (flip substInteractiveContext) ic 
+                           (map skolemiseSubst substs)
+   return hsc_env{hsc_IC=ic'}
+
+skolemiseSubst :: TvSubst -> TvSubst
+skolemiseSubst subst = subst `setTvSubstEnv` 
+                        mapVarEnv (fst.skolemiseTy) (getTvSubstEnv subst)
+
 skolemiseTy :: Type -> (Type, TyVarSet)
 skolemiseTy ty = (substTy subst ty, mkVarSet new_tyvars)
   where env           = mkVarEnv (zip tyvars new_tyvar_tys)
@@ -522,8 +664,9 @@ abandon (Session ref) = do
        resume = ic_resume ic
    case resume of
       []    -> return False
-      _:rs  -> do
+      r:rs  -> do 
          writeIORef ref hsc_env{ hsc_IC = ic { ic_resume = rs } }
+         abandon_ r
          return True
 
 abandonAll :: Session -> IO Bool
@@ -532,11 +675,26 @@ abandonAll (Session ref) = do
    let ic = hsc_IC hsc_env
        resume = ic_resume ic
    case resume of
-      []    -> return False
-      _:rs  -> do
+      []  -> return False
+      rs  -> do 
          writeIORef ref hsc_env{ hsc_IC = ic { ic_resume = [] } }
+         mapM_ abandon_ rs
          return True
 
+-- when abandoning a computation we have to 
+--      (a) kill the thread with an async exception, so that the 
+--          computation itself is stopped, and
+--      (b) fill in the MVar.  This step is necessary because any
+--          thunks that were under evaluation will now be updated
+--          with the partial computation, which still ends in takeMVar,
+--          so any attempt to evaluate one of these thunks will block
+--          unless we fill in the MVar.
+--  See test break010.
+abandon_ :: Resume -> IO ()
+abandon_ r = do
+  killThread (resumeThreadId r)
+  putMVar (resumeBreakMVar r) () 
+
 -- -----------------------------------------------------------------------------
 -- Bounded list, optimised for repeated cons
 
@@ -549,13 +707,18 @@ data BoundedList a = BL
 nilBL :: Int -> BoundedList a
 nilBL bound = BL 0 bound [] []
 
+consBL :: a -> BoundedList a -> BoundedList a
 consBL a (BL len bound left right)
   | len < bound = BL (len+1) bound (a:left) right
   | null right  = BL len     bound [a]      $! tail (reverse left)
   | otherwise   = BL len     bound (a:left) $! tail right
 
+toListBL :: BoundedList a -> [a]
 toListBL (BL _ _ left right) = left ++ reverse right
 
+fromListBL :: Int -> [a] -> BoundedList a
+fromListBL bound l = BL (length l) bound l []
+
 -- lenBL (BL len _ _ _) = len
 
 -- -----------------------------------------------------------------------------
@@ -568,7 +731,7 @@ setContext :: Session
           -> [Module]  -- entire top level scope of these modules
           -> [Module]  -- exports only of these modules
           -> IO ()
-setContext sess@(Session ref) toplev_mods export_mods = do 
+setContext (Session ref) toplev_mods export_mods = do 
   hsc_env <- readIORef ref
   let old_ic  = hsc_IC     hsc_env
       hpt     = hsc_HPT    hsc_env
@@ -593,7 +756,7 @@ mkExportEnv hsc_env mods = do
 
 nameSetToGlobalRdrEnv :: NameSet -> ModuleName -> GlobalRdrEnv
 nameSetToGlobalRdrEnv names mod =
-  mkGlobalRdrEnv [ GRE  { gre_name = name, gre_prov = vanillaProv mod }
+  mkGlobalRdrEnv [ GRE  { gre_name = name, gre_par = NoParent, gre_prov = vanillaProv mod }
                 | name <- nameSetToList names ]
 
 vanillaProv :: ModuleName -> Provenance
@@ -635,8 +798,29 @@ moduleIsInterpreted s modl = withSession s $ \h ->
                 _not_a_home_module -> return False
 
 -- | Looks up an identifier in the current interactive context (for :info)
+-- Filter the instances by the ones whose tycons (or clases resp) 
+-- are in scope (qualified or otherwise).  Otherwise we list a whole lot too many!
+-- The exact choice of which ones to show, and which to hide, is a judgement call.
+--     (see Trac #1581)
 getInfo :: Session -> Name -> IO (Maybe (TyThing,Fixity,[Instance]))
-getInfo s name = withSession s $ \hsc_env -> tcRnGetInfo hsc_env name
+getInfo s name 
+  = withSession s $ \hsc_env -> 
+    do { mb_stuff <- tcRnGetInfo hsc_env name
+       ; case mb_stuff of
+           Nothing -> return Nothing
+           Just (thing, fixity, ispecs) -> do
+       { let rdr_env = ic_rn_gbl_env (hsc_IC hsc_env)
+       ; return (Just (thing, fixity, filter (plausible rdr_env) ispecs)) } }
+  where
+    plausible rdr_env ispec    -- Dfun involving only names that are in ic_rn_glb_env
+       = all ok $ nameSetToList $ tyClsNamesOfType $ idType $ instanceDFunId ispec
+       where   -- A name is ok if it's in the rdr_env, 
+               -- whether qualified or not
+         ok n | n == name         = True       -- The one we looked for in the first place!
+              | isBuiltInSyntax n = True
+              | isExternalName n  = any ((== n) . gre_name)
+                                        (lookupGRE_Name rdr_env n)
+              | otherwise         = True
 
 -- | Returns all names in scope in the current interactive context
 getNamesInScope :: Session -> IO [Name]
@@ -725,7 +909,7 @@ compileExpr s expr = withSession s $ \hsc_env -> do
                hvals <- (unsafeCoerce# hval) :: IO [HValue]
 
                case (ids,hvals) of
-                 ([n],[hv]) -> return (Just hv)
+                 ([_],[hv]) -> return (Just hv)
                  _          -> panic "compileExpr"
 
 -- -----------------------------------------------------------------------------
@@ -765,14 +949,26 @@ isModuleInterpreted s mod_summary = withSession s $ \hsc_env ->
                      where
                         obj_linkable = isObjectLinkable (expectJust "showModule" (hm_linkable mod_info))
 
-obtainTerm1 :: Session -> Bool -> Maybe Type -> a -> IO Term
-obtainTerm1 sess force mb_ty x = withSession sess $ \hsc_env -> cvObtainTerm hsc_env force mb_ty (unsafeCoerce# x)
+----------------------------------------------------------------------------
+-- RTTI primitives
+
+obtainTerm1 :: HscEnv -> Bool -> Maybe Type -> a -> IO Term
+obtainTerm1 hsc_env force mb_ty x = 
+              cvObtainTerm hsc_env maxBound force mb_ty (unsafeCoerce# x)
+
+obtainTermB :: HscEnv -> Int -> Bool -> Id -> IO Term
+obtainTermB hsc_env bound force id =  do
+              hv <- Linker.getHValue hsc_env (varName id) 
+              cvObtainTerm hsc_env bound force (Just$ idType id) hv
 
-obtainTerm :: Session -> Bool -> Id -> IO (Maybe Term)
-obtainTerm sess force id = withSession sess $ \hsc_env -> do
-              mb_v <- Linker.getHValue (varName id) 
-              case mb_v of
-                Just v  -> fmap Just$ cvObtainTerm hsc_env force (Just$ idType id) v
-                Nothing -> return Nothing
+obtainTerm :: HscEnv -> Bool -> Id -> IO Term
+obtainTerm hsc_env force id =  do
+              hv <- Linker.getHValue hsc_env (varName id) 
+              cvObtainTerm hsc_env maxBound force (Just$ idType id) hv
 
+-- Uses RTTI to reconstruct the type of an Id, making it less polymorphic
+reconstructType :: HscEnv -> Int -> Id -> IO (Maybe Type)
+reconstructType hsc_env bound id = do
+              hv <- Linker.getHValue hsc_env (varName id) 
+              cvReconstructType hsc_env bound (Just$ idType id) hv
 #endif /* GHCI */