X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Ftypecheck%2FTcErrors.lhs;h=53975276ad1c609b154e04fb386fc0499c11baa0;hb=1c84e30e295e486c8e97e48aae6ae28060c15a85;hp=533520fc8600bb9b65ae4c782944d47a945a7b71;hpb=d2ce0f52d42edf32bb9f13796e6ba6edba8bd516;p=ghc-hetmet.git diff --git a/compiler/typecheck/TcErrors.lhs b/compiler/typecheck/TcErrors.lhs index 533520f..5397527 100644 --- a/compiler/typecheck/TcErrors.lhs +++ b/compiler/typecheck/TcErrors.lhs @@ -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,12 @@ 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 () +-- The [PredType] are already tidied +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 +164,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 +173,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 +190,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 +201,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 @@ -225,12 +222,6 @@ pprErrCtxtLoc ctxt ppr_skol (PatSkol dc _) = ptext (sLit "the data constructor") <+> quotes (ppr dc) ppr_skol skol_info = pprSkolInfo skol_info -couldNotDeduce :: [EvVar] -> [PredType] -> SDoc -couldNotDeduce givens wanteds - = sep [ ptext (sLit "Could not deduce") <+> pprTheta wanteds - , nest 2 $ ptext (sLit "from the context") - <+> pprEvVarTheta givens] - getUserGivens :: ReportErrCtxt -> Maybe [EvVar] -- Just gs => Say "could not deduce ... from gs" -- Nothing => No interesting givens, say something else @@ -255,9 +246,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,36 +265,43 @@ 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 () +-- The [PredType] are already tidied +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 () +-- ty1 and ty2 are already tidied +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] - Nothing -> misMatchMsg ty1 ty2 - -reportEqErr _ _ _ = panic "reportEqErr" -- Must be equality pred + = addErrorReport ctxt (misMatchOrCND ctxt ty1 ty2 $$ mkTyFunInfoMsg ty1 ty2) -reportTyVarEqErr :: ReportErrCtxt -> WantedLoc - -> TcTyVar -> TcType -> TcM () -reportTyVarEqErr ctxt loc tv1 ty2 +reportTyVarEqErr :: ReportErrCtxt -> TcTyVar -> TcType -> TcM () +-- tv1 and ty2 are already tidied +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 - addErrTcM (misMatchMsgWithExtras (cec_tidy ctxt) ty1 ty2) + addErrTcM (addExtraInfo (misMatchOrCND ctxt ty1 ty2) + (cec_tidy ctxt) ty1 ty2) -- So tv is a meta tyvar, and presumably it is -- an *untouchable* meta tyvar, else it'd have been unified @@ -336,7 +334,7 @@ reportTyVarEqErr ctxt loc tv1 ty2 , let implic_loc = ic_loc implic given = ic_given implic = setCtLoc (ic_loc implic) $ - do { let (env1, msg) = misMatchMsgWithExtras (cec_tidy ctxt) ty1 ty2 + do { let (env1, msg) = addExtraInfo (misMatchMsg ty1 ty2) (cec_tidy ctxt) ty1 ty2 extra = vcat [ ptext (sLit "because") <+> ppr tv1 <+> ptext (sLit "is untouchable") , ptext (sLit "inside the constraints") <+> pprEvVarTheta given , nest 2 (ptext (sLit "bound at") @@ -344,7 +342,7 @@ reportTyVarEqErr ctxt loc tv1 ty2 ; addErrTcM (env1, msg $$ extra) } | otherwise -- I'm not sure how this can happen! - = addErrTcM (misMatchMsgWithExtras (cec_tidy ctxt) ty1 ty2) + = addErrTcM (addExtraInfo (misMatchMsg ty1 ty2) (cec_tidy ctxt) ty1 ty2) where is_meta1 = isMetaTyVar tv1 k1 = tyVarKind tv1 @@ -364,12 +362,24 @@ mkTyFunInfoMsg ty1 ty2 pp_inj tc | isInjectiveTyCon tc = empty | otherwise = ptext (sLit (", and may not be injective")) -misMatchMsgWithExtras :: TidyEnv -> TcType -> TcType -> (TidyEnv, SDoc) +misMatchOrCND :: ReportErrCtxt -> TcType -> TcType -> SDoc +misMatchOrCND ctxt ty1 ty2 + = case getUserGivens ctxt of + Just givens -> couldNotDeduce givens [EqPred ty1 ty2] + Nothing -> misMatchMsg ty1 ty2 + +couldNotDeduce :: [EvVar] -> [PredType] -> SDoc +couldNotDeduce givens wanteds + = sep [ ptext (sLit "Could not deduce") <+> pprTheta wanteds + , nest 2 $ ptext (sLit "from the context") + <+> pprEvVarTheta givens] + +addExtraInfo :: SDoc -> TidyEnv -> TcType -> TcType -> (TidyEnv, SDoc) -- This version is used by TcSimplify too, which doesn't track the -- expected/acutal thing, so we just have ty1 ty2 here -- NB: The types are already tidied -misMatchMsgWithExtras env ty1 ty2 - = (env2, sep [ misMatchMsg ty1 ty2, nest 2 (extra1 $$ extra2) ]) +addExtraInfo msg env ty1 ty2 + = (env2, msg $$ nest 2 (extra1 $$ extra2)) where (env1, extra1) = typeExtraInfoMsg env ty1 (env2, extra2) = typeExtraInfoMsg env1 ty2 @@ -393,11 +403,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 +442,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 +466,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 +485,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 +540,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 +561,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 +644,41 @@ 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 msg = inaccessible_msg $$ misMatchMsg ty1 ty2 + (env1, msg1) = addExtraInfo msg env0 ty1 ty2 + ; failWithTcM (env1, msg1 $$ extra) } where inaccessible_msg = case fl of @@ -659,21 +694,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 +720,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 +728,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}