X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Ftypecheck%2FInst.lhs;h=17dce300f00ad2276d200cea6a1faa0cbab1d9dd;hp=be7c14ae70db0fadb19f7b16df46225905918ec4;hb=c4ec8f2a77894af1c6160c4e8ad5625ab62f0bea;hpb=ecdaf6bc29d23bd704df8c65442ee08032a585fc diff --git a/compiler/typecheck/Inst.lhs b/compiler/typecheck/Inst.lhs index be7c14a..17dce30 100644 --- a/compiler/typecheck/Inst.lhs +++ b/compiler/typecheck/Inst.lhs @@ -6,15 +6,8 @@ The @Inst@ type: dictionaries or method instances \begin{code} -{-# OPTIONS -w #-} --- The above warning supression flag is a temporary kludge. --- While working on this module you are encouraged to remove it and fix --- any warnings in the module. See --- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings --- for details - module Inst ( - Inst, + Inst, pprInstances, pprDictsTheta, pprDictsInFull, -- User error messages showLIE, pprInst, pprInsts, pprInstInFull, -- Debugging messages @@ -47,9 +40,10 @@ module Inst ( InstOrigin(..), InstLoc, pprInstLoc, mkWantedCo, mkGivenCo, - fromWantedCo, fromGivenCo, - eitherEqInst, mkEqInst, mkEqInsts, mkWantedEqInst, - finalizeEqInst, writeWantedCoercion, + isWantedCo, fromWantedCo, fromGivenCo, eqInstCoType, + mkIdEqInstCo, mkSymEqInstCo, mkLeftTransEqInstCo, + mkRightTransEqInstCo, mkAppEqInstCo, + eitherEqInst, mkEqInst, mkEqInsts, mkWantedEqInst, finalizeEqInst, eqInstType, updateEqInstCoercion, eqInstCoercion, eqInstTys ) where @@ -57,7 +51,7 @@ module Inst ( #include "HsVersions.h" import {-# SOURCE #-} TcExpr( tcPolyExpr ) -import {-# SOURCE #-} TcUnify( boxyUnify, unifyType ) +import {-# SOURCE #-} TcUnify( boxyUnify {- , unifyType -} ) import FastString import HsSyn @@ -68,6 +62,7 @@ import InstEnv import FunDeps import TcMType import TcType +import MkCore import Type import TypeRep import Class @@ -76,16 +71,13 @@ import Module import Coercion import HscTypes import CoreFVs -import DataCon import Id import Name import NameSet -import Literal import Var ( Var, TyVar ) import qualified Var import VarEnv import VarSet -import TysWiredIn import PrelNames import BasicTypes import SrcLoc @@ -96,13 +88,12 @@ import Util import Unique import Outputable import Data.List -import TypeRep -import Class import Control.Monad \end{code} + Selection ~~~~~~~~~ \begin{code} @@ -139,6 +130,7 @@ instType imp@(ImplicInst {}) = mkImplicTy (tci_tyvars imp) (tci_given imp) -- instType i@(EqInst {tci_co = co}) = eitherEqInst i TyVarTy id instType (EqInst {tci_left = ty1, tci_right = ty2}) = mkPredTy (EqPred ty1 ty2) +mkImplicTy :: [TyVar] -> [Inst] -> [Inst] -> Type mkImplicTy tvs givens wanteds -- The type of an implication constraint = ASSERT( all isAbstractableInst givens ) -- pprTrace "mkImplicTy" (ppr givens) $ @@ -147,15 +139,14 @@ mkImplicTy tvs givens wanteds -- The type of an implication constraint in mkForAllTys tvs $ mkPhiTy (map dictPred givens) $ - if isSingleton dict_wanteds then - instType (head dict_wanteds) - else - mkTupleTy Boxed (length dict_wanteds) (map instType dict_wanteds) + mkBigCoreTupTy (map instType dict_wanteds) +dictPred :: Inst -> TcPredType dictPred (Dict {tci_pred = pred}) = pred dictPred (EqInst {tci_left=ty1,tci_right=ty2}) = EqPred ty1 ty2 dictPred inst = pprPanic "dictPred" (ppr inst) +getDictClassTys :: Inst -> (Class, [Type]) getDictClassTys (Dict {tci_pred = pred}) = getClassPredTys pred getDictClassTys inst = pprPanic "getDictClassTys" (ppr inst) @@ -165,6 +156,7 @@ getDictClassTys inst = pprPanic "getDictClassTys" (ppr inst) -- Leaving these in is really important for the call to fdPredsOfInsts -- in TcSimplify.inferLoop, because the result is fed to 'grow', -- which is supposed to be conservative +fdPredsOfInst :: Inst -> [TcPredType] fdPredsOfInst (Dict {tci_pred = pred}) = [pred] fdPredsOfInst (Method {tci_theta = theta}) = theta fdPredsOfInst (ImplicInst {tci_given = gs, @@ -175,9 +167,10 @@ fdPredsOfInst (EqInst {}) = [] fdPredsOfInsts :: [Inst] -> [PredType] fdPredsOfInsts insts = concatMap fdPredsOfInst insts +isInheritableInst :: Inst -> Bool isInheritableInst (Dict {tci_pred = pred}) = isInheritablePred pred isInheritableInst (Method {tci_theta = theta}) = all isInheritablePred theta -isInheritableInst other = True +isInheritableInst _ = True --------------------------------- @@ -190,7 +183,7 @@ ipNamesOfInsts insts = [n | inst <- insts, n <- ipNamesOfInst inst] ipNamesOfInst (Dict {tci_pred = IParam n _}) = [ipNameName n] ipNamesOfInst (Method {tci_theta = theta}) = [ipNameName n | IParam n _ <- theta] -ipNamesOfInst other = [] +ipNamesOfInst _ = [] --------------------------------- tyVarsOfInst :: Inst -> TcTyVarSet @@ -206,7 +199,9 @@ tyVarsOfInst (ImplicInst {tci_tyvars = tvs, tci_given = givens, tci_wanted = wan -- Remember the free tyvars of a coercion tyVarsOfInst (EqInst {tci_left = ty1, tci_right = ty2}) = tyVarsOfType ty1 `unionVarSet` tyVarsOfType ty2 +tyVarsOfInsts :: [Inst] -> VarSet tyVarsOfInsts insts = foldr (unionVarSet . tyVarsOfInst) emptyVarSet insts +tyVarsOfLIE :: Bag Inst -> VarSet tyVarsOfLIE lie = tyVarsOfInsts (lieToList lie) @@ -228,39 +223,40 @@ isAbstractableInst inst = isDict inst || isEqInst inst isEqInst :: Inst -> Bool isEqInst (EqInst {}) = True -isEqInst other = False +isEqInst _ = False isDict :: Inst -> Bool isDict (Dict {}) = True -isDict other = False +isDict _ = False isClassDict :: Inst -> Bool isClassDict (Dict {tci_pred = pred}) = isClassPred pred -isClassDict other = False +isClassDict _ = False isTyVarDict :: Inst -> Bool isTyVarDict (Dict {tci_pred = pred}) = isTyVarClassPred pred -isTyVarDict other = False +isTyVarDict _ = False isIPDict :: Inst -> Bool isIPDict (Dict {tci_pred = pred}) = isIPPred pred -isIPDict other = False +isIPDict _ = False +isImplicInst :: Inst -> Bool isImplicInst (ImplicInst {}) = True -isImplicInst other = False +isImplicInst _ = False isMethod :: Inst -> Bool isMethod (Method {}) = True -isMethod other = False +isMethod _ = False isMethodFor :: TcIdSet -> Inst -> Bool isMethodFor ids (Method {tci_oid = id}) = id `elemVarSet` ids -isMethodFor ids inst = False +isMethodFor _ _ = False isMethodOrLit :: Inst -> Bool isMethodOrLit (Method {}) = True isMethodOrLit (LitInst {}) = True -isMethodOrLit other = False +isMethodOrLit _ = False \end{code} @@ -326,7 +322,7 @@ instCallDicts :: InstLoc -> TcThetaType -> TcM HsWrapper -- into the LIE, and returns a HsWrapper to enclose the call site. -- This is the key place where equality predicates -- are unleashed into the world -instCallDicts loc [] = return idHsWrapper +instCallDicts _ [] = return idHsWrapper -- instCallDicts loc (EqPred ty1 ty2 : preds) -- = do { unifyType ty1 ty2 -- For now, we insist that they unify right away @@ -355,7 +351,7 @@ instCallDicts loc (pred : preds) ------------- cloneDict :: Inst -> TcM Inst -cloneDict dict@(Dict nm ty loc) = do { uniq <- newUnique +cloneDict dict@(Dict nm _ _) = do { uniq <- newUnique ; return (dict {tci_name = setNameUnique nm uniq}) } cloneDict eq@(EqInst {}) = return eq cloneDict other = pprPanic "cloneDict" (ppr other) @@ -374,7 +370,7 @@ newIPDict orig ip_name ty = do name = mkPredName uniq inst_loc pred dict = Dict {tci_name = name, tci_pred = pred, tci_loc = inst_loc} - return (mapIPName (\n -> instToId dict) ip_name, dict) + return (mapIPName (\_ -> instToId dict) ip_name, dict) \end{code} @@ -391,7 +387,7 @@ mkPredName uniq loc pred_ty -- we use the outermost tycon of the lhs, if there is one, to -- improve readability of Core code baseOcc = case splitTyConApp_maybe ty of - Nothing -> mkOccName tcName "$" + Nothing -> mkTcOcc "$" Just (tc, _) -> getOccName tc \end{code} @@ -407,7 +403,7 @@ newMethodFromName :: InstOrigin -> BoxyRhoType -> Name -> TcM TcId newMethodFromName origin ty name = do id <- tcLookupId name -- Use tcLookupId not tcLookupGlobalId; the method is almost - -- always a class op, but with -fno-implicit-prelude GHC is + -- always a class op, but with -XNoImplicitPrelude GHC is -- meant to find whatever thing is in scope, and that may -- be an ordinary function. loc <- getInstLoc origin @@ -415,6 +411,7 @@ newMethodFromName origin ty name = do extendLIE inst return (instToId inst) +newMethodWithGivenTy :: InstOrigin -> Id -> [Type] -> TcRn TcId newMethodWithGivenTy orig id tys = do loc <- getInstLoc orig inst <- newMethod loc id tys @@ -457,6 +454,7 @@ checkKind tv ty --------------------------- +newMethod :: InstLoc -> Id -> [Type] -> TcRn Inst newMethod inst_loc id tys = do new_uniq <- newUnique let @@ -482,8 +480,8 @@ mkOverLit (HsFractional r) mkOverLit (HsIsString s) = return (HsString s) isHsVar :: HsExpr Name -> Name -> Bool -isHsVar (HsVar f) g = f==g -isHsVar other g = False +isHsVar (HsVar f) g = f == g +isHsVar _ _ = False \end{code} @@ -531,6 +529,7 @@ zonkInst eqinst@(EqInst {tci_left = ty1, tci_right = ty2}) ; return (eqinst {tci_co = co', tci_left= ty1', tci_right = ty2' }) } +zonkInsts :: [Inst] -> TcRn [Inst] zonkInsts insts = mapM zonkInst insts \end{code} @@ -566,7 +565,7 @@ pprInsts insts = brackets (interpp'SP insts) pprInst, pprInstInFull :: Inst -> SDoc -- Debugging: print the evidence :: type -pprInst i@(EqInst {tci_left = ty1, tci_right = ty2, tci_co = co}) +pprInst i@(EqInst {tci_left = ty1, tci_right = ty2}) = eitherEqInst i (\covar -> text "Wanted" <+> ppr (TyVarTy covar) <+> dcolon <+> ppr (EqPred ty1 ty2)) (\co -> text "Given" <+> ppr co <+> dcolon <+> ppr (EqPred ty1 ty2)) @@ -687,21 +686,25 @@ getOverlapFlag ; return overlap_flag } +traceDFuns :: [Instance] -> TcRn () traceDFuns ispecs = traceTc (hang (text "Adding instances:") 2 (vcat (map pp ispecs))) where pp ispec = ppr (instanceDFunId ispec) <+> colon <+> ppr ispec -- Print the dfun name itself too +funDepErr :: Instance -> [Instance] -> TcRn () funDepErr ispec ispecs = addDictLoc ispec $ addErr (hang (ptext (sLit "Functional dependencies conflict between instance declarations:")) 2 (pprInstances (ispec:ispecs))) +dupInstErr :: Instance -> Instance -> TcRn () dupInstErr ispec dup_ispec = addDictLoc ispec $ addErr (hang (ptext (sLit "Duplicate instance declarations:")) 2 (pprInstances [ispec, dup_ispec])) +addDictLoc :: Instance -> TcRn a -> TcRn a addDictLoc ispec thing_inside = setSrcSpan (mkSrcSpan loc loc) thing_inside where @@ -750,9 +753,7 @@ lookupSimpleInst (Method {tci_oid = id, tci_tys = tys, tci_theta = theta, tci_lo lookupSimpleInst (LitInst { tci_lit = lit@OverLit { ol_val = lit_val , ol_rebindable = rebindable } , tci_ty = ty, tci_loc = iloc}) -#ifdef DEBUG - | rebindable = panic "lookupSimpleInst" -- A LitInst invariant -#endif + | debugIsOn && rebindable = panic "lookupSimpleInst" -- A LitInst invariant | Just witness <- shortCutLit lit_val ty = do { let lit' = lit { ol_witness = witness, ol_type = ty } ; return (GenInst [] (L loc (HsOverLit lit'))) } @@ -832,8 +833,10 @@ lookupPred pred@(ClassP clas tys) ; return Nothing } }} -lookupPred ip_pred = return Nothing -- Implicit parameters +lookupPred (IParam {}) = return Nothing -- Implicit parameters +lookupPred (EqPred {}) = panic "lookupPred EqPred" +record_dfun_usage :: Id -> TcRn () record_dfun_usage dfun_id = do { hsc_env <- getTopEnv ; let dfun_name = idName dfun_id @@ -861,7 +864,7 @@ tcGetInstEnvs = do { eps <- getEps; env <- getGblEnv; %* * %************************************************************************ -Suppose we are doing the -fno-implicit-prelude thing, and we encounter +Suppose we are doing the -XNoImplicitPrelude thing, and we encounter a do-expression. We have to find (>>) in the current environment, which is done by the rename. Then we have to check that it has the same type as Control.Monad.(>>). Or, more precisely, a compatible type. One 'customer' had @@ -915,6 +918,8 @@ tcSyntaxName orig ty (std_nm, user_nm_expr) = do expr <- tcPolyExpr (L span user_nm_expr) sigma1 return (std_nm, unLoc expr) +syntaxNameCtxt :: HsExpr Name -> InstOrigin -> Type -> TidyEnv + -> TcRn (TidyEnv, SDoc) syntaxNameCtxt name orig ty tidy_env = do inst_loc <- getInstLoc orig let @@ -932,21 +937,99 @@ syntaxNameCtxt name orig ty tidy_env = do %* * %************************************************************************ +Operations on EqInstCo. + \begin{code} -mkGivenCo :: Coercion -> Either TcTyVar Coercion +mkGivenCo :: Coercion -> EqInstCo mkGivenCo = Right -mkWantedCo :: TcTyVar -> Either TcTyVar Coercion +mkWantedCo :: TcTyVar -> EqInstCo mkWantedCo = Left -fromGivenCo :: Either TcTyVar Coercion -> Coercion +isWantedCo :: EqInstCo -> Bool +isWantedCo (Left _) = True +isWantedCo _ = False + +fromGivenCo :: EqInstCo -> Coercion fromGivenCo (Right co) = co fromGivenCo _ = panic "fromGivenCo: not a wanted coercion" -fromWantedCo :: String -> Either TcTyVar Coercion -> TcTyVar +fromWantedCo :: String -> EqInstCo -> TcTyVar fromWantedCo _ (Left covar) = covar -fromWantedCo msg _ = panic ("fromWantedCo: not a wanted coercion: " ++ msg) +fromWantedCo msg _ = + panic ("fromWantedCo: not a wanted coercion: " ++ msg) +eqInstCoType :: EqInstCo -> TcType +eqInstCoType (Left cotv) = mkTyVarTy cotv +eqInstCoType (Right co) = co +\end{code} + +Coercion transformations on EqInstCo. These transformations work differently +depending on whether a EqInstCo is for a wanted or local equality: + + Local : apply the inverse of the specified coercion + Wanted: obtain a fresh coercion hole (meta tyvar) and update the old hole + to be the specified coercion applied to the new coercion hole + +\begin{code} +-- Coercion transformation: co = id +-- +mkIdEqInstCo :: EqInstCo -> Type -> TcM () +mkIdEqInstCo (Left cotv) t + = writeMetaTyVar cotv t +mkIdEqInstCo (Right _) _ + = return () + +-- Coercion transformation: co = sym co' +-- +mkSymEqInstCo :: EqInstCo -> (Type, Type) -> TcM EqInstCo +mkSymEqInstCo (Left cotv) (ty1, ty2) + = do { cotv' <- newMetaCoVar ty1 ty2 + ; writeMetaTyVar cotv (mkSymCoercion (TyVarTy cotv')) + ; return $ Left cotv' + } +mkSymEqInstCo (Right co) _ + = return $ Right (mkSymCoercion co) + +-- Coercion transformation: co = co' |> given_co +-- +mkLeftTransEqInstCo :: EqInstCo -> Coercion -> (Type, Type) -> TcM EqInstCo +mkLeftTransEqInstCo (Left cotv) given_co (ty1, ty2) + = do { cotv' <- newMetaCoVar ty1 ty2 + ; writeMetaTyVar cotv (TyVarTy cotv' `mkTransCoercion` given_co) + ; return $ Left cotv' + } +mkLeftTransEqInstCo (Right co) given_co _ + = return $ Right (co `mkTransCoercion` mkSymCoercion given_co) + +-- Coercion transformation: co = given_co |> co' +-- +mkRightTransEqInstCo :: EqInstCo -> Coercion -> (Type, Type) -> TcM EqInstCo +mkRightTransEqInstCo (Left cotv) given_co (ty1, ty2) + = do { cotv' <- newMetaCoVar ty1 ty2 + ; writeMetaTyVar cotv (given_co `mkTransCoercion` TyVarTy cotv') + ; return $ Left cotv' + } +mkRightTransEqInstCo (Right co) given_co _ + = return $ Right (mkSymCoercion given_co `mkTransCoercion` co) + +-- Coercion transformation: co = col cor +-- +mkAppEqInstCo :: EqInstCo -> (Type, Type) -> (Type, Type) + -> TcM (EqInstCo, EqInstCo) +mkAppEqInstCo (Left cotv) (ty1_l, ty2_l) (ty1_r, ty2_r) + = do { cotv_l <- newMetaCoVar ty1_l ty2_l + ; cotv_r <- newMetaCoVar ty1_r ty2_r + ; writeMetaTyVar cotv (mkAppCoercion (TyVarTy cotv_l) (TyVarTy cotv_r)) + ; return (Left cotv_l, Left cotv_r) + } +mkAppEqInstCo (Right co) _ _ + = return (Right $ mkLeftCoercion co, Right $ mkRightCoercion co) +\end{code} + +Operations on entire EqInst. + +\begin{code} eitherEqInst :: Inst -- given or wanted EqInst -> (TcTyVar -> a) -- result if wanted -> (Coercion -> a) -- result if given @@ -955,61 +1038,67 @@ eitherEqInst (EqInst {tci_co = either_co}) withWanted withGiven = case either_co of Left covar -> withWanted covar Right co -> withGiven co +eitherEqInst i _ _ = pprPanic "eitherEqInst" (ppr i) -mkEqInsts :: [PredType] -> [Either TcTyVar Coercion] -> TcM [Inst] +mkEqInsts :: [PredType] -> [EqInstCo] -> TcM [Inst] mkEqInsts preds cos = zipWithM mkEqInst preds cos -mkEqInst :: PredType -> Either TcTyVar Coercion -> TcM Inst +mkEqInst :: PredType -> EqInstCo -> TcM Inst mkEqInst (EqPred ty1 ty2) co = do { uniq <- newUnique ; src_span <- getSrcSpanM ; err_ctxt <- getErrCtxt ; let loc = InstLoc EqOrigin src_span err_ctxt name = mkName uniq src_span - inst = EqInst {tci_left = ty1, tci_right = ty2, tci_co = co, tci_loc = loc, tci_name = name} + inst = EqInst { tci_left = ty1 + , tci_right = ty2 + , tci_co = co + , tci_loc = loc + , tci_name = name + } ; return inst } - where mkName uniq src_span = mkInternalName uniq (mkVarOcc "co") src_span + where + mkName uniq src_span = mkInternalName uniq (mkVarOcc "co") src_span +mkEqInst pred _ = pprPanic "mkEqInst" (ppr pred) mkWantedEqInst :: PredType -> TcM Inst mkWantedEqInst pred@(EqPred ty1 ty2) = do { cotv <- newMetaCoVar ty1 ty2 ; mkEqInst pred (Left cotv) } +mkWantedEqInst pred = pprPanic "mkWantedEqInst" (ppr pred) + +-- Turn a wanted into a local EqInst (needed during type inference for +-- signatures) +-- +-- * Give it a name and change the coercion around. +-- +finalizeEqInst :: Inst -- wanted + -> TcM Inst -- given +finalizeEqInst wanted@(EqInst{tci_left = ty1, tci_right = ty2, tci_name = name}) + = do { let var = Var.mkCoVar name (PredTy $ EqPred ty1 ty2) + + -- fill the coercion hole + ; let cotv = fromWantedCo "writeWantedCoercion" $ tci_co wanted + ; writeMetaTyVar cotv (TyVarTy var) + + -- set the new coercion + ; let given = wanted { tci_co = mkGivenCo $ TyVarTy var } + ; return given + } --- type inference: --- We want to promote the wanted EqInst to a given EqInst --- in the signature context. --- This means we have to give the coercion a name --- and fill it in as its own name. -finalizeEqInst - :: Inst -- wanted - -> TcM Inst -- given -finalizeEqInst wanted@(EqInst {tci_left = ty1, tci_right = ty2, tci_name = name}) - = do { let var = Var.mkCoVar name (PredTy $ EqPred ty1 ty2) - ; writeWantedCoercion wanted (TyVarTy var) - ; let given = wanted { tci_co = mkGivenCo $ TyVarTy var } - ; return given - } - -writeWantedCoercion - :: Inst -- wanted EqInst - -> Coercion -- coercion to fill the hole with - -> TcM () -writeWantedCoercion wanted co - = do { let cotv = fromWantedCo "writeWantedCoercion" $ tci_co wanted - ; writeMetaTyVar cotv co - } +finalizeEqInst i = pprPanic "finalizeEqInst" (ppr i) eqInstType :: Inst -> TcType eqInstType inst = eitherEqInst inst mkTyVarTy id -eqInstCoercion :: Inst -> Either TcTyVar Coercion +eqInstCoercion :: Inst -> EqInstCo eqInstCoercion = tci_co eqInstTys :: Inst -> (TcType, TcType) eqInstTys inst = (tci_left inst, tci_right inst) -updateEqInstCoercion :: (Either TcTyVar Coercion -> Either TcTyVar Coercion) -> Inst -> Inst +updateEqInstCoercion :: (EqInstCo -> EqInstCo) -> Inst -> Inst updateEqInstCoercion f inst = inst {tci_co = f $ tci_co inst} \end{code}