Fix a couple of issues with :print
authorpepe <unknown>
Thu, 18 Sep 2008 12:21:33 +0000 (12:21 +0000)
committerpepe <unknown>
Thu, 18 Sep 2008 12:21:33 +0000 (12:21 +0000)
      - Ticket #1995: Unsoundness with newtypes
      - Ticket #2475: "Can't unify" error when stopped at an exception

      In addition this patch adds the following:

      - Unfailingness: RTTI cannot panic anymore.
        In case of failure, it recovers gracefully by returning the "I know nothing" type
      - A -ddump-rtti flag

compiler/ghci/Debugger.hs
compiler/ghci/RtClosureInspect.hs
compiler/main/DynFlags.hs
compiler/main/GHC.hs
compiler/main/HscTypes.lhs
compiler/main/InteractiveEval.hs

index 15f1502..712eec0 100644 (file)
@@ -53,13 +53,15 @@ pprintClosureCommand bindThings force str = do
   let ids = [id | AnId id <- tythings]
 
   -- Obtain the terms and the recovered type information
   let ids = [id | AnId id <- tythings]
 
   -- Obtain the terms and the recovered type information
-  (terms, substs) <- unzip `liftM` mapM go ids
-  
+  (terms, substs0) <- unzip `liftM` mapM go ids
+
   -- Apply the substitutions obtained after recovering the types
   modifySession $ \hsc_env ->
   -- Apply the substitutions obtained after recovering the types
   modifySession $ \hsc_env ->
-         hsc_env{hsc_IC = foldr (flip substInteractiveContext)
-                                (hsc_IC hsc_env)
-                                (map skolemiseSubst substs)}
+    let (substs, skol_vars) = unzip$ map skolemiseSubst substs0
+        hsc_ic' = foldr (flip substInteractiveContext)
+                        (extendInteractiveContext (hsc_IC hsc_env) [] (unionVarSets skol_vars))
+                        substs
+     in hsc_env{hsc_IC = hsc_ic'}
   -- Finally, print the Terms
   unqual  <- GHC.getPrintUnqual
   docterms <- mapM showTerm terms
   -- Finally, print the Terms
   unqual  <- GHC.getPrintUnqual
   docterms <- mapM showTerm terms
@@ -68,13 +70,12 @@ pprintClosureCommand bindThings force str = do
                     ids
                     docterms)
  where
                     ids
                     docterms)
  where
-
    -- Do the obtainTerm--bindSuspensions-computeSubstitution dance
    go :: GhcMonad m => Id -> m (Term, TvSubst)
    go id = do
    -- Do the obtainTerm--bindSuspensions-computeSubstitution dance
    go :: GhcMonad m => Id -> m (Term, TvSubst)
    go id = do
-       term_    <- GHC.obtainTerm force id
+       term_    <- GHC.obtainTermFromId maxBound force id
        term     <- tidyTermTyVars term_
        term     <- tidyTermTyVars term_
-       term'    <- if bindThings && 
+       term'    <- if bindThings &&
                       False == isUnliftedTypeKind (termType term)
                      then bindSuspensions term
                      else return term
                       False == isUnliftedTypeKind (termType term)
                      then bindSuspensions term
                      else return term
@@ -84,6 +85,11 @@ pprintClosureCommand bindThings force str = do
        let reconstructed_type = termType term
        mb_subst <- withSession $ \hsc_env ->
                      liftIO $ improveRTTIType hsc_env (idType id) (reconstructed_type)
        let reconstructed_type = termType term
        mb_subst <- withSession $ \hsc_env ->
                      liftIO $ improveRTTIType hsc_env (idType id) (reconstructed_type)
