Tidy up RuntimeUnkSkols a bit more
[ghc-hetmet.git] / compiler / typecheck / TcErrors.lhs
index 533520f..28fc91b 100644 (file)
@@ -1,7 +1,8 @@
 \begin{code}
 module TcErrors( 
-       reportUnsolved, reportUnsolvedImplication, reportUnsolvedDeriv,
-       reportUnsolvedWantedEvVars, warnDefaulting, typeExtraInfoMsg,
+       reportUnsolved, reportUnsolvedDeriv,
+       reportUnsolvedWantedEvVars, warnDefaulting, 
+       unifyCtxt, typeExtraInfoMsg, 
        kindErrorTcS, misMatchErrorTcS, flattenForAllErrorTcS,
        occursCheckErrorTcS, solverDepthErrorTcS
   ) where
@@ -27,13 +28,12 @@ import SrcLoc
 import Bag
 import ListSetOps( equivClasses )
 import Util
-import Unique
 import FastString
 import Outputable
 import DynFlags
 import StaticFlags( opt_PprStyle_Debug )
 import Data.List( partition )
-import Control.Monad( unless )
+import Control.Monad( when, unless )
 \end{code}
 
 %************************************************************************
@@ -52,7 +52,9 @@ reportUnsolved (unsolved_flats, unsolved_implics)
   | isEmptyBag unsolved
   = return ()
   | otherwise
