[commit: ghc] wip/impredicativity: Apply instantiation also when checking type classes from the inert set (3a4762f)
git at git.haskell.org
git at git.haskell.org
Wed Jul 15 12:22:04 UTC 2015
Repository : ssh://git@git.haskell.org/ghc
On branch : wip/impredicativity
Link : http://ghc.haskell.org/trac/ghc/changeset/3a4762f44df65c886a4c0bfe8a2ab2af181097fb/ghc
>---------------------------------------------------------------
commit 3a4762f44df65c886a4c0bfe8a2ab2af181097fb
Author: Alejandro Serrano <trupill at gmail.com>
Date: Wed Jul 15 14:22:56 2015 +0200
Apply instantiation also when checking type classes from the inert set
>---------------------------------------------------------------
3a4762f44df65c886a4c0bfe8a2ab2af181097fb
compiler/typecheck/TcInteract.hs | 44 ++++++++++++++++++++++++++++++++--------
1 file changed, 35 insertions(+), 9 deletions(-)
diff --git a/compiler/typecheck/TcInteract.hs b/compiler/typecheck/TcInteract.hs
index 706bc09..2df6354 100644
--- a/compiler/typecheck/TcInteract.hs
+++ b/compiler/typecheck/TcInteract.hs
@@ -673,7 +673,12 @@ interactIrred _ wi = pprPanic "interactIrred" (ppr wi)
-}
interactDict :: InertCans -> Ct -> TcS (StopOrContinue Ct)
-interactDict inerts workItem@(CDictCan { cc_ev = ev_w, cc_class = cls, cc_tyargs = tys })
+interactDict inerts workItem
+ = do { lazyEqs <- inerts_to_lazy_eqs (inert_irreds inerts)
+ ; interactDict' inerts lazyEqs workItem }
+
+interactDict' :: InertCans -> LazyEqs [TcPredType] -> Ct -> TcS (StopOrContinue Ct)
+interactDict' inerts lazyEqs workItem@(CDictCan { cc_ev = ev_w, cc_class = cls, cc_tyargs = tys })
-- don't ever try to solve CallStack IPs directly from other dicts,
-- we always build new dicts instead.
-- See Note [Overview of implicit CallStacks]
@@ -693,8 +698,12 @@ interactDict inerts workItem@(CDictCan { cc_ev = ev_w, cc_class = cls, cc_tyargs
setWantedEvBind (ctEvId ev_w) ev_tm
stopWith ev_w "Wanted CallStack IP"
- | Just ctev_i <- lookupInertDict inerts cls tys
- = do { (inert_effect, stop_now) <- solveOneFromTheOther ctev_i ev_w
+ | Just (ctev_i, qs) <- over_lazy_eqs (lookupInertDict inerts cls) lazyEqs tys
+ = do { -- Apply obtained lazy equation
+ qs_evs <- mapM (newWantedEvVarNC (ctev_loc ev_w)) (extract_lazy_eqs qs)
+ ; emitWorkNC qs_evs
+ -- Perform interaction
+ ; (inert_effect, stop_now) <- solveOneFromTheOther ctev_i ev_w
; case inert_effect of
IRKeep -> return ()
IRDelete -> updInertDicts $ \ ds -> delDict ds cls tys
@@ -712,7 +721,7 @@ interactDict inerts workItem@(CDictCan { cc_ev = ev_w, cc_class = cls, cc_tyargs
= do { addFunDepWork inerts ev_w cls
; continueWith workItem }
-interactDict _ wi = pprPanic "interactDict" (ppr wi)
+interactDict' _ _ wi = pprPanic "interactDict" (ppr wi)
addFunDepWork :: InertCans -> CtEvidence -> Class -> TcS ()
-- Add derived constraints from type-class functional dependencies.
@@ -1187,13 +1196,13 @@ doTopReact work_item
doTopReactDict :: InertSet -> Ct -> TcS (StopOrContinue Ct)
-- Try to use type-class instance declarations to simplify the constraint
doTopReactDict inerts work_item@(CDictCan { cc_ev = fl, cc_class = cls
- , cc_tyargs = xis })
+ , cc_tyargs = xis })
| isGiven fl -- Never use instances for Given constraints
= do { try_fundep_improvement
; continueWith work_item }
| Just ev <- lookupSolvedDict inerts cls xis -- Cached
- = do { setEvBindIfWanted fl (ctEvTerm ev);
+ = do { setEvBindIfWanted fl (ctEvTerm ev)
; stopWith fl "Dict/Top (cached)" }
| isDerived fl -- Use type-class instances for Deriveds, in the hope
@@ -1695,10 +1704,9 @@ matchClassInst _ _ clas [k,t] _
| className clas == typeableClassName
= matchTypeableClass clas k t
-matchClassInst dflags _ clas tys loc
+matchClassInst dflags inerts clas tys loc
= do { instEnvs <- getInstEnvs
- ; inertCans <- getInertCans
- ; lazyEqs <- inerts_to_lazy_eqs (inert_irreds inertCans)
+ ; lazyEqs <- inerts_to_lazy_eqs (inert_irreds (inert_cans inerts))
; traceTcS "matchClassInst" $ vcat [ text "pred =" <+> ppr pred
, text "lazy_eqs =" <+> ppr lazyEqs ]
; let safeOverlapCheck = safeHaskell dflags `elem` [Sf_Safe, Sf_Trustworthy]
@@ -1760,6 +1768,24 @@ inerts_to_lazy_eqs = flatMapBagM $ \ct ->
extract_lazy_eqs :: LazyEqs [TcPredType] -> [TcPredType]
extract_lazy_eqs leqs = concatMap (\(_,_,qs) -> qs) (bagToList leqs)
+over_lazy_eqs :: ([Type] -> Maybe a) -> LazyEqs l -> [Type] -> Maybe (a, LazyEqs l)
+over_lazy_eqs f leqs tys
+ = go (subsets (bagToList leqs))
+ where
+ subsets :: [(Type, Type, l)] -> [(TvSubst, LazyEqs l)]
+ subsets [] = [(emptyTvSubst, emptyBag)]
+ subsets (elt@(ty1,ty2,_):xs)
+ | Just v <- getTyVar_maybe ty1
+ = let sxs = subsets xs
+ in sxs ++ flip map sxs (\(s, b) -> ( extendTvSubst s v ty2
+ , consBag elt b ))
+ | otherwise = pprPanic "Lazy eqs without var in the LHS" (ppr ty1)
+
+ go [] = Nothing
+ go ((subst, l):rest) = case f (substTys subst tys) of
+ Just x -> Just (x, l)
+ Nothing -> go rest
+
{- Note [Instance and Given overlap]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
More information about the ghc-commits
mailing list