+       maybe (return ())
+             (\subst -> traceOptIf Opt_D_dump_rtti
+                   (fsep $ [text "RTTI Improvement for", ppr id,
+                           text "is the substitution:" , ppr subst]))
+             mb_subst
        return (term', fromMaybe emptyTvSubst mb_subst)
 
    tidyTermTyVars :: GhcMonad m => Term -> m Term
        return (term', fromMaybe emptyTvSubst mb_subst)
 
    tidyTermTyVars :: GhcMonad m => Term -> m Term
@@ -110,11 +116,10 @@ bindSuspensions t = do
       availNames_var  <- liftIO $ newIORef availNames
       (t', stuff)     <- liftIO $ foldTerm (nameSuspensionsAndGetInfos availNames_var) t
       let (names, tys, hvals) = unzip3 stuff
       availNames_var  <- liftIO $ newIORef availNames
       (t', stuff)     <- liftIO $ foldTerm (nameSuspensionsAndGetInfos availNames_var) t
       let (names, tys, hvals) = unzip3 stuff
-      let tys' = map (fst.skolemiseTy) tys
+          (tys', skol_vars)   = unzip $ map skolemiseTy tys
       let ids = [ mkGlobalId VanillaGlobal name ty vanillaIdInfo
                 | (name,ty) <- zip names tys']
       let ids = [ mkGlobalId VanillaGlobal name ty vanillaIdInfo
                 | (name,ty) <- zip names tys']
-          new_tyvars   = tyVarsOfTypes tys'
-          new_ic       = extendInteractiveContext ictxt ids new_tyvars
+          new_ic = extendInteractiveContext ictxt ids (unionVarSets skol_vars)
       liftIO $ extendLinkEnv (zip names hvals)
       modifySession $ \_ -> hsc_env {hsc_IC = new_ic }
       return t'
       liftIO $ extendLinkEnv (zip names hvals)
       modifySession $ \_ -> hsc_env {hsc_IC = new_ic }
       return t'
@@ -194,7 +199,7 @@ showTerm term = do
     name <- newGrimName userName
     let ictxt    = hsc_IC hsc_env
         tmp_ids  = ic_tmp_ids ictxt
     name <- newGrimName userName
     let ictxt    = hsc_IC hsc_env
         tmp_ids  = ic_tmp_ids ictxt
-        id       = mkGlobalId VanillaGlobal name (sigmaType ty) vanillaIdInfo
+        id       = mkGlobalId VanillaGlobal name ty vanillaIdInfo
         new_ic   = ictxt { ic_tmp_ids = id : tmp_ids }
     return (hsc_env {hsc_IC = new_ic }, name)
 
         new_ic   = ictxt { ic_tmp_ids = id : tmp_ids }
     return (hsc_env {hsc_IC = new_ic }, name)
 
@@ -215,9 +220,17 @@ pprTypeAndContents ids = do
   if pcontents 
     then do
       let depthBound = 100
   if pcontents 
     then do
       let depthBound = 100
-      terms      <- mapM (GHC.obtainTermB depthBound False) ids
+      terms      <- mapM (GHC.obtainTermFromId depthBound False) ids
       docs_terms <- mapM showTerm terms
       return $ vcat $ zipWith (\ty cts -> ty <+> equals <+> cts)
                              (map (pprTyThing pefas . AnId) ids)
                              docs_terms
     else return $  vcat $ map (pprTyThing pefas . AnId) ids
       docs_terms <- mapM showTerm terms
       return $ vcat $ zipWith (\ty cts -> ty <+> equals <+> cts)
                              (map (pprTyThing pefas . AnId) ids)
                              docs_terms
     else return $  vcat $ map (pprTyThing pefas . AnId) ids
+
+--------------------------------------------------------------
+-- Utils 
+
+traceOptIf :: GhcMonad m => DynFlag -> SDoc -> m ()
+traceOptIf flag doc = do
+  dflags <- GHC.getSessionDynFlags
+  when (dopt flag dflags) $ liftIO $ printForUser stderr alwaysQualify doc
index 6be0633..164b9c5 100644 (file)
@@ -7,65 +7,50 @@
 -----------------------------------------------------------------------------
 
 module RtClosureInspect(
 -----------------------------------------------------------------------------
 
 module RtClosureInspect(
-  
      cvObtainTerm,      -- :: HscEnv -> Int -> Bool -> Maybe Type -> HValue -> IO Term
      cvObtainTerm,      -- :: HscEnv -> Int -> Bool -> Maybe Type -> HValue -> IO Term
-
-     Term(..),
-     isTerm,
-     isSuspension,
-     isPrim,
-     isNewtypeWrap,
-     pprTerm, 
-     cPprTerm, 
-     cPprTermBase,
-     CustomTermPrinter,
-     termType,
-     foldTerm, 
-     TermFold(..), 
-     idTermFold, 
-     idTermFoldM,
-     isFullyEvaluated, 
-     isPointed,
-     isFullyEvaluatedTerm,
-     mapTermType,
-     termTyVars,
---     unsafeDeepSeq, 
      cvReconstructType,
      improveRTTIType,
      cvReconstructType,
      improveRTTIType,
-     sigmaType,
-     Closure(..),
-     getClosureData,
-     ClosureType(..),
-     isConstr,
-     isIndirection
- ) where 
+
+     Term(..),
+     isTerm, isSuspension, isPrim, isFun, isFunLike, isNewtypeWrap,
+     isFullyEvaluated, isFullyEvaluatedTerm,
+     termType, mapTermType, termTyVars,
+     foldTerm, TermFold(..), foldTermM, TermFoldM(..), idTermFold,
+     pprTerm, cPprTerm, cPprTermBase, CustomTermPrinter,
+
+--     unsafeDeepSeq,
+
+     Closure(..), getClosureData, ClosureType(..), isConstr, isIndirection,
+
+     sigmaType
+ ) where
 
 #include "HsVersions.h"
 
 import ByteCodeItbls    ( StgInfoTable )
 import qualified ByteCodeItbls as BCI( StgInfoTable(..) )
 
 #include "HsVersions.h"
 
 import ByteCodeItbls    ( StgInfoTable )
 import qualified ByteCodeItbls as BCI( StgInfoTable(..) )
-import HscTypes         ( HscEnv )
+import HscTypes
 import Linker
 
 import DataCon
 import Type
 import Linker
 
 import DataCon
 import Type
+import TypeRep         -- I know I know, this is cheating
 import Var
 import TcRnMonad
 import TcType
 import TcMType
 import TcUnify
 import TcEnv
 import Var
 import TcRnMonad
 import TcType
 import TcMType
 import TcUnify
 import TcEnv
-import DriverPhases
+
 import TyCon
 import Name
 import VarEnv
 import Util
 import VarSet
 import TyCon
 import Name
 import VarEnv
 import Util
 import VarSet
-
 import TysPrim
 import PrelNames
 import TysWiredIn
 import TysPrim
 import PrelNames
 import TysWiredIn
-
+import DynFlags
 import Outputable
 import FastString
 import Panic
 import Outputable
 import FastString
 import Panic
@@ -80,7 +65,7 @@ import Control.Monad
 import Data.Maybe
 import Data.Array.Base
 import Data.Ix
 import Data.Maybe
 import Data.Array.Base
 import Data.Ix
-import Data.List        ( partition )
+import Data.List
 import qualified Data.Sequence as Seq
 import Data.Monoid
 import Data.Sequence hiding (null, length, index, take, drop, splitAt, reverse)
 import qualified Data.Sequence as Seq
 import Data.Monoid
 import Data.Sequence hiding (null, length, index, take, drop, splitAt, reverse)
@@ -91,11 +76,8 @@ import System.IO
 ---------------------------------------------
 -- * A representation of semi evaluated Terms
 ---------------------------------------------
 ---------------------------------------------
 -- * A representation of semi evaluated Terms
 ---------------------------------------------
-{-
-
--}
 
 
-data Term = Term { ty        :: Type 
+data Term = Term { ty        :: RttiType
                  , dc        :: Either String DataCon
                                -- Carries a text representation if the datacon is
                                -- not exported by the .hi file, which is the case 
                  , dc        :: Either String DataCon
                                -- Carries a text representation if the datacon is
                                -- not exported by the .hi file, which is the case 
@@ -103,21 +85,26 @@ data Term = Term { ty        :: Type
                  , val       :: HValue 
                  , subTerms  :: [Term] }
 
                  , val       :: HValue 
                  , subTerms  :: [Term] }
 
-          | Prim { ty        :: Type
+          | Prim { ty        :: RttiType
                  , value     :: [Word] }
 
           | Suspension { ctype    :: ClosureType
                  , value     :: [Word] }
 
           | Suspension { ctype    :: ClosureType
-                       , ty       :: Type
+                       , ty       :: RttiType
                        , val      :: HValue
                        , bound_to :: Maybe Name   -- Useful for printing
                        }
                        , val      :: HValue
                        , bound_to :: Maybe Name   -- Useful for printing
                        }
-          | NewtypeWrap{ ty           :: Type
+          | NewtypeWrap{       -- At runtime there are no newtypes, and hence no
+                               -- newtype constructors. A NewtypeWrap is just a
+                               -- made-up tag saying "heads up, there used to be
+                               -- a newtype constructor here".
+                         ty           :: RttiType
                        , dc           :: Either String DataCon
                        , wrapped_term :: Term }
                        , dc           :: Either String DataCon
                        , wrapped_term :: Term }
-          | RefWrap    { ty           :: Type
+          | RefWrap    {       -- The contents of a reference
+                         ty           :: RttiType
                        , wrapped_term :: Term }
 
                        , wrapped_term :: Term }
 
-isTerm, isSuspension, isPrim, isNewtypeWrap :: Term -> Bool
+isTerm, isSuspension, isPrim, isFun, isFunLike, isNewtypeWrap :: Term -> Bool
 isTerm Term{} = True
 isTerm   _    = False
 isSuspension Suspension{} = True
 isTerm Term{} = True
 isTerm   _    = False
 isSuspension Suspension{} = True
@@ -127,7 +114,13 @@ isPrim   _    = False
 isNewtypeWrap NewtypeWrap{} = True
 isNewtypeWrap _             = False
 
 isNewtypeWrap NewtypeWrap{} = True
 isNewtypeWrap _             = False
 
-termType :: Term -> Type
+isFun Suspension{ctype=Fun} = True
+isFun _ = False
+
+isFunLike s@Suspension{ty=ty} = isFun s || isFunTy ty
+isFunLike _ = False
+
+termType :: Term -> RttiType
 termType t = ty t
 
 isFullyEvaluatedTerm :: Term -> Bool
 termType t = ty t
 
 isFullyEvaluatedTerm :: Term -> Bool
@@ -153,6 +146,7 @@ data ClosureType = Constr
                  | PAP 
                  | Indirection Int 
                  | MutVar Int
                  | PAP 
                  | Indirection Int 
                  | MutVar Int
+                 | MVar   Int
                  | Other  Int
  deriving (Show, Eq)
 
                  | Other  Int
  deriving (Show, Eq)
 
@@ -209,7 +203,8 @@ readCType i
  | i' == aP_CODE                           = AP
  | i == AP_STACK                           = AP
  | i' == pAP_CODE                          = PAP
  | i' == aP_CODE                           = AP
  | i == AP_STACK                           = AP
  | i' == pAP_CODE                          = PAP
- | i == MUT_VAR_CLEAN || i == MUT_VAR_DIRTY     = MutVar i'
+ | i == MUT_VAR_CLEAN || i == MUT_VAR_DIRTY= MutVar i'
+ | i == MVAR_CLEAN    || i == MVAR_DIRTY   = MVar i'
  | otherwise                               = Other  i'
   where i' = fromIntegral i
  
  | otherwise                               = Other  i'
   where i' = fromIntegral i
  
@@ -234,11 +229,6 @@ isFullyEvaluated a = do
     _      -> return False
   where amapM f = sequence . amap' f
 
     _      -> return False
   where amapM f = sequence . amap' f
 
-amap' :: (t -> b) -> Array Int t -> [b]
-amap' f (Array i0 i _ arr#) = map g [0 .. i - i0]
-    where g (I# i#) = case indexArray# arr# i# of
-                          (# e #) -> f e
-
 -- TODO: Fix it. Probably the otherwise case is failing, trace/debug it
 {-
 unsafeDeepSeq :: a -> b -> b
 -- TODO: Fix it. Probably the otherwise case is failing, trace/debug it
 {-
 unsafeDeepSeq :: a -> b -> b
@@ -251,37 +241,30 @@ unsafeDeepSeq = unsafeDeepSeq1 2
                         closure -> foldl' (flip unsafeDeepSeq) b (ptrs closure)
         where tipe = unsafePerformIO (getClosureType a)
 -}
                         closure -> foldl' (flip unsafeDeepSeq) b (ptrs closure)
         where tipe = unsafePerformIO (getClosureType a)
 -}
-isPointed :: Type -> Bool
-isPointed t | Just (t, _) <- splitTyConApp_maybe t 
-            = not$ isUnliftedTypeKind (tyConKind t)
-isPointed _ = True
-
-extractUnboxed  :: [Type] -> Closure -> [[Word]]
-extractUnboxed tt clos = go tt (nonPtrs clos)
-   where sizeofType t
-           | Just (tycon,_) <- splitTyConApp_maybe t
-           = ASSERT (isPrimTyCon tycon) sizeofTyCon tycon
-           | otherwise = pprPanic "Expected a TcTyCon" (ppr t)
-         go [] _ = []
-         go (t:tt) xx 
-           | (x, rest) <- splitAt (sizeofType t) xx
-           = x : go tt rest
-
-sizeofTyCon :: TyCon -> Int -- in *words*
-sizeofTyCon = primRepSizeW . tyConPrimRep
 
 -----------------------------------
 -- * Traversals for Terms
 -----------------------------------
 
 -----------------------------------
 -- * Traversals for Terms
 -----------------------------------
-type TermProcessor a b = Type -> Either String DataCon -> HValue -> [a] -> b
+type TermProcessor a b = RttiType -> Either String DataCon -> HValue -> [a] -> b
 
 data TermFold a = TermFold { fTerm        :: TermProcessor a a
 
 data TermFold a = TermFold { fTerm        :: TermProcessor a a
-                           , fPrim        :: Type -> [Word] -> a
-                           , fSuspension  :: ClosureType -> Type -> HValue
+                           , fPrim        :: RttiType -> [Word] -> a
+                           , fSuspension  :: ClosureType -> RttiType -> HValue
                                             -> Maybe Name -> a
                                             -> Maybe Name -> a
-                           , fNewtypeWrap :: Type -> Either String DataCon
+                           , fNewtypeWrap :: RttiType -> Either String DataCon
                                             -> a -> a
                                             -> a -> a
-                           , fRefWrap     :: Type -> a -> a
+                           , fRefWrap     :: RttiType -> a -> a
+                           }
+
+
+data TermFoldM m a =
+                   TermFoldM {fTermM        :: TermProcessor a (m a)
+                            , fPrimM        :: RttiType -> [Word] -> m a
+                            , fSuspensionM  :: ClosureType -> RttiType -> HValue
+                                             -> Maybe Name -> m a
+                            , fNewtypeWrapM :: RttiType -> Either String DataCon
+                                            -> a -> m a
+                            , fRefWrapM     :: RttiType -> a -> m a
                            }
 
 foldTerm :: TermFold a -> Term -> a
                            }
 
 foldTerm :: TermFold a -> Term -> a
@@ -291,6 +274,14 @@ foldTerm tf (Suspension ct ty v b) = fSuspension tf ct ty v b
 foldTerm tf (NewtypeWrap ty dc t)  = fNewtypeWrap tf ty dc (foldTerm tf t)
 foldTerm tf (RefWrap ty t)         = fRefWrap tf ty (foldTerm tf t)
 
 foldTerm tf (NewtypeWrap ty dc t)  = fNewtypeWrap tf ty dc (foldTerm tf t)
 foldTerm tf (RefWrap ty t)         = fRefWrap tf ty (foldTerm tf t)
 
+
+foldTermM :: Monad m => TermFoldM m a -> Term -> m a
+foldTermM tf (Term ty dc v tt) = mapM (foldTermM tf) tt >>= fTermM tf ty dc v
+foldTermM tf (Prim ty    v   ) = fPrimM tf ty v
+foldTermM tf (Suspension ct ty v b) = fSuspensionM tf ct ty v b
+foldTermM tf (NewtypeWrap ty dc t)  = foldTermM tf t >>=  fNewtypeWrapM tf ty dc
+foldTermM tf (RefWrap ty t)         = foldTermM tf t >>= fRefWrapM tf ty
+
 idTermFold :: TermFold Term
 idTermFold = TermFold {
               fTerm = Term,
 idTermFold :: TermFold Term
 idTermFold = TermFold {
               fTerm = Term,
@@ -299,16 +290,8 @@ idTermFold = TermFold {
               fNewtypeWrap = NewtypeWrap,
               fRefWrap = RefWrap
                       }
               fNewtypeWrap = NewtypeWrap,
               fRefWrap = RefWrap
                       }
-idTermFoldM :: Monad m => TermFold (m Term)
-idTermFoldM = TermFold {
-              fTerm       = \ty dc v tt -> sequence tt >>= return . Term ty dc v,
-              fPrim       = (return.). Prim,
-              fSuspension = (((return.).).). Suspension,
-              fNewtypeWrap= \ty dc t -> NewtypeWrap ty dc `liftM` t,
-              fRefWrap    = \ty t -> RefWrap ty `liftM` t
-                       }
 
 
-mapTermType :: (Type -> Type) -> Term -> Term
+mapTermType :: (RttiType -> Type) -> Term -> Term
 mapTermType f = foldTerm idTermFold {
           fTerm       = \ty dc hval tt -> Term (f ty) dc hval tt,
           fSuspension = \ct ty hval n ->
 mapTermType f = foldTerm idTermFold {
           fTerm       = \ty dc hval tt -> Term (f ty) dc hval tt,
           fSuspension = \ct ty hval n ->
@@ -316,6 +299,15 @@ mapTermType f = foldTerm idTermFold {
           fNewtypeWrap= \ty dc t -> NewtypeWrap (f ty) dc t,
           fRefWrap    = \ty t -> RefWrap (f ty) t}
 
           fNewtypeWrap= \ty dc t -> NewtypeWrap (f ty) dc t,
           fRefWrap    = \ty t -> RefWrap (f ty) t}
 
+mapTermTypeM :: Monad m =>  (RttiType -> m Type) -> Term -> m Term
+mapTermTypeM f = foldTermM TermFoldM {
+          fTermM       = \ty dc hval tt -> f ty >>= \ty' -> return $ Term ty'  dc hval tt,
+          fPrimM       = (return.) . Prim,
+          fSuspensionM = \ct ty hval n ->
+                          f ty >>= \ty' -> return $ Suspension ct ty' hval n,
+          fNewtypeWrapM= \ty dc t -> f ty >>= \ty' -> return $ NewtypeWrap ty' dc t,
+          fRefWrapM    = \ty t -> f ty >>= \ty' -> return $ RefWrap ty' t}
+
 termTyVars :: Term -> TyVarSet
 termTyVars = foldTerm TermFold {
             fTerm       = \ty _ _ tt   -> 
 termTyVars :: Term -> TyVarSet
 termTyVars = foldTerm TermFold {
             fTerm       = \ty _ _ tt   -> 
@@ -375,9 +367,10 @@ ppr_termM _ _ t = ppr_termM1 t
 ppr_termM1 :: Monad m => Term -> m SDoc
 ppr_termM1 Prim{value=words, ty=ty} = 
     return$ text$ repPrim (tyConAppTyCon ty) words
 ppr_termM1 :: Monad m => Term -> m SDoc
 ppr_termM1 Prim{value=words, ty=ty} = 
     return$ text$ repPrim (tyConAppTyCon ty) words
-ppr_termM1 Suspension{bound_to=Nothing} = return$ char '_'
+ppr_termM1 Suspension{ty=ty, bound_to=Nothing} = 
+    return (char '_' <+> ifPprDebug (text "::" <> ppr ty))
 ppr_termM1 Suspension{ty=ty, bound_to=Just n}
 ppr_termM1 Suspension{ty=ty, bound_to=Just n}
-  | Just _ <- splitFunTy_maybe ty = return$ ptext (sLit "<function>")
+--  | Just _ <- splitFunTy_maybe ty = return$ ptext (sLit("<function>")
   | otherwise = return$ parens$ ppr n <> text "::" <> ppr ty
 ppr_termM1 Term{}        = panic "ppr_termM1 - Term"
 ppr_termM1 RefWrap{}     = panic "ppr_termM1 - RefWrap"
   | otherwise = return$ parens$ ppr n <> text "::" <> ppr ty
 ppr_termM1 Term{}        = panic "ppr_termM1 - Term"
 ppr_termM1 RefWrap{}     = panic "ppr_termM1 - RefWrap"
@@ -440,15 +433,15 @@ cPprTermBase y =
            ifTerm _ _ _ _  = return Nothing
 
            isIntegerTy ty  = fromMaybe False $ do
            ifTerm _ _ _ _  = return Nothing
 
            isIntegerTy ty  = fromMaybe False $ do
-             (tc,_) <- splitTyConApp_maybe ty 
+             (tc,_) <- tcSplitTyConApp_maybe ty 
              return (tyConName tc == integerTyConName)
 
            isTupleTy ty    = fromMaybe False $ do 
              return (tyConName tc == integerTyConName)
 
            isTupleTy ty    = fromMaybe False $ do 
-             (tc,_) <- splitTyConApp_maybe ty 
+             (tc,_) <- tcSplitTyConApp_maybe ty 
              return (isBoxedTupleTyCon tc)
 
            isTyCon a_tc ty = fromMaybe False $ do 
              return (isBoxedTupleTyCon tc)
 
            isTyCon a_tc ty = fromMaybe False $ do 
-             (tc,_) <- splitTyConApp_maybe ty
+             (tc,_) <- tcSplitTyConApp_maybe ty
              return (a_tc == tc)
 
            coerceShow f _p = return . text . show . f . unsafeCoerce# . val
              return (a_tc == tc)
 
            coerceShow f _p = return . text . show . f . unsafeCoerce# . val
@@ -527,18 +520,47 @@ The function congruenceNewtypes takes a shot at (b)
 -- The Type Reconstruction monad
 type TR a = TcM a
 
 -- The Type Reconstruction monad
 type TR a = TcM a
 
+-- A (non-mutable) tau type containing
+-- existentially quantified tyvars.
+--    (since GHC type language currently does not support
+--     existentials, we leave these variables unquantified)
+type RttiType = Type
+
+-- An incomplete type as stored in GHCi:
+--  no polymorphism: no quantifiers & all tyvars are skolem.
+type GhciType = Type
+{-
 runTR :: HscEnv -> TR a -> IO a
 runTR :: HscEnv -> TR a -> IO a
-runTR hsc_env c = do 
+runTR hsc_env c = do
   mb_term <- runTR_maybe hsc_env c
   case mb_term of 
   mb_term <- runTR_maybe hsc_env c
   case mb_term of 
-    Nothing -> panic "Can't unify"
+    Nothing -> panic "RTTI: Failed to reconstruct a term"
+    Just x  -> return x
+-}
+
+runTR :: HscEnv -> TR a -> IO a
+runTR hsc_env thing = do
+  mb_val <- runTR_maybe hsc_env thing
+  case mb_val of
+    Nothing -> error "RTTI error: probably due to :forcing an undefined"
     Just x  -> return x
 
 runTR_maybe :: HscEnv -> TR a -> IO (Maybe a)
 runTR_maybe hsc_env = fmap snd . initTc hsc_env HsSrcFile False  iNTERACTIVE
 
 traceTR :: SDoc -> TR ()
     Just x  -> return x
 
 runTR_maybe :: HscEnv -> TR a -> IO (Maybe a)
 runTR_maybe hsc_env = fmap snd . initTc hsc_env HsSrcFile False  iNTERACTIVE
 
 traceTR :: SDoc -> TR ()
-traceTR = liftTcM . traceTc
+traceTR = liftTcM . traceOptTcRn Opt_D_dump_rtti
+
+
+-- Semantically different to recoverM in TcRnMonad 
+-- recoverM retains the errors in the first action,
+--  whereas recoverTc here does not
+recoverTR :: TR a -> TR a -> TR a
+recoverTR recover thing = do 
+  (_,mb_res) <- tryTcErrs thing
+  case mb_res of 
+    Nothing  -> recover
+    Just res -> return res
 
 trIO :: IO a -> TR a 
 trIO = liftTcM . liftIO
 
 trIO :: IO a -> TR a 
 trIO = liftTcM . liftIO
@@ -547,13 +569,14 @@ liftTcM :: TcM a -> TR a
 liftTcM = id
 
 newVar :: Kind -> TR TcType
 liftTcM = id
 
 newVar :: Kind -> TR TcType
-newVar = liftTcM . fmap mkTyVarTy . newBoxyTyVar
+newVar = liftTcM . liftM mkTyVarTy . newBoxyTyVar
 
 -- | Returns the instantiated type scheme ty', and the substitution sigma 
 --   such that sigma(ty') = ty 
 instScheme :: Type -> TR (TcType, TvSubst)
 
 -- | Returns the instantiated type scheme ty', and the substitution sigma 
 --   such that sigma(ty') = ty 
 instScheme :: Type -> TR (TcType, TvSubst)
-instScheme ty | (tvs, _rho) <- tcSplitForAllTys ty = liftTcM$ do
-   (tvs',_theta,ty') <- tcInstType (mapM tcInstTyVar) ty
+instScheme ty = liftTcM$ do
+   (tvs, _, _)      <- tcInstType return ty
+   (tvs',_,ty') <- tcInstType (mapM tcInstTyVar) ty
    return (ty', zipTopTvSubst tvs' (mkTyVarTys tvs))
 
 -- Adds a constraint of the form t1 == t2
    return (ty', zipTopTvSubst tvs' (mkTyVarTys tvs))
 
 -- Adds a constraint of the form t1 == t2
@@ -562,34 +585,64 @@ instScheme ty | (tvs, _rho) <- tcSplitForAllTys ty = liftTcM$ do
 -- Before unification, congruenceNewtypes needs to
 -- do its magic.
 addConstraint :: TcType -> TcType -> TR ()
 -- Before unification, congruenceNewtypes needs to
 -- do its magic.
 addConstraint :: TcType -> TcType -> TR ()
-addConstraint t1 t2  = congruenceNewtypes t1 t2 >>= uncurry boxyUnify 
-                      >> return () -- TOMDO: what about the coercion?
-                                   -- we should consider family instances 
+addConstraint actual expected = do
+    traceTR $ fsep [text "add constraint:", ppr actual, equals, ppr expected]
+    recoverTR (traceTR $ fsep [text "Failed to unify", ppr actual,
+                                    text "with", ppr expected])
+              (congruenceNewtypes actual expected >>=
+                           uncurry boxyUnify >> return ())
+     -- TOMDO: what about the coercion?
+     -- we should consider family instances
 
 -- Type & Term reconstruction 
 
 -- Type & Term reconstruction 
-cvObtainTerm :: HscEnv -> Int -> Bool -> Maybe Type -> HValue -> IO Term
-cvObtainTerm hsc_env bound force mb_ty hval = runTR hsc_env $ do
-   tv <- newVar argTypeKind
-   case mb_ty of
-     Nothing ->      go bound tv tv hval 
-                >>= zonkTerm 
-                >>= return . expandNewtypes
-     Just ty | isMonomorphic ty ->     go bound ty ty hval 
-                                   >>= zonkTerm
-                                   >>= return . expandNewtypes
-     Just ty -> do 
-              (ty',rev_subst) <- instScheme (sigmaType ty)
-              addConstraint tv ty'
-              term <- go bound tv tv hval >>= zonkTerm
-              --restore original Tyvars
-              return$ expandNewtypes $ mapTermType (substTy rev_subst) term
+cvObtainTerm :: HscEnv -> Int -> Bool -> RttiType -> HValue -> IO Term
+cvObtainTerm hsc_env max_depth force old_ty hval = runTR hsc_env $ do
+  -- we quantify existential tyvars as universal,
+  -- as this is needed to be able to manipulate
+  -- them properly
+   let sigma_old_ty = sigmaType old_ty
+   traceTR (text "Term reconstruction started with initial type " <> ppr old_ty)
+   term <-
+     if isMonomorphic sigma_old_ty
+      then do
+        new_ty <- go max_depth sigma_old_ty sigma_old_ty hval >>= zonkTerm
+        return $ fixFunDictionaries $ expandNewtypes new_ty
+      else do
+              (old_ty', rev_subst) <- instScheme sigma_old_ty
+              my_ty <- newVar argTypeKind
+              when (check1 sigma_old_ty) (traceTR (text "check1 passed") >>
+                                          addConstraint my_ty old_ty')
+              term  <- go max_depth my_ty sigma_old_ty hval
+              zterm <- zonkTerm term
+              let new_ty = termType zterm
+              if isMonomorphic new_ty || check2 (sigmaType new_ty) sigma_old_ty
+                 then do
+                      traceTR (text "check2 passed")
+                      addConstraint (termType term) old_ty'
+                      zterm' <- zonkTerm term
+                      return ((fixFunDictionaries . expandNewtypes . mapTermType (substTy rev_subst)) zterm')
+                 else do
+                      traceTR (text "check2 failed" <+> parens
+                                       (ppr zterm <+> text "::" <+> ppr new_ty))
+                      -- we have unsound types. Replace constructor types in
+                      -- subterms with tyvars
+                      zterm' <- mapTermTypeM
+                                 (\ty -> case tcSplitTyConApp_maybe ty of
+                                           Just (tc, _:_) | tc /= funTyCon
+                                               -> newVar argTypeKind
+                                           _   -> return ty)
+                                 zterm
+                      zonkTerm zterm'
+   traceTR (text "Term reconstruction completed. Term obtained: " <> ppr term)
+   return term
     where 
     where 
-  go bound _ _ _ | seq bound False = undefined
-  go 0 tv _ty a = do
+  go :: Int -> Type -> Type -> HValue -> TcM Term
+  go max_depth _ _ _ | seq max_depth False = undefined
+  go 0 my_ty _old_ty a = do
     clos <- trIO $ getClosureData a
     clos <- trIO $ getClosureData a
-    return (Suspension (tipe clos) tv a Nothing)
-  go bound tv ty a = do 
-    let monomorphic = not(isTyVarTy tv)   
+    return (Suspension (tipe clos) my_ty a Nothing)
+  go max_depth my_ty old_ty a = do 
+    let monomorphic = not(isTyVarTy my_ty)   
     -- This ^^^ is a convention. The ancestor tests for
     -- monomorphism and passes a type instead of a tv
     clos <- trIO $ getClosureData a
     -- This ^^^ is a convention. The ancestor tests for
     -- monomorphism and passes a type instead of a tv
     clos <- trIO $ getClosureData a
@@ -598,21 +651,31 @@ cvObtainTerm hsc_env bound force mb_ty hval = runTR hsc_env $ do
 -- NB. this won't attempt to force a BLACKHOLE.  Even with :force, we never
 -- force blackholes, because it would almost certainly result in deadlock,
 -- and showing the '_' is more useful.
 -- NB. this won't attempt to force a BLACKHOLE.  Even with :force, we never
 -- force blackholes, because it would almost certainly result in deadlock,
 -- and showing the '_' is more useful.
-      t | isThunk t && force -> seq a $ go (pred bound) tv ty a
--- We always follow indirections 
-      Indirection _ -> go bound tv ty $! (ptrs clos ! 0)
+      t | isThunk t && force -> traceTR (text "Forcing a " <> text (show t)) >>
+                                seq a (go (pred max_depth) my_ty old_ty a)
+-- We always follow indirections
+      Indirection i -> do traceTR (text "Following an indirection" <> parens (int i) )
+                          go max_depth my_ty old_ty $! (ptrs clos ! 0)
 -- We also follow references
 -- We also follow references
-      MutVar _ | Just (tycon,[world,ty_contents]) <- splitTyConApp_maybe ty
-                -- , tycon == mutVarPrimTyCon 
+      MutVar _ | Just (tycon,[world,contents_ty]) <- tcSplitTyConApp_maybe old_ty
              -> do
              -> do
+                  -- Deal with the MutVar# primitive
+                  -- It does not have a constructor at all, 
+                  -- so we simulate the following one
+                  -- MutVar# :: contents_ty -> MutVar# s contents_ty
+         traceTR (text "Following a MutVar")
+         contents_tv <- newVar liftedTypeKind
          contents <- trIO$ IO$ \w -> readMutVar# (unsafeCoerce# a) w
          contents <- trIO$ IO$ \w -> readMutVar# (unsafeCoerce# a) w
-         tv' <- newVar liftedTypeKind
-         addConstraint tv (mkTyConApp tycon [world,tv'])
-         x <- go bound tv' ty_contents contents
-         return (RefWrap ty x)
+         ASSERT(isUnliftedTypeKind $ typeKind my_ty) return ()
+         (mutvar_ty,_) <- instScheme $ sigmaType $ mkFunTy 
+                            contents_ty (mkTyConApp tycon [world,contents_ty])
+         addConstraint (mkFunTy contents_tv my_ty) mutvar_ty
+         x <- go (pred max_depth) contents_tv contents_ty contents
+         return (RefWrap my_ty x)
 
  -- The interesting case
       Constr -> do
 
  -- The interesting case
       Constr -> do
+        traceTR (text "entering a constructor")
         Right dcname <- dataConInfoPtrToName (infoPtr clos)
         (_,mb_dc)    <- tryTcErrs (tcLookupDataCon dcname)
         case mb_dc of
         Right dcname <- dataConInfoPtrToName (infoPtr clos)
         (_,mb_dc)    <- tryTcErrs (tcLookupDataCon dcname)
         case mb_dc of
@@ -624,94 +687,107 @@ cvObtainTerm hsc_env bound force mb_ty hval = runTR hsc_env $ do
                        let tag = showSDoc (ppr dcname)
                        vars     <- replicateM (length$ elems$ ptrs clos) 
                                               (newVar (liftedTypeKind))
                        let tag = showSDoc (ppr dcname)
                        vars     <- replicateM (length$ elems$ ptrs clos) 
                                               (newVar (liftedTypeKind))
-                       subTerms <- sequence [appArr (go (pred bound) tv tv) (ptrs clos) i 
+                       subTerms <- sequence [appArr (go (pred max_depth) tv tv) (ptrs clos) i 
                                               | (i, tv) <- zip [0..] vars]
                                               | (i, tv) <- zip [0..] vars]
-                       return (Term tv (Left ('<' : tag ++ ">")) a subTerms)
-          Just dc -> do 
-            let extra_args = length(dataConRepArgTys dc) - 
-                             length(dataConOrigArgTys dc)
-                subTtypes  = matchSubTypes dc ty
-                (subTtypesP, subTtypesNP) = partition isPointed subTtypes
-            subTermTvs <- sequence
-                 [ if isMonomorphic t then return t 
-                                      else (newVar k)
-                   | (t,k) <- zip subTtypesP (map typeKind subTtypesP)]
+                       return (Term my_ty (Left ('<' : tag ++ ">")) a subTerms)
+          Just dc -> do
+            let subTtypes  = matchSubTypes dc old_ty
+                (subTtypesP, subTtypesNP) = partition (isLifted |.| isRefType) subTtypes
+            subTermTvs    <- mapMif (not . isMonomorphic)
+                                    (\t -> newVar (typeKind t))
+                                    subTtypes
             -- It is vital for newtype reconstruction that the unification step
             -- It is vital for newtype reconstruction that the unification step
-            --  is done right here, _before_ the subterms are RTTI reconstructed
+            -- is done right here, _before_ the subterms are RTTI reconstructed
             when (not monomorphic) $ do
             when (not monomorphic) $ do
-                  let myType = mkFunTys (reOrderTerms subTermTvs 
-                                                      subTtypesNP 
-                                                      subTtypes) 
-                                        tv
-                  (signatureType,_) <- instScheme(dataConRepType dc) 
-                  addConstraint myType signatureType
-            subTermsP <- sequence $ drop extra_args 
-                                -- \^^^  all extra arguments are pointed
-                  [ appArr (go (pred bound) tv t) (ptrs clos) i
+
+                       -- When we already have all the information, avoid solving
+                       -- unnecessary constraints. Propagation of type information
+                       -- to subterms is already being done via matching.
+               let myType = mkFunTys subTermTvs my_ty
+               (signatureType,_) <- instScheme (rttiView $ dataConUserType dc)
+               addConstraint myType signatureType
+            subTermsP <- sequence
+                  [ appArr (go (pred max_depth) tv t) (ptrs clos) i
                    | (i,tv,t) <- zip3 [0..] subTermTvs subTtypesP]
             let unboxeds   = extractUnboxed subTtypesNP clos
                 subTermsNP = map (uncurry Prim) (zip subTtypesNP unboxeds)      
                    | (i,tv,t) <- zip3 [0..] subTermTvs subTtypesP]
             let unboxeds   = extractUnboxed subTtypesNP clos
                 subTermsNP = map (uncurry Prim) (zip subTtypesNP unboxeds)      
-                subTerms   = reOrderTerms subTermsP subTermsNP 
-                                (drop extra_args subTtypes)
-            return (Term tv (Right dc) a subTerms)
+                subTerms   = reOrderTerms subTermsP subTermsNP subTtypes
+            return (Term my_ty (Right dc) a subTerms)
 -- The otherwise case: can be a Thunk,AP,PAP,etc.
       tipe_clos ->
 -- The otherwise case: can be a Thunk,AP,PAP,etc.
       tipe_clos ->
-         return (Suspension tipe_clos tv a Nothing)
+         return (Suspension tipe_clos my_ty a Nothing)
 
   matchSubTypes dc ty
 
   matchSubTypes dc ty
-    | Just (_,ty_args) <- splitTyConApp_maybe (repType ty) 
---     assumption:             ^^^ looks through newtypes 
-    , isVanillaDataCon dc  --TODO non-vanilla case
-    = dataConInstArgTys dc ty_args
+    | ty' <- repType ty     -- look through newtypes
+    , Just (tc,ty_args) <- tcSplitTyConApp_maybe ty'
+    , dc `elem` tyConDataCons tc
+      -- It is necessary to check that dc is actually a constructor for tycon tc,
+      -- because it may be the case that tc is a recursive newtype and tcSplitTyConApp
+      -- has not removed it. In that case, we happily give up and don't match
+    = myDataConInstArgTys dc ty_args
     | otherwise = dataConRepArgTys dc
 
     | otherwise = dataConRepArgTys dc
 
--- This is used to put together pointed and nonpointed subterms in the 
---  correct order.
+  -- put together pointed and nonpointed subterms in the
+  --  correct order.
   reOrderTerms _ _ [] = []
   reOrderTerms pointed unpointed (ty:tys) 
   reOrderTerms _ _ [] = []
   reOrderTerms pointed unpointed (ty:tys) 
-   | isPointed ty = ASSERT2(not(null pointed)
+   | isLifted ty || isRefType ty
+                  = ASSERT2(not(null pointed)
                             , ptext (sLit "reOrderTerms") $$ 
                                         (ppr pointed $$ ppr unpointed))
                     let (t:tt) = pointed in t : reOrderTerms tt unpointed tys
    | otherwise    = ASSERT2(not(null unpointed)
                             , ptext (sLit "reOrderTerms") $$ 
                                         (ppr pointed $$ ppr unpointed))
                     let (t:tt) = pointed in t : reOrderTerms tt unpointed tys
    | otherwise    = ASSERT2(not(null unpointed)
-                           , ptext (sLit "reOrderTerms") $$ 
+                           , ptext (sLit "Reorderterms") $$ 
                                        (ppr pointed $$ ppr unpointed))
                     let (t:tt) = unpointed in t : reOrderTerms pointed tt tys
                                        (ppr pointed $$ ppr unpointed))
                     let (t:tt) = unpointed in t : reOrderTerms pointed tt tys
-  
-  expandNewtypes t@Term{ ty=ty, subTerms=tt }
-   | Just (tc, args) <- tcSplitTyConApp_maybe ty
-   , isNewTyCon tc
-   , wrapped_type    <- newTyConInstRhs tc args
-   , Just dc         <- tyConSingleDataCon_maybe tc
-   , t'              <- expandNewtypes t{ ty = wrapped_type
-                                        , subTerms = map expandNewtypes tt }
-   = NewtypeWrap ty (Right dc) t'
 
 
-   | otherwise = t{ subTerms = map expandNewtypes tt }
+  -- insert NewtypeWraps around newtypes
+  expandNewtypes = foldTerm idTermFold { fTerm = worker } where
+   worker ty dc hval tt
+     | Just (tc, args) <- tcSplitTyConApp_maybe ty
+     , isNewTyCon tc
+     , wrapped_type    <- newTyConInstRhs tc args
+     , Just dc'        <- tyConSingleDataCon_maybe tc
+     , t'              <- worker wrapped_type dc hval tt
+     = NewtypeWrap ty (Right dc') t'
+     | otherwise = Term ty dc hval tt
+
 
 
-  expandNewtypes t = t
+   -- Avoid returning types where predicates have been expanded to dictionaries.
+  fixFunDictionaries = foldTerm idTermFold {fSuspension = worker} where
+      worker ct ty hval n | isFunTy ty = Suspension ct (dictsView ty) hval n
+                          | otherwise  = Suspension ct ty hval n
 
 
 -- Fast, breadth-first Type reconstruction
 
 
 -- Fast, breadth-first Type reconstruction
-cvReconstructType :: HscEnv -> Int -> Maybe Type -> HValue -> IO (Maybe Type)
-cvReconstructType hsc_env max_depth mb_ty hval = runTR_maybe hsc_env $ do
-   tv <- newVar argTypeKind
-   case mb_ty of
-     Nothing -> do search (isMonomorphic `fmap` zonkTcType tv)
-                          (uncurry go)
-                          (Seq.singleton (tv, hval))
-                          max_depth
-                   zonkTcType tv  -- TODO untested!
-     Just ty | isMonomorphic ty -> return ty
-     Just ty -> do
-              (ty',rev_subst) <- instScheme (sigmaType ty)
-              addConstraint tv ty'
-              search (isMonomorphic `fmap` zonkTcType tv)
-                     (\(ty,a) -> go ty a)
-                     (Seq.singleton (tv, hval))
-                     max_depth
-              substTy rev_subst `fmap` zonkTcType tv
-    where 
+cvReconstructType :: HscEnv -> Int -> GhciType -> HValue -> IO (Maybe Type)
+cvReconstructType hsc_env max_depth old_ty hval = runTR_maybe hsc_env $ do
+   traceTR (text "RTTI started with initial type " <> ppr old_ty)
+   let sigma_old_ty = sigmaType old_ty
+   new_ty <-
+       if isMonomorphic sigma_old_ty
+        then return old_ty
+        else do
+          (old_ty', rev_subst) <- instScheme sigma_old_ty
+          my_ty <- newVar argTypeKind
+          when (check1 sigma_old_ty) (traceTR (text "check1 passed") >>
+                                      addConstraint my_ty old_ty')
+          search (isMonomorphic `fmap` zonkTcType my_ty)
+                 (\(ty,a) -> go ty a)
+                 (Seq.singleton (my_ty, hval))
+                 max_depth
+          new_ty <- zonkTcType my_ty
+          if isMonomorphic new_ty || check2 (sigmaType new_ty) sigma_old_ty
+            then do
+                 traceTR (text "check2 passed")
+                 addConstraint my_ty old_ty'
+                 new_ty' <- zonkTcType my_ty
+                 return (substTy rev_subst new_ty')
+            else traceTR (text "check2 failed" <+> parens (ppr new_ty)) >>
+                 return old_ty
+   traceTR (text "RTTI completed. Type obtained:" <+> ppr new_ty)
+   return new_ty
+    where
 --  search :: m Bool -> ([a] -> [a] -> [a]) -> [a] -> m ()
   search _ _ _ 0 = traceTR (text "Failed to reconstruct a type after " <>
                                 int max_depth <> text " steps")
 --  search :: m Bool -> ([a] -> [a] -> [a]) -> [a] -> m ()
   search _ _ _ 0 = traceTR (text "Failed to reconstruct a type after " <>
                                 int max_depth <> text " steps")
@@ -724,16 +800,15 @@ cvReconstructType hsc_env max_depth mb_ty hval = runTR_maybe hsc_env $ do
 
    -- returns unification tasks,since we are going to want a breadth-first search
   go :: Type -> HValue -> TR [(Type, HValue)]
 
    -- returns unification tasks,since we are going to want a breadth-first search
   go :: Type -> HValue -> TR [(Type, HValue)]
-  go tv a = do
+  go my_ty a = do
     clos <- trIO $ getClosureData a
     case tipe clos of
     clos <- trIO $ getClosureData a
     case tipe clos of
-      Indirection _ -> go tv $! (ptrs clos ! 0)
+      Indirection _ -> go my_ty $! (ptrs clos ! 0)
       MutVar _ -> do
          contents <- trIO$ IO$ \w -> readMutVar# (unsafeCoerce# a) w
          tv'   <- newVar liftedTypeKind
          world <- newVar liftedTypeKind
       MutVar _ -> do
          contents <- trIO$ IO$ \w -> readMutVar# (unsafeCoerce# a) w
          tv'   <- newVar liftedTypeKind
          world <- newVar liftedTypeKind
-         addConstraint tv (mkTyConApp mutVarPrimTyCon [world,tv'])
---         x <- go tv' ty_contents contents
+         addConstraint my_ty (mkTyConApp mutVarPrimTyCon [world,tv'])
          return [(tv', contents)]
       Constr -> do
         Right dcname <- dataConInfoPtrToName (infoPtr clos)
          return [(tv', contents)]
       Constr -> do
         Right dcname <- dataConInfoPtrToName (infoPtr clos)
@@ -746,44 +821,187 @@ cvReconstructType hsc_env max_depth mb_ty hval = runTR_maybe hsc_env $ do
                         return$ appArr (\e->(tv,e)) (ptrs clos) i
 
           Just dc -> do
                         return$ appArr (\e->(tv,e)) (ptrs clos) i
 
           Just dc -> do
-            let extra_args = length(dataConRepArgTys dc) -
-                             length(dataConOrigArgTys dc)
             subTtypes <- mapMif (not . isMonomorphic)
                                 (\t -> newVar (typeKind t))
                                 (dataConRepArgTys dc)
 
             -- It is vital for newtype reconstruction that the unification step
             -- is done right here, _before_ the subterms are RTTI reconstructed
             subTtypes <- mapMif (not . isMonomorphic)
                                 (\t -> newVar (typeKind t))
                                 (dataConRepArgTys dc)
 
             -- It is vital for newtype reconstruction that the unification step
             -- is done right here, _before_ the subterms are RTTI reconstructed
-            let myType         = mkFunTys subTtypes tv
-            (signatureType,_) <- instScheme(dataConRepType dc) 
+            let myType         = mkFunTys subTtypes my_ty
+            (signatureType,_) <- instScheme(rttiView $ dataConUserType dc)
             addConstraint myType signatureType
             return $ [ appArr (\e->(t,e)) (ptrs clos) i
             addConstraint myType signatureType
             return $ [ appArr (\e->(t,e)) (ptrs clos) i
-                       | (i,t) <- drop extra_args $ 
-                                     zip [0..] (filter isPointed subTtypes)]
+                       | (i,t) <- zip [0..] (filter (isLifted |.| isRefType) subTtypes)]
       _ -> return []
 
 -- Compute the difference between a base type and the type found by RTTI
 -- improveType <base_type> <rtti_type>
 -- The types can contain skolem type variables, which need to be treated as normal vars.
 -- In particular, we want them to unify with things.
       _ -> return []
 
 -- Compute the difference between a base type and the type found by RTTI
 -- improveType <base_type> <rtti_type>
 -- The types can contain skolem type variables, which need to be treated as normal vars.
 -- In particular, we want them to unify with things.
-improveRTTIType :: HscEnv -> Type -> Type -> IO (Maybe TvSubst)
-improveRTTIType hsc_env ty rtti_ty = runTR_maybe hsc_env $ do
-    let (_,ty0)     = splitForAllTys ty
-        ty_tvs      = varSetElems $ tyVarsOfType ty0
-    let (_,rtti_ty0)= splitForAllTys rtti_ty
-        rtti_tvs    = varSetElems $ tyVarsOfType rtti_ty0
-    (ty_tvs',_,ty')<- tcInstType (mapM tcInstTyVar) (mkSigmaTy ty_tvs   [] ty0)
-    (_,_,rtti_ty') <- tcInstType (mapM tcInstTyVar) (mkSigmaTy rtti_tvs [] rtti_ty0)
+improveRTTIType :: HscEnv -> RttiType -> RttiType -> IO (Maybe TvSubst)
+improveRTTIType hsc_env _ty rtti_ty = runTR_maybe hsc_env $ do
+    traceTR $ fsep [text "improveRttiType", ppr _ty, ppr rtti_ty]
+    (ty_tvs,  _, _)   <- tcInstType return ty
+    (ty_tvs', _, ty') <- tcInstType (mapM tcInstTyVar) ty
+    (_, _, rtti_ty')  <- tcInstType (mapM tcInstTyVar) (sigmaType rtti_ty)
     boxyUnify rtti_ty' ty'
     boxyUnify rtti_ty' ty'
-    tvs1_contents  <- zonkTcTyVars ty_tvs'
-    let subst = uncurry zipTopTvSubst
-                  (unzip [(tv,ty) | tv <- ty_tvs, ty <- tvs1_contents
-                                  , getTyVar_maybe ty /= Just tv
-                                  , not(isTyVarTy ty)])
---    liftIO $ hPutStrLn stderr $ showSDocDebug $ text "unify " <+> sep [ppr ty, ppr rtti_ty, equals, ppr subst ]
+    tvs1_contents     <- zonkTcTyVars ty_tvs'
+    let subst = (uncurry zipTopTvSubst . unzip)
+                 [(tv,ty) | (tv,ty) <- zip ty_tvs tvs1_contents
+                          , getTyVar_maybe ty /= Just tv
+                          --, not(isTyVarTy ty)
+                          ]
     return subst
     return subst
+ where ty = sigmaType _ty
+
+myDataConInstArgTys :: DataCon -> [Type] -> [Type]
+myDataConInstArgTys dc args
+    | null (dataConExTyVars dc) && null (dataConEqTheta dc) = dataConInstArgTys dc args
+    | otherwise = dataConRepArgTys dc
+
+isRefType :: Type -> Bool
+isRefType ty
+   | Just (tc, _) <- tcSplitTyConApp_maybe ty' = isRefTyCon tc
+   | otherwise = False
+  where ty'= repType ty
+
+isRefTyCon :: TyCon -> Bool
+isRefTyCon tc = tc `elem` [mutVarPrimTyCon, mVarPrimTyCon, tVarPrimTyCon]
+
+-- Soundness checks
+--------------------
+{-
+This is not formalized anywhere, so hold to your seats!
+RTTI in the presence of newtypes can be a tricky and unsound business.
+
+Example:
+~~~~~~~~~
+Suppose we are doing RTTI for a partially evaluated
+closure t, the real type of which is t :: MkT Int, for
+
+   newtype MkT a = MkT [Maybe a]
+
+The table below shows the results of RTTI and the improvement
+calculated for different combinations of evaluatedness and :type t.
+Regard the two first columns as input and the next two as output.
+
+  # |     t     |  :type t  | rtti(t)  | improv.    | result
+    ------------------------------------------------------------
+  1 |     _     |    t b    |    a     | none       | OK
+  2 |     _     |   MkT b   |    a     | none       | OK
+  3 |     _     |   t Int   |    a     | none       | OK
+
+  If t is not evaluated at *all*, we are safe.
+
+  4 |  (_ : _)  |    t b    |   [a]    | t = []     | UNSOUND
+  5 |  (_ : _)  |   MkT b   |  MkT a   | none       | OK (compensating for the missing newtype)
+  6 |  (_ : _)  |   t Int   |  [Int]   | t = []     | UNSOUND
+
+  If a is a minimal whnf, we run into trouble. Note that
+  row 5 above does newtype enrichment on the ty_rtty parameter.
+
+  7 | (Just _:_)|    t b    |[Maybe a] | t = [],    | UNSOUND
+    |                       |          | b = Maybe a|
+
+  8 | (Just _:_)|   MkT b   |  MkT a   |  none      | OK
+  9 | (Just _:_)|   t Int   |   FAIL   |  none      | OK
+
+  And if t is any more evaluated than whnf, we are still in trouble.
+  Because constraints are solved in top-down order, when we reach the
+  Maybe subterm what we got is already unsound. This explains why the
+  row 9 fails to complete.
+
+  10 | (Just _:_)|  t Int  | [Maybe a]   |  FAIL    | OK
+  11 | (Just 1:_)|  t Int  | [Maybe Int] |  FAIL    | OK
+
+  We can undo the failure in row 9 by leaving out the constraint
+  coming from the type signature of t (i.e., the 2nd column).
+  Note that this type information is still used
+  to calculate the improvement. But we fail
+  when trying to calculate the improvement, as there is no unifier for
+  t Int = [Maybe a] or t Int = [Maybe Int].
+
+
+  Another set of examples with t :: [MkT (Maybe Int)]  \equiv  [[Maybe (Maybe Int)]]
+
+  # |     t     |    :type t    |  rtti(t)    | improvement | result
+    ---------------------------------------------------------------------
+  1 |(Just _:_) | [t (Maybe a)] | [[Maybe b]] | t = []      |
+    |           |               |             | b = Maybe a |
+
+The checks:
+~~~~~~~~~~~
+Consider a function obtainType that takes a value and a type and produces
+the Term representation and a substitution (the improvement).
+Assume an auxiliar rtti' function which does the actual job if recovering
+the type, but which may produce a false type.
+
+In pseudocode:
+
+  rtti' :: a -> IO Type  -- Does not use the static type information
+
+  obtainType :: a -> Type -> IO (Maybe (Term, Improvement))
+  obtainType v old_ty = do
+       rtti_ty <- rtti' v
+       if monomorphic rtti_ty || (check rtti_ty old_ty)
+        then ...
+         else return Nothing
+  where check rtti_ty old_ty = check1 rtti_ty &&
+                              check2 rtti_ty old_ty
+
+  check1 :: Type -> Bool
+  check2 :: Type -> Type -> Bool
+
+Now, if rtti' returns a monomorphic type, we are safe.
+If that is not the case, then we consider two conditions.
+
+
+1. To prevent the class of unsoundness displayed by
+   rows 4 and 7 in the example: no higher kind tyvars
+   accepted.
+
+  check1 (t a)   = NO
+  check1 (t Int) = NO
+  check1 ([] a)  = YES
+
+2. To prevent the class of unsoundness shown by row 6,
+   the rtti type should be structurally more
+   defined than the old type we are comparing it to.
+  check2 :: OldType -> NewTy            pe -> Bool
+  check2 a  _        = True
+  check2 [a] a       = True
+  check2 [a] (t Int) = False
+  check2 [a] (t a)   = False  -- By check1 we never reach this equation
+  check2 [Int] a     = True
+  check2 [Int] (t Int) = True
+  check2 [Maybe a]   (t Int) = False
+  check2 [Maybe Int] (t Int) = True
+  check2 (Maybe [a])   (m [Int]) = False
+  check2 (Maybe [Int]) (m [Int]) = True
+
+-}
+
+check1 :: Type -> Bool
+check1 ty | (tvs, _, _) <- tcSplitSigmaTy ty = not $ any isHigherKind (map tyVarKind tvs)
+ where
+   isHigherKind = not . null . fst . splitKindFunTys
+
+check2 :: Type -> Type -> Bool
+check2 sigma_rtti_ty sigma_old_ty
+  | Just (_, rttis) <- tcSplitTyConApp_maybe rtti_ty
+  = case () of
+      _ | Just (_,olds) <- tcSplitTyConApp_maybe old_ty
+        -> and$ zipWith check2 rttis olds
+      _ | Just _ <- splitAppTy_maybe old_ty
+        -> isMonomorphicOnNonPhantomArgs rtti_ty
+      _ -> True
+  | otherwise = True
+  where (_, _ , rtti_ty) = tcSplitSigmaTy sigma_rtti_ty
+        (_, _ , old_ty)  = tcSplitSigmaTy sigma_old_ty
+
 
 -- Dealing with newtypes
 
 -- Dealing with newtypes
+--------------------------
 {-
  congruenceNewtypes does a parallel fold over two Type values, 
  compensating for missing newtypes on both sides. 
 {-
  congruenceNewtypes does a parallel fold over two Type values, 
  compensating for missing newtypes on both sides. 
@@ -813,53 +1031,112 @@ Therefore, congruenceNewtypes is sound only if the types
 recovered by the RTTI mechanism are unified Top-Down.
 -}
 congruenceNewtypes ::  TcType -> TcType -> TR (TcType,TcType)
 recovered by the RTTI mechanism are unified Top-Down.
 -}
 congruenceNewtypes ::  TcType -> TcType -> TR (TcType,TcType)
-congruenceNewtypes lhs rhs 
+congruenceNewtypes lhs rhs = go lhs rhs >>= \rhs' -> return (lhs,rhs')
+ where
+   go l r
  -- TyVar lhs inductive case
  -- TyVar lhs inductive case
-    | Just tv <- getTyVar_maybe lhs 
-    = recoverTc (return (lhs,rhs)) $ do  
+    | Just tv <- getTyVar_maybe l
+    = recoverTR (return r) $ do
          Indirect ty_v <- readMetaTyVar tv
          Indirect ty_v <- readMetaTyVar tv
-         (_lhs1, rhs1) <- congruenceNewtypes ty_v rhs
-         return (lhs, rhs1)
+         traceTR $ fsep [text "(congruence) Following indirect tyvar:",
+                          ppr tv, equals, ppr ty_v]
+         go ty_v r
 -- FunTy inductive case
 -- FunTy inductive case
-    | Just (l1,l2) <- splitFunTy_maybe lhs
-    , Just (r1,r2) <- splitFunTy_maybe rhs
-    = do (l2',r2') <- congruenceNewtypes l2 r2
-         (l1',r1') <- congruenceNewtypes l1 r1
-         return (mkFunTy l1' l2', mkFunTy r1' r2')
+    | Just (l1,l2) <- splitFunTy_maybe l
+    , Just (r1,r2) <- splitFunTy_maybe r
+    = do r2' <- go l2 r2
+         r1' <- go l1 r1
+         return (mkFunTy r1' r2')
 -- TyconApp Inductive case; this is the interesting bit.
     | Just (tycon_l, _) <- tcSplitTyConApp_maybe lhs
     , Just (tycon_r, _) <- tcSplitTyConApp_maybe rhs 
     , tycon_l /= tycon_r 
 -- TyconApp Inductive case; this is the interesting bit.
     | Just (tycon_l, _) <- tcSplitTyConApp_maybe lhs
     , Just (tycon_r, _) <- tcSplitTyConApp_maybe rhs 
     , tycon_l /= tycon_r 
-    = do rhs' <- upgrade tycon_l rhs
-         return (lhs, rhs')
+    = upgrade tycon_l r
 
 
-    | otherwise = return (lhs,rhs)
+    | otherwise = return r
 
     where upgrade :: TyCon -> Type -> TR Type
           upgrade new_tycon ty
 
     where upgrade :: TyCon -> Type -> TR Type
           upgrade new_tycon ty
-            | not (isNewTyCon new_tycon) = return ty 
-            | otherwise = do 
+            | not (isNewTyCon new_tycon) = do
+              traceTR (text "(Upgrade) Not matching newtype evidence: " <>
+                       ppr new_tycon <> text " for " <> ppr ty)
+              return ty 
+            | otherwise = do
+               traceTR (text "(Upgrade) upgraded " <> ppr ty <>
+                        text " in presence of newtype evidence " <> ppr new_tycon)
                vars <- mapM (newVar . tyVarKind) (tyConTyVars new_tycon)
                let ty' = mkTyConApp new_tycon vars
                vars <- mapM (newVar . tyVarKind) (tyConTyVars new_tycon)
                let ty' = mkTyConApp new_tycon vars
-               liftTcM (unifyType ty (repType ty'))
+               liftTcM (boxyUnify ty (repType ty'))
         -- assumes that reptype doesn't ^^^^ touch tyconApp args 
                return ty'
 
 
         -- assumes that reptype doesn't ^^^^ touch tyconApp args 
                return ty'
 
 
+zonkTerm :: Term -> TcM Term
+zonkTerm = foldTermM TermFoldM{
+              fTermM = \ty dc v tt -> zonkTcType ty    >>= \ty' ->
+                                      return (Term ty' dc v tt)
+             ,fSuspensionM = \ct ty v b -> zonkTcType ty >>= \ty ->
+                                           return (Suspension ct ty v b)
+             ,fNewtypeWrapM= \ty dc t -> zonkTcType ty >>= \ty' ->
+                                         return$ NewtypeWrap ty' dc t
+             ,fRefWrapM    = \ty t ->
+                               return RefWrap `ap` zonkTcType ty `ap` return t
+             ,fPrimM       = (return.) . Prim
+             }
+
 --------------------------------------------------------------------------------
 --------------------------------------------------------------------------------
--- Semantically different to recoverM in TcRnMonad 
--- recoverM retains the errors in the first action,
---  whereas recoverTc here does not
-recoverTc :: TcM a -> TcM a -> TcM a
-recoverTc recover thing = do 
-  (_,mb_res) <- tryTcErrs thing
-  case mb_res of 
-    Nothing  -> recover
-    Just res -> return res
+-- representation types for thetas
+rttiView :: Type -> Type
+rttiView ty | Just ty' <- coreView ty  = rttiView ty'
+rttiView ty
+  | (tvs, theta, tau) <- tcSplitSigmaTy ty
+  =  mkForAllTys tvs (mkFunTys [predTypeRep p | p <- theta, isClassPred p] tau)
+
+-- Restore Class predicates out of a representation type
+dictsView :: Type -> Type
+-- dictsView ty = ty
+dictsView (FunTy (TyConApp tc_dict args) ty)
+  | Just c <- tyConClass_maybe tc_dict
+  = FunTy (PredTy (ClassP c args)) (dictsView ty)
+dictsView ty
+  | Just (tc_fun, [TyConApp tc_dict args, ty2]) <- tcSplitTyConApp_maybe ty
+  , Just c <- tyConClass_maybe tc_dict
+  = mkTyConApp tc_fun [PredTy (ClassP c args), dictsView ty2]
+dictsView ty = ty
+
+
+-- Use only for RTTI types
+isMonomorphic :: RttiType -> Bool
+isMonomorphic ty = noExistentials && noUniversals
+ where (tvs, _, ty')     = tcSplitSigmaTy ty
+       noExistentials = isEmptyVarSet (tyVarsOfType ty')
+       noUniversals   = null tvs
+
+-- Use only for RTTI types
+isMonomorphicOnNonPhantomArgs :: RttiType -> Bool
+isMonomorphicOnNonPhantomArgs ty
+  | Just (tc, all_args) <- tcSplitTyConApp_maybe (repType ty)
+  , phantom_vars  <- tyConPhantomTyVars tc
+  , concrete_args <- [ arg | (tyv,arg) <- tyConTyVars tc `zip` all_args
+                           , tyv `notElem` phantom_vars]
+  = all isMonomorphicOnNonPhantomArgs concrete_args
+  | Just (ty1, ty2) <- splitFunTy_maybe ty
+  = all isMonomorphicOnNonPhantomArgs [ty1,ty2]
+  | otherwise = isMonomorphic ty
+
+tyConPhantomTyVars :: TyCon -> [TyVar]
+tyConPhantomTyVars tc
+  | isAlgTyCon tc
+  , Just dcs <- tyConDataCons_maybe tc
+  , dc_vars  <- concatMap dataConUnivTyVars dcs
+  = tyConTyVars tc \\ dc_vars
+tyConPhantomTyVars _ = []
+
+-- Is this defined elsewhere?
+-- Generalize the type: find all free tyvars and wrap in the appropiate ForAll.
+sigmaType :: Type -> Type
+sigmaType ty = mkSigmaTy (varSetElems$ tyVarsOfType ty) [] ty
 
 
-isMonomorphic :: Type -> Bool
-isMonomorphic ty | (tvs, ty') <- splitForAllTys ty
-                 = null tvs && (isEmptyVarSet . tyVarsOfType) ty'
 
 mapMif :: Monad m => (a -> Bool) -> (a -> m a) -> [a] -> m [a]
 mapMif pred f xx = sequence $ mapMif_ pred f xx
 
 mapMif :: Monad m => (a -> Bool) -> (a -> m a) -> [a] -> m [a]
 mapMif pred f xx = sequence $ mapMif_ pred f xx
@@ -870,27 +1147,37 @@ mapMif pred f xx = sequence $ mapMif_ pred f xx
 unlessM :: Monad m => m Bool -> m () -> m ()
 unlessM condM acc = condM >>= \c -> unless c acc
 
 unlessM :: Monad m => m Bool -> m () -> m ()
 unlessM condM acc = condM >>= \c -> unless c acc
 
+
 -- Strict application of f at index i
 appArr :: Ix i => (e -> a) -> Array i e -> Int -> a
 appArr f a@(Array _ _ _ ptrs#) i@(I# i#)
 -- Strict application of f at index i
 appArr :: Ix i => (e -> a) -> Array i e -> Int -> a
 appArr f a@(Array _ _ _ ptrs#) i@(I# i#)
- = ASSERT (i < length(elems a))
+ = ASSERT2 (i < length(elems a), ppr(length$ elems a, i))
    case indexArray# ptrs# i# of
        (# e #) -> f e
 
    case indexArray# ptrs# i# of
        (# e #) -> f e
 
-zonkTerm :: Term -> TcM Term
-zonkTerm = foldTerm idTermFoldM {
-              fTerm = \ty dc v tt -> sequence tt      >>= \tt ->
-                                     zonkTcType ty    >>= \ty' ->
-                                     return (Term ty' dc v tt)
-             ,fSuspension = \ct ty v b -> zonkTcType ty >>= \ty ->
-                                          return (Suspension ct ty v b)
-             ,fNewtypeWrap= \ty dc t -> 
-                   return NewtypeWrap `ap` zonkTcType ty `ap` return dc `ap` t}
+amap' :: (t -> b) -> Array Int t -> [b]
+amap' f (Array i0 i _ arr#) = map g [0 .. i - i0]
+    where g (I# i#) = case indexArray# arr# i# of
+                          (# e #) -> f e
 
 
 
 
--- Is this defined elsewhere?
--- Generalize the type: find all free tyvars and wrap in the appropiate ForAll.
-sigmaType :: Type -> Type
-sigmaType ty = mkSigmaTy (varSetElems$ tyVarsOfType (dropForAlls ty)) [] ty
+isLifted :: Type -> Bool
+isLifted =  not . isUnLiftedType
+
+extractUnboxed  :: [Type] -> Closure -> [[Word]]
+extractUnboxed tt clos = go tt (nonPtrs clos)
+   where sizeofType t
+           | Just (tycon,_) <- tcSplitTyConApp_maybe t
+           = ASSERT (isPrimTyCon tycon) sizeofTyCon tycon
+           | otherwise = pprPanic "Expected a TcTyCon" (ppr t)
+         go [] _ = []
+         go (t:tt) xx 
+           | (x, rest) <- splitAt (sizeofType t) xx
+           = x : go tt rest
+
+sizeofTyCon :: TyCon -> Int -- in *words*
+sizeofTyCon = primRepSizeW . tyConPrimRep
 
 
 
 
+(|.|) :: (a -> Bool) -> (a -> Bool) -> a -> Bool
+(f |.| g) x = f x || g x
\ No newline at end of file
index ec9bca8..c75510b 100644 (file)
@@ -145,6 +145,7 @@ data DynFlag
    | Opt_D_dump_BCOs
    | Opt_D_dump_vect
    | Opt_D_dump_hpc
    | Opt_D_dump_BCOs
    | Opt_D_dump_vect
    | Opt_D_dump_hpc
+   | Opt_D_dump_rtti
    | Opt_D_source_stats
    | Opt_D_verbose_core2core
    | Opt_D_verbose_stg2stg
    | Opt_D_source_stats
    | Opt_D_verbose_core2core
    | Opt_D_verbose_stg2stg
@@ -1357,6 +1358,8 @@ dynamic_flags = [
          Supported
   , Flag "ddump-hi-diffs"          (setDumpFlag Opt_D_dump_hi_diffs)
          Supported
          Supported
   , Flag "ddump-hi-diffs"          (setDumpFlag Opt_D_dump_hi_diffs)
          Supported
+  , Flag "ddump-rtti"             (setDumpFlag Opt_D_dump_rtti)
+         Supported
 
   , Flag "dcore-lint"              (NoArg (setDynFlag Opt_DoCoreLinting))
          Supported
 
   , Flag "dcore-lint"              (NoArg (setDynFlag Opt_DoCoreLinting))
          Supported
index 766ed01..3d6ce01 100644 (file)
@@ -106,7 +106,7 @@ module GHC (
         isModuleInterpreted,
        InteractiveEval.compileExpr, HValue, dynCompileExpr,
        lookupName,
         isModuleInterpreted,
        InteractiveEval.compileExpr, HValue, dynCompileExpr,
        lookupName,
-        GHC.obtainTerm, GHC.obtainTerm1, GHC.obtainTermB, reconstructType,
+        GHC.obtainTermFromId, GHC.obtainTermFromVal, reconstructType,
         modInfoModBreaks,
         ModBreaks(..), BreakIndex,
         BreakInfo(breakInfo_number, breakInfo_module),
         modInfoModBreaks,
         ModBreaks(..), BreakIndex,
         BreakInfo(breakInfo_number, breakInfo_module),
@@ -2555,18 +2555,14 @@ getHistorySpan :: GhcMonad m => History -> m SrcSpan
 getHistorySpan h = withSession $ \hsc_env ->
                           return$ InteractiveEval.getHistorySpan hsc_env h
 
 getHistorySpan h = withSession $ \hsc_env ->
                           return$ InteractiveEval.getHistorySpan hsc_env h
 
-obtainTerm :: GhcMonad m => Bool -> Id -> m Term
-obtainTerm force id = withSession $ \hsc_env ->
-                        liftIO $ InteractiveEval.obtainTerm hsc_env force id
-
-obtainTerm1 :: GhcMonad m => Bool -> Maybe Type -> a -> m Term
-obtainTerm1 force mb_ty a =
+obtainTermFromVal :: GhcMonad m => Int ->  Bool -> Type -> a -> m Term
+obtainTermFromVal bound force ty a =
     withSession $ \hsc_env ->
     withSession $ \hsc_env ->
-      liftIO $ InteractiveEval.obtainTerm1 hsc_env force mb_ty a
+      liftIO $ InteractiveEval.obtainTermFromVal hsc_env bound force ty a
 
 
-obtainTermB :: GhcMonad m => Int -> Bool -> Id -> m Term
-obtainTermB bound force id =
+obtainTermFromId :: GhcMonad m => Int -> Bool -> Id -> m Term
+obtainTermFromId bound force id =
     withSession $ \hsc_env ->
     withSession $ \hsc_env ->
-      liftIO $ InteractiveEval.obtainTermB hsc_env bound force id
+      liftIO $ InteractiveEval.obtainTermFromId hsc_env bound force id
 
 #endif
 
 #endif
index e508e09..6d43ea8 100644 (file)
@@ -1089,11 +1089,11 @@ extendInteractiveContext
         -> TyVarSet
         -> InteractiveContext
 extendInteractiveContext ictxt ids tyvars
         -> TyVarSet
         -> InteractiveContext
 extendInteractiveContext ictxt ids tyvars
-  = ictxt { ic_tmp_ids =  ic_tmp_ids ictxt ++ ids,
+  = ictxt { ic_tmp_ids =  snub((ic_tmp_ids ictxt \\ ids) ++ ids),
                           -- NB. must be this way around, because we want
                           -- new ids to shadow existing bindings.
             ic_tyvars   = ic_tyvars ictxt `unionVarSet` tyvars }
                           -- NB. must be this way around, because we want
                           -- new ids to shadow existing bindings.
             ic_tyvars   = ic_tyvars ictxt `unionVarSet` tyvars }
-
+    where snub = map head . group . sort
 
 substInteractiveContext :: InteractiveContext -> TvSubst -> InteractiveContext
 substInteractiveContext ictxt subst | isEmptyTvSubst subst = ictxt
 
 substInteractiveContext :: InteractiveContext -> TvSubst -> InteractiveContext
 substInteractiveContext ictxt subst | isEmptyTvSubst subst = ictxt
index 77594f8..e5d91c9 100644 (file)
@@ -30,7 +30,7 @@ module InteractiveEval (
         isModuleInterpreted,
        compileExpr, dynCompileExpr,
        lookupName,
         isModuleInterpreted,
        compileExpr, dynCompileExpr,
        lookupName,
-        Term(..), obtainTerm, obtainTerm1, obtainTermB, reconstructType,
+        Term(..), obtainTermFromId, obtainTermFromVal, reconstructType,
         skolemiseSubst, skolemiseTy
 #endif
         ) where
         skolemiseSubst, skolemiseTy
 #endif
         ) where
@@ -83,6 +83,7 @@ import Exception
 import Control.Concurrent
 import Data.List (sortBy)
 import Foreign.StablePtr
 import Control.Concurrent
 import Data.List (sortBy)
 import Foreign.StablePtr
+import System.IO
 
 -- -----------------------------------------------------------------------------
 -- running a statement interactively
 
 -- -----------------------------------------------------------------------------
 -- running a statement interactively
@@ -637,26 +638,46 @@ rttiEnvironment hsc_env@HscEnv{hsc_IC=ic} = do
    let InteractiveContext{ic_tmp_ids=tmp_ids} = ic
        incompletelyTypedIds = 
            [id | id <- tmp_ids
    let InteractiveContext{ic_tmp_ids=tmp_ids} = ic
        incompletelyTypedIds = 
            [id | id <- tmp_ids
-               , not $ null [v | v <- varSetElems$ tyVarsOfType (idType id)
-                              , isSkolemTyVar v]
+               , not $ noSkolems id
                , (occNameFS.nameOccName.idName) id /= result_fs]
                , (occNameFS.nameOccName.idName) id /= result_fs]
-   tys <- reconstructType hsc_env 10 `mapM` incompletelyTypedIds
-          -- map termType `fmap` (obtainTerm hsc_env False `mapM` incompletelyTypedIds)
-   
-   improvs <- sequence [improveRTTIType hsc_env ty ty'
-                 | (ty, Just ty') <- zip (map idType incompletelyTypedIds) tys]
-   let ic' = foldr (\mb_subst ic' ->
-                        maybe (WARN(True, text ("RTTI failed to calculate the "
-                                           ++  "improvement for a type")) ic')
-                              (substInteractiveContext ic' . skolemiseSubst)
-                              mb_subst)
-                   ic
-                   improvs
-   return hsc_env{hsc_IC=ic'}
-
-skolemiseSubst :: TvSubst -> TvSubst
-skolemiseSubst subst = subst `setTvSubstEnv` 
-                        mapVarEnv (fst.skolemiseTy) (getTvSubstEnv subst)
+   hsc_env' <- foldM improveTypes hsc_env (map idName incompletelyTypedIds)
+   return hsc_env'
+    where
+     noSkolems = null . filter isSkolemTyVar . varSetElems . tyVarsOfType . idType
+     improveTypes hsc_env@HscEnv{hsc_IC=ic} name = do
+      let InteractiveContext{ic_tmp_ids=tmp_ids} = ic
+          Just id = find (\i -> idName i == name) tmp_ids
+      if noSkolems id
+         then return hsc_env
+         else do
+           mb_new_ty <- reconstructType hsc_env 10 id
+           let old_ty = idType id
+           case mb_new_ty of
+             Nothing -> return hsc_env
+             Just new_ty -> do
+              mb_subst <- improveRTTIType hsc_env old_ty new_ty
+              case mb_subst of
+               Nothing -> return $
+                        WARN(True, text (":print failed to calculate the "
+                                           ++ "improvement for a type")) hsc_env
+               Just subst -> do
+                 when (dopt Opt_D_dump_rtti (hsc_dflags hsc_env)) $
+                      printForUser stderr alwaysQualify $
+                      fsep [text "RTTI Improvement for", ppr id, equals, ppr subst]
+
+                 let (subst', skols) = skolemiseSubst subst
+                     ic' = extendInteractiveContext
+                               (substInteractiveContext ic subst') [] skols
+                 return hsc_env{hsc_IC=ic'}
+
+skolemiseSubst :: TvSubst -> (TvSubst, TyVarSet)
+skolemiseSubst subst = let
+    varenv               = getTvSubstEnv subst
+    all_together         = mapVarEnv skolemiseTy varenv
+    (varenv', skol_vars) = ( mapVarEnv fst all_together
+                           , map snd (varEnvElts all_together))
+    in (subst `setTvSubstEnv` varenv', unionVarSets skol_vars)
+                        
 
 skolemiseTy :: Type -> (Type, TyVarSet)
 skolemiseTy ty = (substTy subst ty, mkVarSet new_tyvars)
 
 skolemiseTy :: Type -> (Type, TyVarSet)
 skolemiseTy ty = (substTy subst ty, mkVarSet new_tyvars)
@@ -969,23 +990,20 @@ isModuleInterpreted mod_summary = withSession $ \hsc_env ->
 ----------------------------------------------------------------------------
 -- RTTI primitives
 
 ----------------------------------------------------------------------------
 -- 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)
+obtainTermFromVal :: HscEnv -> Int -> Bool -> Type -> a -> IO Term
+obtainTermFromVal hsc_env bound force ty x =
+              cvObtainTerm hsc_env bound force 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 :: 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
+obtainTermFromId :: HscEnv -> Int -> Bool -> Id -> IO Term
+obtainTermFromId hsc_env bound force id =  do
+              hv <- Linker.getHValue hsc_env (varName id)
+              cvObtainTerm hsc_env bound force (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) 
 
 -- 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
+              cvReconstructType hsc_env bound (idType id) hv
+
 #endif /* GHCI */
 #endif /* GHCI */
+