-  = do { env0 <- tcInitTidyEnv
+  = do { unsolved <- mapBagM zonkWanted unsolved
+                    -- Zonk to un-flatten any flatten-skols
+       ; env0 <- tcInitTidyEnv
        ; let tidy_env      = tidyFreeTyVars env0 (tyVarsOfWanteds unsolved)
              tidy_unsolved = tidyWanteds tidy_env unsolved
              err_ctxt = CEC { cec_encl = [] 
@@ -63,12 +65,14 @@ reportUnsolved (unsolved_flats, unsolved_implics)
   where
     unsolved = mkWantedConstraints unsolved_flats unsolved_implics
 
+
 reportUnsolvedWantedEvVars :: Bag WantedEvVar -> TcM ()
 reportUnsolvedWantedEvVars wanteds
   | isEmptyBag wanteds 
   = return ()
   | otherwise
-  = do { env0 <- tcInitTidyEnv
+  = do { wanteds <- mapBagM zonkWantedEvVar wanteds
+       ; env0 <- tcInitTidyEnv
        ; let tidy_env      = tidyFreeTyVars env0 (tyVarsOfWantedEvVars wanteds)
              tidy_unsolved = tidyWantedEvVars tidy_env wanteds
              err_ctxt = CEC { cec_encl  = [] 
@@ -81,41 +85,22 @@ reportUnsolvedDeriv unsolved loc
   | null unsolved
   = return ()
   | otherwise
-  = do { env0 <- tcInitTidyEnv
+  = setCtLoc loc $
+    do { unsolved <- zonkTcThetaType unsolved
+       ; env0 <- tcInitTidyEnv
        ; let tidy_env      = tidyFreeTyVars env0 (tyVarsOfTheta unsolved)
              tidy_unsolved = map (tidyPred tidy_env) unsolved
              err_ctxt = CEC { cec_encl  = [] 
                             , cec_extra = alt_fix
                             , cec_tidy  = tidy_env } 
-       ; reportFlat err_ctxt tidy_unsolved loc }
+       ; reportFlat err_ctxt tidy_unsolved (ctLocOrigin loc) }
   where
     alt_fix = vcat [ptext (sLit "Alternatively, use a standalone 'deriving instance' declaration,"),
                     nest 2 $ ptext (sLit "so you can specify the instance context yourself")]
 
-reportUnsolvedImplication :: Implication -> TcM ()
-reportUnsolvedImplication implic
-  = do { env0 <- tcInitTidyEnv
-       ; let tidy_env    = tidyFreeTyVars env0 (tyVarsOfImplication implic)
-             tidy_implic = tidyImplication tidy_env implic
-             new_tidy_env = foldNameEnv add tidy_env (ic_env implic)
-             err_ctxt = CEC { cec_encl = [tidy_implic]
-                            , cec_extra = empty
-                            , cec_tidy = new_tidy_env } 
-       ; reportTidyWanteds err_ctxt (ic_wanted tidy_implic) }
-  where
-    -- Extend the tidy env with a mapping from tyvars to the
-    -- names the user originally used.  At the moment we do this
-    -- from the type env, but it might be better to record the
-    -- scoped type variable in the Implication.  Urgh.
-    add (ATyVar name ty) (occ_env, var_env)
-       | Just tv <- tcGetTyVar_maybe ty
-       , not (getUnique name `elemVarEnvByKey` var_env)
-       = case tidyOccName occ_env (nameOccName name) of
-           (occ_env', occ') ->  (occ_env', extendVarEnv var_env tv tv')
-               where
-                 tv'   = setTyVarName tv name'
-                 name' = tidyNameOcc name occ'
-    add _ tidy_env = tidy_env      
+--------------------------------------------
+--      Internal functions
+--------------------------------------------
 
 data ReportErrCtxt 
     = CEC { cec_encl :: [Implication]  -- Enclosing implications
@@ -132,17 +117,27 @@ reportTidyImplic ctxt implic
   
 reportTidyWanteds :: ReportErrCtxt -> WantedConstraints -> TcM ()
 reportTidyWanteds ctxt unsolved
-  = do { let (flats, implics) = splitWanteds unsolved
-             (ambigs, others) = partition is_ambiguous (bagToList flats)
-       ; groupErrs (reportFlat ctxt) others
-       ; mapBagM_ (reportTidyImplic ctxt) implics
-       ; ifErrsM (return ()) $
-                  -- Only report ambiguity if no other errors happened
-          -- See Note [Avoiding spurious errors]
-         reportAmbigErrs ctxt skols ambigs }
+  = do { let (flats,  implics)    = splitWanteds unsolved
+             (ambigs, non_ambigs) = partition is_ambiguous (bagToList flats)
+                    (tv_eqs, others)     = partition is_tv_eq non_ambigs
+
+       ; groupErrs (reportEqErrs ctxt) tv_eqs
+       ; when (null tv_eqs) $ groupErrs (reportFlat ctxt) others
+       ; when (null tv_eqs) $ mapBagM_ (reportTidyImplic ctxt) implics
+
+                  -- Only report ambiguity if no other errors (at all) happened
+          -- See Note [Avoiding spurious errors] in TcSimplify
+       ; ifErrsM (return ()) $ reportAmbigErrs ctxt skols ambigs }
   where
     skols = foldr (unionVarSet . ic_skols) emptyVarSet (cec_encl ctxt)
  
+       -- Report equalities of form (a~ty) first.  They are usually
+       -- skolem-equalities, and they cause confusing knock-on 
+       -- effects in other errors; see test T4093b.
+    is_tv_eq c | EqPred ty1 ty2 <- wantedEvVarPred c
+               = tcIsTyVarTy ty1 || tcIsTyVarTy ty2
+               | otherwise = False
+
        -- Treat it as "ambiguous" if 
        --   (a) it is a class constraint
         --   (b) it constrains only type variables
@@ -153,11 +148,11 @@ reportTidyWanteds ctxt unsolved
                  where   
                      pred = wantedEvVarPred d
 
-reportFlat :: ReportErrCtxt -> [PredType] -> WantedLoc -> TcM ()
-reportFlat ctxt flats loc
-  = do { unless (null dicts) $ reportDictErrs ctxt dicts loc
-       ; unless (null eqs)   $ reportEqErrs   ctxt eqs   loc
-       ; unless (null ips)   $ reportIPErrs   ctxt ips   loc
+reportFlat :: ReportErrCtxt -> [PredType] -> CtOrigin -> TcM ()
+reportFlat ctxt flats origin
+  = do { unless (null dicts) $ reportDictErrs ctxt dicts origin
+       ; unless (null eqs)   $ reportEqErrs   ctxt eqs   origin
+       ; unless (null ips)   $ reportIPErrs   ctxt ips   origin
        ; ASSERT( null others ) return () }
   where
     (dicts, non_dicts) = partition isClassPred flats
@@ -168,8 +163,8 @@ reportFlat ctxt flats loc
 --      Support code 
 --------------------------------------------
 
-groupErrs :: ([PredType] -> WantedLoc -> TcM ()) -- Deal with one group
-         -> [WantedEvVar]                       -- Unsolved wanteds
+groupErrs :: ([PredType] -> CtOrigin -> TcM ()) -- Deal with one group
+         -> [WantedEvVar]                      -- Unsolved wanteds
           -> TcM ()
 -- Group together insts with the same origin
 -- We want to report them together in error messages
@@ -177,7 +172,8 @@ groupErrs :: ([PredType] -> WantedLoc -> TcM ()) -- Deal with one group
 groupErrs _ [] 
   = return ()
 groupErrs report_err (wanted : wanteds)
-  = do { setCtLoc the_loc $ report_err the_vars the_loc
+  = do { setCtLoc the_loc $ 
+          report_err the_vars (ctLocOrigin the_loc)
        ; groupErrs report_err others }
   where
    the_loc           = wantedEvVarLoc wanted
@@ -193,8 +189,8 @@ groupErrs report_err (wanted : wanteds)
        -- and it avoids need equality on InstLocs.
 
 -- Add the "arising from..." part to a message about bunch of dicts
-addArising :: WantedLoc -> SDoc -> SDoc
-addArising loc msg = msg $$ nest 2 (pprArising loc)
+addArising :: CtOrigin -> SDoc -> SDoc
+addArising orig msg = msg $$ nest 2 (pprArising orig)
 
 pprWithArising :: [WantedEvVar] -> (WantedLoc, SDoc)
 -- Print something like
@@ -204,7 +200,7 @@ pprWithArising :: [WantedEvVar] -> (WantedLoc, SDoc)
 pprWithArising [] 
   = panic "pprWithArising"
 pprWithArising [WantedEvVar ev loc] 
-  = (loc, pprEvVarTheta [ev] <+> pprArising loc)
+  = (loc, pprEvVarTheta [ev] <+> pprArising (ctLocOrigin loc))
 pprWithArising ev_vars
   = (first_loc, vcat (map ppr_one ev_vars))
   where
@@ -255,9 +251,9 @@ getUserGivens (CEC {cec_encl = ctxt})
 %************************************************************************
 
 \begin{code}
-reportIPErrs :: ReportErrCtxt -> [PredType] -> WantedLoc -> TcM ()
-reportIPErrs ctxt ips loc
-  = addErrorReport ctxt $ addArising loc msg
+reportIPErrs :: ReportErrCtxt -> [PredType] -> CtOrigin -> TcM ()
+reportIPErrs ctxt ips orig
+  = addErrorReport ctxt $ addArising orig msg
   where
     msg | Just givens <- getUserGivens ctxt
         = couldNotDeduce givens ips
@@ -274,32 +270,39 @@ reportIPErrs ctxt ips loc
 %************************************************************************
 
 \begin{code}
-reportEqErrs :: ReportErrCtxt -> [PredType] -> WantedLoc -> TcM ()
-reportEqErrs ctxt eqs loc = mapM_ (reportEqErr ctxt loc) eqs 
-
-reportEqErr :: ReportErrCtxt -> WantedLoc -> PredType -> TcM ()
-reportEqErr ctxt loc pred@(EqPred ty1 ty2)
-  | Just tv1 <- tcGetTyVar_maybe ty1 = reportTyVarEqErr ctxt loc tv1 ty2
-  | Just tv2 <- tcGetTyVar_maybe ty2 = reportTyVarEqErr ctxt loc tv2 ty1
+reportEqErrs :: ReportErrCtxt -> [PredType] -> CtOrigin -> TcM ()
+reportEqErrs ctxt eqs orig
+  = mapM_ report_one eqs 
+  where
+    env0 = cec_tidy ctxt
+    report_one (EqPred ty1 ty2) 
+      = do { (env1, extra) <- getWantedEqExtra emptyTvSubst env0 orig ty1 ty2
+           ; let ctxt' = ctxt { cec_tidy = env1
+                               , cec_extra = cec_extra ctxt $$ extra }
+           ; reportEqErr ctxt' ty1 ty2 }
+    report_one pred 
+      = pprPanic "reportEqErrs" (ppr pred)    
+
+reportEqErr :: ReportErrCtxt -> TcType -> TcType -> TcM ()
+reportEqErr ctxt ty1 ty2
+  | Just tv1 <- tcGetTyVar_maybe ty1 = reportTyVarEqErr ctxt tv1 ty2
+  | Just tv2 <- tcGetTyVar_maybe ty2 = reportTyVarEqErr ctxt tv2 ty1
   | otherwise  -- Neither side is a type variable
                -- Since the unsolved constraint is canonical, 
                -- it must therefore be of form (F tys ~ ty)
   = addErrorReport ctxt (msg $$ mkTyFunInfoMsg ty1 ty2)
   where
     msg = case getUserGivens ctxt of
-            Just givens -> couldNotDeduce givens [pred]
+            Just givens -> couldNotDeduce givens [EqPred ty1 ty2]
             Nothing     -> misMatchMsg ty1 ty2
 
-reportEqErr _ _ _ = panic "reportEqErr"          -- Must be equality pred
-
-reportTyVarEqErr :: ReportErrCtxt -> WantedLoc
-                 -> TcTyVar -> TcType -> TcM ()
-reportTyVarEqErr ctxt loc tv1 ty2
+reportTyVarEqErr :: ReportErrCtxt -> TcTyVar -> TcType -> TcM ()
+reportTyVarEqErr ctxt tv1 ty2
   | not is_meta1
   , Just tv2 <- tcGetTyVar_maybe ty2
   , isMetaTyVar tv2
   = -- sk ~ alpha: swap
-    reportTyVarEqErr ctxt loc tv2 ty1
+    reportTyVarEqErr ctxt tv2 ty1
 
   | not is_meta1
   = -- sk ~ ty, where ty isn't a meta-tyvar: mis-match
@@ -393,11 +396,25 @@ typeExtraInfoMsg env ty
   | Just tv <- tcGetTyVar_maybe ty
   , isTcTyVar tv
   , isSkolemTyVar tv || isSigTyVar tv
-  , not (isUnk tv)
+  , not (isUnkSkol tv)
   , let (env1, tv1) = tidySkolemTyVar env tv
   = (env1, pprSkolTvBinding tv1)
   where
 typeExtraInfoMsg env _ty = (env, empty)                -- Normal case
+
+--------------------
+unifyCtxt :: EqOrigin -> TidyEnv -> TcM (TidyEnv, SDoc)
+unifyCtxt (UnifyOrigin { uo_actual = act_ty, uo_expected = exp_ty }) tidy_env
+  = do  { act_ty' <- zonkTcType act_ty
+        ; exp_ty' <- zonkTcType exp_ty
+        ; let (env1, exp_ty'') = tidyOpenType tidy_env exp_ty'
+              (env2, act_ty'') = tidyOpenType env1     act_ty'
+        ; return (env2, mkExpectedActualMsg act_ty'' exp_ty'') }
+
+mkExpectedActualMsg :: Type -> Type -> SDoc
+mkExpectedActualMsg act_ty exp_ty
+  = vcat [ text "Expected type" <> colon <+> ppr exp_ty
+         , text "  Actual type" <> colon <+> ppr act_ty ]
 \end{code}
 
 Note [Non-injective type functions]
@@ -418,8 +435,8 @@ Warn of loopy local equalities that were dropped.
 %************************************************************************
 
 \begin{code}
-reportDictErrs :: ReportErrCtxt -> [PredType] -> WantedLoc -> TcM ()   
-reportDictErrs ctxt wanteds loc
+reportDictErrs :: ReportErrCtxt -> [PredType] -> CtOrigin -> TcM ()    
+reportDictErrs ctxt wanteds orig
   = do { inst_envs <- tcGetInstEnvs
        ; let (others, overlaps) = partitionWith (check_overlap inst_envs) wanteds
        ; unless (null others) $
@@ -442,7 +459,7 @@ reportDictErrs ctxt wanteds loc
 
     mk_overlap_msg pred (matches, unifiers)
       = ASSERT( not (null matches) )
-        vcat [ addArising loc (ptext (sLit "Overlapping instances for") 
+        vcat [ addArising orig (ptext (sLit "Overlapping instances for") 
                                <+> pprPred pred)
             ,  sep [ptext (sLit "Matching instances") <> colon,
                     nest 2 (vcat [pprInstances ispecs, pprInstances unifiers])]
@@ -461,11 +478,11 @@ reportDictErrs ctxt wanteds loc
     mk_no_inst_err :: [PredType] -> SDoc
     mk_no_inst_err wanteds
       | Just givens <- getUserGivens ctxt
-      = vcat [ addArising loc $ couldNotDeduce givens wanteds
+      = vcat [ addArising orig $ couldNotDeduce givens wanteds
             , show_fixes (fix1 : fixes2) ]
 
       | otherwise      -- Top level 
-      = vcat [ addArising loc $
+      = vcat [ addArising orig $
               ptext (sLit "No instance") <> plural wanteds
                    <+> ptext (sLit "for") <+> pprTheta wanteds
             , show_fixes fixes2 ]
@@ -516,10 +533,11 @@ mkMonomorphismMsg :: ReportErrCtxt -> [TcTyVar] -> TcM (TidyEnv, SDoc)
 -- ASSUMPTION: the Insts are fully zonked
 mkMonomorphismMsg ctxt inst_tvs
   = do { dflags <- getDOpts
-       ; (tidy_env, docs) <- findGlobals ctxt (mkVarSet inst_tvs)
+       ; traceTc "Mono" (vcat (map pprSkolTvBinding inst_tvs))
+        ; (tidy_env, docs) <- findGlobals ctxt (mkVarSet inst_tvs)
        ; return (tidy_env, mk_msg dflags docs) }
   where
-    mk_msg _ _ | any isRuntimeUnk inst_tvs
+    mk_msg _ _ | any isRuntimeUnkSkol inst_tvs  -- See Note [Runtime skolems]
         =  vcat [ptext (sLit "Cannot resolve unknown runtime types:") <+>
                    (pprWithCommas ppr inst_tvs),
                 ptext (sLit "Use :print or :force to determine these types")]
@@ -536,7 +554,7 @@ monomorphism_fix :: DynFlags -> SDoc
 monomorphism_fix dflags
   = ptext (sLit "Probable fix:") <+> vcat
        [ptext (sLit "give these definition(s) an explicit type signature"),
-        if dopt Opt_MonomorphismRestriction dflags
+        if xopt Opt_MonomorphismRestriction dflags
            then ptext (sLit "or use -XNoMonomorphismRestriction")
            else empty] -- Only suggest adding "-XNoMonomorphismRestriction"
                        -- if it is not already set!
@@ -619,31 +637,40 @@ warnDefaulting wanteds default_ty
     (loc, ppr_wanteds) = pprWithArising wanteds
 \end{code}
 
+Note [Runtime skolems]
+~~~~~~~~~~~~~~~~~~~~~~
+We want to give a reasonably helpful error message for ambiguity
+arising from *runtime* skolems in the debugger.  These
+are created by in RtClosureInspect.zonkRTTIType.  
+
+
 %************************************************************************
 %*                                                                     *
                  Error from the canonicaliser
+        These ones are called *during* constraint simplification
 %*                                                                     *
 %************************************************************************
 
 \begin{code}
 kindErrorTcS :: CtFlavor -> TcType -> TcType -> TcS a
+-- If there's a kind error, we don't want to blindly say "kind error"
+-- We might, say, be unifying a skolem 'a' with a type 'Int', 
+-- in which case that's the error to report.  So we set things
+-- up to call reportEqErr, which does the business properly
 kindErrorTcS fl ty1 ty2
-  = wrapErrTcS        $ 
-    setCtFlavorLoc fl $ 
-    do { env0 <- tcInitTidyEnv
-       ; let (env1, ty1') = tidyOpenType env0 ty1
-             (env2, ty2') = tidyOpenType env1 ty2
-       ; failWithTcM (env2, kindErrorMsg ty1' ty2') }
+  = wrapEqErrTcS fl ty1 ty2 $ \ env0 ty1 ty2 extra -> 
+    do { let ctxt = CEC { cec_encl = []
+                        , cec_extra = extra
+                        , cec_tidy = env0 }
+       ; reportEqErr ctxt ty1 ty2 
+       ; failM
+       }
 
 misMatchErrorTcS :: CtFlavor -> TcType -> TcType -> TcS a
 misMatchErrorTcS fl ty1 ty2
-  = wrapErrTcS        $ 
-    setCtFlavorLoc fl $ 
-    do { env0 <- tcInitTidyEnv
-       ; let (env1, ty1') = tidyOpenType env0 ty1
-             (env2, ty2') = tidyOpenType env1 ty2
-             (env3, msg)  = misMatchMsgWithExtras env2 ty1' ty2'
-       ; failWithTcM (env3, inaccessible_msg $$ msg) }
+  = wrapEqErrTcS fl ty1 ty2 $ \ env0 ty1 ty2 extra -> 
+    do { let (env1, msg)  = misMatchMsgWithExtras env0 ty1 ty2
+       ; failWithTcM (env1, inaccessible_msg $$ msg $$ extra) }
   where
     inaccessible_msg 
       = case fl of 
@@ -659,21 +686,12 @@ misMatchErrorTcS fl ty1 ty2
 
 occursCheckErrorTcS :: CtFlavor -> TcTyVar -> TcType -> TcS a
 occursCheckErrorTcS fl tv ty
-  = wrapErrTcS           $ 
-    setCtFlavorLoc fl $ 
-    do { env0          <- tcInitTidyEnv
-       ; let (env1, tv') = tidyOpenTyVar env0 tv
-             (env2, ty') = tidyOpenType env1 ty
-             extra = sep [ppr tv', char '=', ppr ty']
-       ; failWithTcM (env2, hang msg 2 extra) }
+  = wrapEqErrTcS fl (mkTyVarTy tv) ty $ \ env0 ty1 ty2 extra2 -> 
+    do { let extra1 = sep [ppr ty1, char '=', ppr ty2]
+       ; failWithTcM (env0, hang msg 2 (extra1 $$ extra2)) }
   where
     msg = text $ "Occurs check: cannot construct the infinite type:"
 
-setCtFlavorLoc :: CtFlavor -> TcM a -> TcM a
-setCtFlavorLoc (Wanted  loc) thing = setCtLoc loc thing
-setCtFlavorLoc (Derived loc) thing = setCtLoc loc thing
-setCtFlavorLoc (Given loc)   thing = setCtLoc loc thing
-
 solverDepthErrorTcS :: Int -> [CanonicalCt] -> TcS a
 solverDepthErrorTcS depth stack
   | null stack     -- Shouldn't happen unless you say -fcontext-stack=0
@@ -694,7 +712,7 @@ solverDepthErrorTcS depth stack
 
 flattenForAllErrorTcS :: CtFlavor -> TcType -> Bag CanonicalCt -> TcS a
 flattenForAllErrorTcS fl ty _bad_eqs
-  = wrapErrTcS           $ 
+  = wrapErrTcS        $ 
     setCtFlavorLoc fl $ 
     do { env0 <- tcInitTidyEnv
        ; let (env1, ty') = tidyOpenType env0 ty 
@@ -702,3 +720,77 @@ flattenForAllErrorTcS fl ty _bad_eqs
                        , ppr ty' ]
        ; failWithTcM (env1, msg) }
 \end{code}
+
+%************************************************************************
+%*                                                                     *
+                 Setting the context
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+setCtFlavorLoc :: CtFlavor -> TcM a -> TcM a
+setCtFlavorLoc (Wanted  loc)   thing = setCtLoc loc thing
+setCtFlavorLoc (Derived loc _) thing = setCtLoc loc thing
+setCtFlavorLoc (Given   loc)   thing = setCtLoc loc thing
+
+wrapEqErrTcS :: CtFlavor -> TcType -> TcType
+             -> (TidyEnv -> TcType -> TcType -> SDoc -> TcM a)
+             -> TcS a
+wrapEqErrTcS fl ty1 ty2 thing_inside
+  = do { ty_binds_var <- getTcSTyBinds
+       ; wrapErrTcS $ setCtFlavorLoc fl $ 
+    do {   -- Apply the current substitition
+           -- and zonk to get rid of flatten-skolems
+       ; ty_binds_map <- readTcRef ty_binds_var
+       ; let subst = mkOpenTvSubst (mapVarEnv snd ty_binds_map)
+       ; env0 <- tcInitTidyEnv 
+       ; (env1, ty1) <- zonkSubstTidy env0 subst ty1
+       ; (env2, ty2) <- zonkSubstTidy env1 subst ty2
+       ; let do_wanted loc = do { (env3, extra) <- getWantedEqExtra subst env2 
+                                                     (ctLocOrigin loc) ty1 ty2
+                                ; thing_inside env3 ty1 ty2 extra } 
+       ; case fl of
+           Wanted  loc   -> do_wanted loc
+           Derived loc _ -> do_wanted loc
+           Given {}      -> thing_inside env2 ty1 ty2 empty 
+                                -- We could print more info, but it
+                                 -- seems to be coming out already
+       } }  
+  where
+
+getWantedEqExtra :: TvSubst -> TidyEnv -> CtOrigin -> TcType -> TcType
+                 -> TcM (TidyEnv, SDoc)
+getWantedEqExtra subst env0 (TypeEqOrigin item) ty1 ty2
+  -- If the types in the error message are the same 
+  -- as the types we are unifying (remember to zonk the latter)
+  -- don't add the extra expected/actual message
+  --
+  -- The complication is that the types in the TypeEqOrigin must
+  --   (a) be zonked
+  --   (b) have any TcS-monad pending equalities applied to them 
+  --                   (hence the passed-in substitution)
+  = do { (env1, act) <- zonkSubstTidy env0 subst (uo_actual item)
+       ; (env2, exp) <- zonkSubstTidy env1 subst (uo_expected item)
+       ; if (act `tcEqType` ty1 && exp `tcEqType` ty2)
+         || (exp `tcEqType` ty1 && act `tcEqType` ty2)
+         then  
+            return (env0, empty)
+         else 
+            return (env2, mkExpectedActualMsg act exp) }
+
+getWantedEqExtra _ env0 orig _ _ 
+  = return (env0, pprArising orig)
+
+zonkSubstTidy :: TidyEnv -> TvSubst -> TcType -> TcM (TidyEnv, TcType)
+-- In general, becore printing a type, we want to
+--   a) Zonk it.  Even during constraint simplification this is
+--      is important, to un-flatten the flatten skolems in a type
+--   b) Substitute any solved unification variables.  This is
+--      only important *during* solving, becuase after solving
+--      the substitution is expressed in the mutable type variables
+--      But during solving there may be constraint (F xi ~ ty)
+--      where the substitution has not been applied to the RHS
+zonkSubstTidy env subst ty
+  = do { ty' <- zonkTcTypeAndSubst subst ty
+       ; return (tidyOpenType env ty') }
+\end{code}