[project @ 2002-04-02 13:21:36 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / Inst.lhs
index 64889ef..6b25d8a 100644 (file)
@@ -13,7 +13,7 @@ module Inst (
 
        newDictsFromOld, newDicts, cloneDict,
        newMethod, newMethodWithGivenTy, newMethodAtLoc,
-       newOverloadedLit, newIPDict, tcInstId,
+       newOverloadedLit, newIPDict, tcInstCall, tcInstDataCon,
 
        tyVarsOfInst, tyVarsOfInsts, tyVarsOfLIE, 
        ipNamesOfInst, ipNamesOfInsts, predsOfInst, predsOfInsts,
@@ -21,7 +21,8 @@ module Inst (
 
        lookupInst, lookupSimpleInst, LookupInstResult(..),
 
-       isDict, isClassDict, isMethod, isLinearInst, linearInstType,
+       isDict, isClassDict, isMethod, 
+       isLinearInst, linearInstType,
        isTyVarDict, isStdClassTyVarDict, isMethodFor, 
        instBindingRequired, instCanBeGeneralised,
 
@@ -33,31 +34,31 @@ module Inst (
 
 #include "HsVersions.h"
 
-import CmdLineOpts ( opt_NoMethodSharing )
 import HsSyn   ( HsLit(..), HsOverLit(..), HsExpr(..) )
-import TcHsSyn ( TcExpr, TcId, 
+import TcHsSyn ( TcExpr, TcId, TypecheckedHsExpr,
                  mkHsTyApp, mkHsDictApp, mkHsConApp, zonkId
                )
 import TcMonad
 import TcEnv   ( TcIdSet, tcGetInstEnv, tcLookupId )
 import InstEnv ( InstLookupResult(..), lookupInstEnv )
-import TcMType ( zonkTcType, zonkTcTypes, zonkTcPredType,
-                 zonkTcThetaType, tcInstTyVar, tcInstType,
+import TcMType ( zonkTcType, zonkTcTypes, zonkTcPredType, zapToType,
+                 zonkTcThetaType, tcInstTyVar, tcInstType, tcInstTyVars
                )
 import TcType  ( Type, TcType, TcThetaType, TcPredType, TcTauType, TcTyVarSet,
-                 SourceType(..), PredType, ThetaType,
-                 tcSplitForAllTys, tcSplitForAllTys, 
-                 tcSplitMethodTy, tcSplitRhoTy, tcFunArgTy,
+                 SourceType(..), PredType, ThetaType, TyVarDetails(VanillaTv),
+                 tcSplitForAllTys, tcSplitForAllTys, mkTyConApp,
+                 tcSplitMethodTy, tcSplitPhiTy, tcFunArgTy,
                  isIntTy,isFloatTy, isIntegerTy, isDoubleTy,
                  tcIsTyVarTy, mkPredTy, mkTyVarTy, mkTyVarTys,
                  tyVarsOfType, tyVarsOfTypes, tyVarsOfPred, tidyPred,
-                 isClassPred, isTyVarClassPred, 
+                 isClassPred, isTyVarClassPred, isLinearPred,
                  getClassPredTys, getClassPredTys_maybe, mkPredName,
                  tidyType, tidyTypes, tidyFreeTyVars,
                  tcCmpType, tcCmpTypes, tcCmpPred
                )
 import CoreFVs ( idFreeTyVars )
 import Class   ( Class )
+import DataCon ( dataConSig )
 import Id      ( Id, idName, idType, mkUserLocal, mkSysLocal, mkLocalId, setIdUnique )
 import PrelInfo        ( isStandardClass, isCcallishClass, isNoDictClass )
 import Name    ( Name, mkMethodOcc, getOccName )
@@ -272,11 +273,7 @@ isLinearInst other      = False
        -- We never build Method Insts that have
        -- linear implicit paramters in them.
        -- Hence no need to look for Methods
-       -- See Inst.tcInstId 
-
-isLinearPred :: TcPredType -> Bool
-isLinearPred (IParam (Linear n) _) = True
-isLinearPred other                = False
+       -- See TcExpr.tcId 
 
 linearInstType :: Inst -> TcType       -- %x::t  -->  t
 linearInstType (Dict _ (IParam _ ty) _) = ty
@@ -358,62 +355,41 @@ newIPDict orig ip_name ty
 %*                                                                     *
 %************************************************************************
 
-tcInstId instantiates an occurrence of an Id.
-The instantiate_it loop runs round instantiating the Id.
-It has to be a loop because we are now prepared to entertain
-types like
-       f:: forall a. Eq a => forall b. Baz b => tau
-We want to instantiate this to
-       f2::tau         {f2 = f1 b (Baz b), f1 = f a (Eq a)}
-
-The -fno-method-sharing flag controls what happens so far as the LIE
-is concerned.  The default case is that for an overloaded function we 
-generate a "method" Id, and add the Method Inst to the LIE.  So you get
-something like
-       f :: Num a => a -> a
-       f = /\a (d:Num a) -> let m = (+) a d in \ (x:a) -> m x x
-If you specify -fno-method-sharing, the dictionary application 
-isn't shared, so we get
-       f :: Num a => a -> a
-       f = /\a (d:Num a) (x:a) -> (+) a d x x
-This gets a bit less sharing, but
-       a) it's better for RULEs involving overloaded functions
-       b) perhaps fewer separated lambdas
-
 
 \begin{code}
-tcInstId :: Id -> NF_TcM (TcExpr, LIE, TcType)
-tcInstId fun
-  = loop (HsVar fun) emptyLIE (idType fun)
-  where
-    orig = OccurrenceOf fun
-    loop fun lie fun_ty = tcInstType fun_ty            `thenNF_Tc` \ (tyvars, theta, tau) ->
-                         loop_help fun lie (mkTyVarTys tyvars) theta tau
-
-    loop_help fun lie arg_tys [] tau   -- Not overloaded
-       = returnNF_Tc (mkHsTyApp fun arg_tys, lie, tau)
-
-    loop_help (HsVar fun_id) lie arg_tys theta tau
-       | can_share theta               -- Sharable method binding
-       = newMethodWithGivenTy orig fun_id arg_tys theta tau    `thenNF_Tc` \ meth ->
-         loop (HsVar (instToId meth)) 
-              (unitLIE meth `plusLIE` lie) tau
-
-    loop_help fun lie arg_tys theta tau        -- The general case
-       = newDicts orig theta                                   `thenNF_Tc` \ dicts ->
-         loop (mkHsDictApp (mkHsTyApp fun arg_tys) (map instToId dicts)) 
-              (mkLIE dicts `plusLIE` lie) tau
-
-    can_share theta | opt_NoMethodSharing = False
-                   | otherwise           = not (any isLinearPred theta)
-       -- This is a slight hack.
-       -- If   f :: (%x :: T) => Int -> Int
-       -- Then if we have two separate calls, (f 3, f 4), we cannot
-       -- make a method constraint that then gets shared, thus:
-       --      let m = f %x in (m 3, m 4)
-       -- because that loses the linearity of the constraint.
-       -- The simplest thing to do is never to construct a method constraint
-       -- in the first place that has a linear implicit parameter in it.
+tcInstCall :: InstOrigin  -> TcType -> NF_TcM (TypecheckedHsExpr -> TypecheckedHsExpr, LIE, TcType)
+tcInstCall orig fun_ty -- fun_ty is usually a sigma-type
+  = tcInstType VanillaTv fun_ty        `thenNF_Tc` \ (tyvars, theta, tau) ->
+    newDicts orig theta                `thenNF_Tc` \ dicts ->
+    let
+       inst_fn e = mkHsDictApp (mkHsTyApp e (mkTyVarTys tyvars)) (map instToId dicts)
+    in
+    returnNF_Tc (inst_fn, mkLIE dicts, tau)
+
+tcInstDataCon orig data_con
+  = let 
+       (tvs, stupid_theta, ex_tvs, ex_theta, arg_tys, tycon) = dataConSig data_con
+            -- We generate constraints for the stupid theta even when 
+            -- pattern matching (as the Report requires)
+    in
+    tcInstTyVars VanillaTv (ex_tvs ++ tvs)     `thenNF_Tc` \ (all_tvs', ty_args', tenv) ->
+    let
+       stupid_theta' = substTheta tenv stupid_theta
+       ex_theta'     = substTheta tenv ex_theta
+       arg_tys'      = map (substTy tenv) arg_tys
+
+       n_ex_tvs  = length ex_tvs
+       ex_tvs'   = take n_ex_tvs all_tvs'
+       result_ty = mkTyConApp tycon (drop n_ex_tvs ty_args')
+    in
+    newDicts orig stupid_theta'        `thenNF_Tc` \ stupid_dicts ->
+    newDicts orig ex_theta'    `thenNF_Tc` \ ex_dicts ->
+
+       -- Note that we return the stupid theta *only* in the LIE;
+       -- we don't otherwise use it at all
+    returnNF_Tc (ty_args', map instToId ex_dicts, arg_tys', result_ty,
+                mkLIE stupid_dicts, mkLIE ex_dicts, ex_tvs')
+
 
 newMethod :: InstOrigin
          -> TcId
@@ -449,7 +425,7 @@ newMethodAtLoc inst_loc real_id tys
        (tyvars,rho)  = tcSplitForAllTys (idType real_id)
        rho_ty        = ASSERT( equalLength tyvars tys )
                        substTy (mkTopTyVarSubst tyvars tys) rho
-       (theta, tau)  = tcSplitRhoTy rho_ty
+       (theta, tau)  = tcSplitPhiTy rho_ty
     in
     newMethodWith inst_loc real_id tys theta tau       `thenNF_Tc` \ meth_inst ->
     returnNF_Tc (meth_inst, instToId meth_inst)
@@ -465,16 +441,19 @@ newOverloadedLit :: InstOrigin
                 -> HsOverLit
                 -> TcType
                 -> NF_TcM (TcExpr, LIE)
-newOverloadedLit orig lit ty
-  | Just expr <- shortCutLit lit ty
+newOverloadedLit orig lit expected_ty
+  | Just expr <- shortCutLit lit expected_ty
   = returnNF_Tc (expr, emptyLIE)
 
   | otherwise
   = tcGetInstLoc orig          `thenNF_Tc` \ loc ->
     tcGetUnique                        `thenNF_Tc` \ new_uniq ->
+    zapToType expected_ty      `thenNF_Tc_` 
+       -- The expected type might be a 'hole' type variable, 
+       -- in which case we must zap it to an ordinary type variable
     let
-       lit_inst = LitInst lit_id lit ty loc
-       lit_id   = mkSysLocal SLIT("lit") new_uniq ty
+       lit_inst = LitInst lit_id lit expected_ty loc
+       lit_id   = mkSysLocal FSLIT("lit") new_uniq expected_ty
     in
     returnNF_Tc (HsVar (instToId lit_inst), unitLIE lit_inst)
 
@@ -600,22 +579,22 @@ lookupInst dict@(Dict _ (ClassP clas tys) loc)
     case lookupInstEnv dflags inst_env clas tys of
 
       FoundInst tenv dfun_id
-       -> let
+       ->      -- It's possible that not all the tyvars are in
+               -- the substitution, tenv. For example:
+               --      instance C X a => D X where ...
+               -- (presumably there's a functional dependency in class C)
+               -- Hence the mk_ty_arg to instantiate any un-substituted tyvars.        
+          let
                (tyvars, rho) = tcSplitForAllTys (idType dfun_id)
                mk_ty_arg tv  = case lookupSubstEnv tenv tv of
                                   Just (DoneTy ty) -> returnNF_Tc ty
-                                  Nothing          -> tcInstTyVar tv   `thenNF_Tc` \ tc_tv ->
+                                  Nothing          -> tcInstTyVar VanillaTv tv `thenNF_Tc` \ tc_tv ->
                                                       returnTc (mkTyVarTy tc_tv)
           in
-               -- It's possible that not all the tyvars are in
-               -- the substitution, tenv. For example:
-               --      instance C X a => D X where ...
-               -- (presumably there's a functional dependency in class C)
-               -- Hence the mk_ty_arg to instantiate any un-substituted tyvars.        
           mapNF_Tc mk_ty_arg tyvars    `thenNF_Tc` \ ty_args ->
           let
                dfun_rho   = substTy (mkTyVarSubst tyvars ty_args) rho
-               (theta, _) = tcSplitRhoTy dfun_rho
+               (theta, _) = tcSplitPhiTy dfun_rho
                ty_app     = mkHsTyApp (HsVar dfun_id) ty_args
           in
           if null theta then
@@ -685,7 +664,7 @@ lookupSimpleInst clas tys
        -> returnNF_Tc (Just (substTheta (mkSubst emptyInScopeSet tenv) theta))
         where
           (_, rho)  = tcSplitForAllTys (idType dfun)
-          (theta,_) = tcSplitRhoTy rho
+          (theta,_) = tcSplitPhiTy rho
 
       other  -> returnNF_Tc Nothing
 \end{code}