[commit: ghc] wip/impredicativity: Implement second rule for InstanceOf canon. (06820b4)

git at git.haskell.org git at git.haskell.org
Wed Jun 17 11:52:47 UTC 2015


Repository : ssh://git@git.haskell.org/ghc

On branch  : wip/impredicativity
Link       : http://ghc.haskell.org/trac/ghc/changeset/06820b45707e6df02f5df20564acc3b8dee5acb6/ghc

>---------------------------------------------------------------

commit 06820b45707e6df02f5df20564acc3b8dee5acb6
Author: Alejandro Serrano <trupill at gmail.com>
Date:   Wed Jun 17 13:42:31 2015 +0200

    Implement second rule for InstanceOf canon.
    
    Rule InstanceOf (T ...) (forall a. Q => ty)
     --> [a/alpha]Q /\ T ... ~ [a/alpha]ty


>---------------------------------------------------------------

06820b45707e6df02f5df20564acc3b8dee5acb6
 compiler/typecheck/TcCanonical.hs | 20 +++++++++++++++++++-
 compiler/typecheck/TcEvidence.hs  | 11 +++++++----
 compiler/typecheck/TcSMonad.hs    | 12 +++++++++++-
 compiler/typecheck/TcSimplify.hs  |  1 +
 4 files changed, 38 insertions(+), 6 deletions(-)

diff --git a/compiler/typecheck/TcCanonical.hs b/compiler/typecheck/TcCanonical.hs
index 3159cb8..d1c56cf 100644
--- a/compiler/typecheck/TcCanonical.hs
+++ b/compiler/typecheck/TcCanonical.hs
@@ -1665,8 +1665,26 @@ can_instance_of ct@(CInstanceOfCan { cc_ev = ev, cc_lhs = lhs, cc_rhs = rhs })
            CtDerived {} -> canEqNC (ev { ctev_pred = eq }) NomEq lhs rhs
            CtGiven {ctev_loc = loc } ->
              do { emitNewDerivedEq loc eq
-                ; stopWith ev "Given instance equality" }
+                ; stopWith ev "Given instanceOf equality" }
            CtWanted { ctev_evar = evar, ctev_loc = loc } ->
              do { new_ev <- newWantedEvVarNC loc eq
                 ; setWantedEvBind evar (mkInstanceOfEq (ctEvCoercion new_ev))
                 ; canEqNC new_ev NomEq lhs rhs } }
+
+  -- case InstanceOf (T ...) (forall qvars. Q => ty)
+  | Nothing <- getTyVar_maybe lhs, Nothing <- splitForAllTy_maybe lhs
+  , Just _  <- splitForAllTy_maybe rhs
+  = case ev of
+      CtWanted { ctev_evar = evar, ctev_loc = loc } ->
+        do { (_qvars, q, ty) <- splitInst rhs
+             -- generate new constraints
+           ; new_ev_qs <- mapM (newWantedEvVarNC loc) q
+           ; let eq = mkTcEqPredRole Nominal lhs ty
+           ; new_ev_ty <- newWantedEvVarNC loc eq
+             -- compute the evidence for the instantiation
+           ; setWantedEvBind evar (mkInstanceOfInst (ctEvCoercion new_ev_ty)
+                                                    (map ctev_evar new_ev_qs))
+             -- emit new work
+           ; emitWorkNC new_ev_qs
+           ; canEqNC new_ev_ty NomEq lhs ty }
+      _ -> stopWith ev "Given/Derived instanceOf instantiation"
diff --git a/compiler/typecheck/TcEvidence.hs b/compiler/typecheck/TcEvidence.hs
index 904e9fd..2400a18 100644
--- a/compiler/typecheck/TcEvidence.hs
+++ b/compiler/typecheck/TcEvidence.hs
@@ -18,7 +18,7 @@ module TcEvidence (
   EvLit(..), evTermCoercion,
   EvCallStack(..),
   EvTypeable(..),
-  EvInstanceOf(..), mkInstanceOfEq,
+  EvInstanceOf(..), mkInstanceOfEq, mkInstanceOfInst,
 
   -- TcCoercion
   TcCoercion(..), LeftOrRight(..), pickLR,
@@ -767,13 +767,16 @@ data EvCallStack
 -- Evidence for instantiation / InstanceOf constraints
 data EvInstanceOf
   = EvInstanceOfEq   TcCoercion  -- ^ term witnessing equality
-  | EvInstanceOfInst TcCoercion EvTerm
+  | EvInstanceOfInst TcCoercion [EvTerm]
   | EvInstanceOfLet  TcEvBinds  EvInstanceOf
     deriving ( Data.Data, Data.Typeable )
 
 mkInstanceOfEq :: TcCoercion -> EvTerm
 mkInstanceOfEq = EvInstanceOf . EvInstanceOfEq
 
+mkInstanceOfInst :: TcCoercion -> [EvVar] -> EvTerm
+mkInstanceOfInst co q = EvInstanceOf (EvInstanceOfInst co (map EvId q))
+
 {-
 Note [Coercion evidence terms]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -1037,8 +1040,8 @@ evVarsOfTypeable ev =
 evVarsOfInstanceOf :: EvInstanceOf -> VarSet
 evVarsOfInstanceOf ev =
   case ev of
-    EvInstanceOfEq co     -> coVarsOfTcCo co
-    EvInstanceOfInst co t -> coVarsOfTcCo co `unionVarSet` evVarsOfTerm t
+    EvInstanceOfEq   co   -> coVarsOfTcCo co
+    EvInstanceOfInst co q -> coVarsOfTcCo co `unionVarSet` evVarsOfTerms q
     EvInstanceOfLet  _  _ -> emptyVarSet
 
 {-
diff --git a/compiler/typecheck/TcSMonad.hs b/compiler/typecheck/TcSMonad.hs
index 231f94a..c0c213c 100644
--- a/compiler/typecheck/TcSMonad.hs
+++ b/compiler/typecheck/TcSMonad.hs
@@ -15,7 +15,7 @@ module TcSMonad (
     TcS, runTcS, runTcSWithEvBinds,
     failTcS, tryTcS, nestTcS, nestImplicTcS, recoverTcS,
 
-    runTcPluginTcS, addUsedRdrNamesTcS, deferTcSForAllEq,
+    runTcPluginTcS, addUsedRdrNamesTcS, deferTcSForAllEq, splitInst,
 
     -- Tracing etc
     panicTcS, traceTcS,
@@ -2869,3 +2869,13 @@ deferTcSForAllEq role loc (tvs1,body1) (tvs2,body2)
                          ; return (TcLetCo ev_binds new_co) }
 
         ; return $ EvCoercion (foldr mkTcForAllCo coe_inside skol_tvs) }
+
+-- Split a sigma type and instantiate its variables
+splitInst :: Type -> TcS ([TyVar], ThetaType, Type)
+splitInst sigma
+  = do { let (qvars, q, ty) = tcSplitSigmaTy sigma
+         -- instantiate variables for q and ty
+         ; (subst, inst_vars) <- wrapTcS $ TcM.tcInstTyVars qvars
+         ; let q_subst  = map (Type.substTy subst) q
+               ty_subst = Type.substTy subst ty
+         ; return (inst_vars, q_subst, ty_subst) }
diff --git a/compiler/typecheck/TcSimplify.hs b/compiler/typecheck/TcSimplify.hs
index 2bcf5eb..5b35437 100644
--- a/compiler/typecheck/TcSimplify.hs
+++ b/compiler/typecheck/TcSimplify.hs
@@ -616,6 +616,7 @@ pickQuantifiablePreds qtvs theta
 
           EqPred NomEq ty1 ty2  -> quant_fun ty1 || quant_fun ty2
           IrredPred ty          -> tyVarsOfType ty `intersectsVarSet` qtvs
+          InstanceOfPred ty1 ty2 -> quant_fun ty1 || quant_fun ty2
 
     pick_cls_pred flex_ctxt tys
       = tyVarsOfTypes tys `intersectsVarSet` qtvs



More information about the ghc-commits mailing list