[project @ 2003-06-24 07:58:18 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / Inst.lhs
index 464ec76..5790e7b 100644 (file)
@@ -21,7 +21,7 @@ module Inst (
        ipNamesOfInst, ipNamesOfInsts, fdPredsOfInst, fdPredsOfInsts,
        instLoc, getDictClassTys, dictPred,
 
-       lookupInst, lookupSimpleInst, LookupInstResult(..),
+       lookupInst, LookupInstResult(..),
 
        isDict, isClassDict, isMethod, 
        isLinearInst, linearInstType, isIPDict, isInheritableInst,
@@ -36,45 +36,44 @@ module Inst (
 
 #include "HsVersions.h"
 
-import {-# SOURCE #-}  TcExpr( tcExpr )
+import {-# SOURCE #-}  TcExpr( tcCheckSigma )
 
 import HsSyn   ( HsLit(..), HsOverLit(..), HsExpr(..) )
-import TcHsSyn ( TcExpr, TcId, TcIdSet, TypecheckedHsExpr,
-                 mkHsTyApp, mkHsDictApp, mkHsConApp, zonkId
+import TcHsSyn ( TcExpr, TcId, TcIdSet, 
+                 mkHsTyApp, mkHsDictApp, mkHsConApp, zonkId,
+                 mkCoercion, ExprCoFn
                )
 import TcRnMonad
-import TcEnv   ( tcGetInstEnv, tcLookupId, tcLookupTyCon )
+import TcEnv   ( tcGetInstEnv, tcLookupId, tcLookupTyCon, checkWellStaged, topIdLvl )
 import InstEnv ( InstLookupResult(..), lookupInstEnv )
-import TcMType ( zonkTcType, zonkTcTypes, zonkTcPredType, zapToType,
+import TcMType ( zonkTcType, zonkTcTypes, zonkTcPredType, 
                  zonkTcThetaType, tcInstTyVar, tcInstType, tcInstTyVars
                )
 import TcType  ( Type, TcType, TcThetaType, TcTyVarSet,
-                 SourceType(..), PredType, ThetaType, TyVarDetails(VanillaTv),
+                 SourceType(..), PredType, TyVarDetails(VanillaTv),
                  tcSplitForAllTys, tcSplitForAllTys, mkTyConApp,
-                 tcSplitMethodTy, tcSplitPhiTy, mkGenTyConApp,
+                 tcSplitPhiTy, mkGenTyConApp,
                  isIntTy,isFloatTy, isIntegerTy, isDoubleTy,
                  tcIsTyVarTy, mkPredTy, mkTyVarTy, mkTyVarTys,
                  tyVarsOfType, tyVarsOfTypes, tyVarsOfPred, tidyPred,
-                 isClassPred, isTyVarClassPred, isLinearPred, predHasFDs,
+                 isClassPred, isTyVarClassPred, isLinearPred, 
                  getClassPredTys, getClassPredTys_maybe, mkPredName,
                  isInheritablePred, isIPPred, 
                  tidyType, tidyTypes, tidyFreeTyVars, tcSplitSigmaTy
                )
 import CoreFVs ( idFreeTyVars )
-import Class   ( Class )
 import DataCon ( DataCon,dataConSig )
 import Id      ( Id, idName, idType, mkUserLocal, mkSysLocal, mkLocalId, setIdUnique )
 import PrelInfo        ( isStandardClass, isCcallishClass, isNoDictClass )
 import Name    ( Name, mkMethodOcc, getOccName )
 import PprType ( pprPred, pprParendType )      
-import Subst   ( emptyInScopeSet, mkSubst, substTy, substTyWith, substTheta, mkTyVarSubst )
+import Subst   ( substTy, substTyWith, substTheta, mkTyVarSubst )
 import Literal ( inIntRange )
 import Var     ( TyVar )
 import VarEnv  ( TidyEnv, emptyTidyEnv, lookupSubstEnv, SubstResult(..) )
 import VarSet  ( elemVarSet, emptyVarSet, unionVarSet )
 import TysWiredIn ( floatDataCon, doubleDataCon )
 import PrelNames( fromIntegerName, fromRationalName, rationalTyConName )
-import Util    ( equalLength )
 import BasicTypes( IPName(..), mapIPName, ipNameName )
 import UniqSupply( uniqsFromSupply )
 import Outputable
@@ -102,11 +101,14 @@ dictPred inst               = pprPanic "dictPred" (ppr inst)
 getDictClassTys (Dict _ pred _) = getClassPredTys pred
 
 -- fdPredsOfInst is used to get predicates that contain functional 
--- dependencies; i.e. should participate in improvement
-fdPredsOfInst (Dict _ pred _) | predHasFDs pred = [pred]
-                             | otherwise       = []
-fdPredsOfInst (Method _ _ _ theta _ _) = filter predHasFDs theta
-fdPredsOfInst other                   = []
+-- dependencies *or* might do so.  The "might do" part is because
+-- a constraint (C a b) might have a superclass with FDs
+-- 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 (Dict _ pred _)         = [pred]
+fdPredsOfInst (Method _ _ _ theta _ _) = theta
+fdPredsOfInst other                   = []     -- LitInsts etc
 
 fdPredsOfInsts :: [Inst] -> [PredType]
 fdPredsOfInsts insts = concatMap fdPredsOfInst insts
@@ -258,7 +260,7 @@ newIPDict orig ip_name ty
 
 
 \begin{code}
-tcInstCall :: InstOrigin  -> TcType -> TcM (TypecheckedHsExpr -> TypecheckedHsExpr, TcType)
+tcInstCall :: InstOrigin  -> TcType -> TcM (ExprCoFn, TcType)
 tcInstCall orig fun_ty -- fun_ty is usually a sigma-type
   = tcInstType VanillaTv fun_ty        `thenM` \ (tyvars, theta, tau) ->
     newDicts orig theta                `thenM` \ dicts ->
@@ -266,7 +268,7 @@ tcInstCall orig fun_ty      -- fun_ty is usually a sigma-type
     let
        inst_fn e = mkHsDictApp (mkHsTyApp e (mkTyVarTys tyvars)) (map instToId dicts)
     in
-    returnM (inst_fn, tau)
+    returnM (mkCoercion inst_fn, tau)
 
 tcInstDataCon :: InstOrigin -> DataCon
              -> TcM ([TcType], -- Types to instantiate at
@@ -324,23 +326,14 @@ newMethodWithGivenTy orig id tys theta tau
 -- to simplify Insts
 
 tcInstClassOp :: InstLoc -> Id -> [TcType] -> TcM Inst
-  -- Instantiate the specified class op, but *only* with the main
-  -- class dictionary. For example, given 'op' defined thus:
-  --   class Foo a where
-  --     op :: (?x :: String) => a -> a
-  -- (tcInstClassOp op T) should return an Inst with type
-  --   (?x :: String) => T -> T
-  -- That is, the class-op's context is still there.  
-  -- This is really important in the use of tcInstClassOp in TcClassDcls.mkMethodBind
 tcInstClassOp inst_loc sel_id tys
   = let
        (tyvars,rho) = tcSplitForAllTys (idType sel_id)
-       rho_ty       = substTyWith tyvars tys rho
-       (pred,tau)   = tcSplitMethodTy rho_ty
-               -- Split off exactly one predicate (see the example above)
+       rho_ty       = ASSERT( length tyvars == length tys )
+                      substTyWith tyvars tys rho
+       (preds,tau)  = tcSplitPhiTy rho_ty
     in
-    ASSERT( isClassPred pred )
-    newMethod inst_loc sel_id tys [pred] tau
+    newMethod inst_loc sel_id tys preds tau
 
 ---------------------------
 newMethod inst_loc id tys theta tau
@@ -367,7 +360,7 @@ newOverloadedLit orig lit@(HsIntegral i fi) expected_ty
   | fi /= fromIntegerName      -- Do not generate a LitInst for rebindable
                                -- syntax.  Reason: tcSyntaxName does unification
                                -- which is very inconvenient in tcSimplify
-  = tcSyntaxName orig expected_ty fromIntegerName fi   `thenM` \ (expr, _) ->
+  = tcSyntaxName orig expected_ty (fromIntegerName, HsVar fi)  `thenM` \ (_,expr) ->
     returnM (HsApp expr (HsLit (HsInteger i)))
 
   | Just expr <- shortCutIntLit i expected_ty 
@@ -378,8 +371,8 @@ newOverloadedLit orig lit@(HsIntegral i fi) expected_ty
 
 newOverloadedLit orig lit@(HsFractional r fr) expected_ty
   | fr /= fromRationalName     -- c.f. HsIntegral case
-  = tcSyntaxName orig expected_ty fromRationalName fr  `thenM` \ (expr, _) ->
-    mkRatLit r                                         `thenM` \ rat_lit ->
+  = tcSyntaxName orig expected_ty (fromRationalName, HsVar fr) `thenM` \ (_,expr) ->
+    mkRatLit r                                                 `thenM` \ rat_lit ->
     returnM (HsApp expr rat_lit)
 
   | Just expr <- shortCutFracLit r expected_ty 
@@ -391,9 +384,6 @@ newOverloadedLit orig lit@(HsFractional r fr) expected_ty
 newLitInst orig lit expected_ty
   = getInstLoc orig            `thenM` \ loc ->
     newUnique                  `thenM` \ new_uniq ->
-    zapToType expected_ty      `thenM_` 
-       -- 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 expected_ty loc
        lit_id   = mkSysLocal FSLIT("lit") new_uniq expected_ty
@@ -481,7 +471,7 @@ pprInsts insts  = parens (sep (punctuate comma (map pprInst insts)))
 pprInstsInFull insts
   = vcat (map go insts)
   where
-    go inst = quotes (ppr inst) <+> pprInstLoc (instLoc inst)
+    go inst = sep [quotes (ppr inst), nest 2 (pprInstLoc (instLoc inst))]
 
 pprInst (LitInst u lit ty loc)
   = hsep [ppr lit, ptext SLIT("at"), ppr ty, show_uniq u]
@@ -514,11 +504,11 @@ tidyMoreInsts env insts
 tidyInsts :: [Inst] -> (TidyEnv, [Inst])
 tidyInsts insts = tidyMoreInsts emptyTidyEnv insts
 
-showLIE :: String -> TcM ()    -- Debugging
+showLIE :: SDoc -> TcM ()      -- Debugging
 showLIE str
   = do { lie_var <- getLIEVar ;
         lie <- readMutVar lie_var ;
-        traceTc (text str <+> pprInstsInFull (lieToList lie)) }
+        traceTc (str <+> pprInstsInFull (lieToList lie)) }
 \end{code}
 
 
@@ -541,7 +531,7 @@ lookupInst :: Inst -> TcM (LookupInstResult s)
 
 
 -- Dictionaries
-lookupInst dict@(Dict _ (ClassP clas tys) loc)
+lookupInst dict@(Dict _ pred@(ClassP clas tys) loc)
   = getDOpts                   `thenM` \ dflags ->
     tcGetInstEnv               `thenM` \ inst_env ->
     case lookupInstEnv dflags inst_env clas tys of
@@ -552,6 +542,10 @@ lookupInst dict@(Dict _ (ClassP clas tys) loc)
                --      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.        
+          getStage                                             `thenM` \ use_stage ->
+          checkWellStaged (ptext SLIT("instance for") <+> quotes (ppr pred))
+                          (topIdLvl dfun_id) use_stage         `thenM_`
+          traceTc (text "lookupInst" <+> ppr dfun_id <+> ppr (topIdLvl dfun_id) <+> ppr use_stage) `thenM_`
           let
                (tyvars, rho) = tcSplitForAllTys (idType dfun_id)
                mk_ty_arg tv  = case lookupSubstEnv tenv tv of
@@ -617,28 +611,6 @@ lookupInst inst@(LitInst u (HsFractional f from_rat_name) ty loc)
     returnM (GenInst [method_inst] (HsApp (HsVar (instToId method_inst)) rat_lit))
 \end{code}
 
-There is a second, simpler interface, when you want an instance of a
-class at a given nullary type constructor.  It just returns the
-appropriate dictionary if it exists.  It is used only when resolving
-ambiguous dictionaries.
-
-\begin{code}
-lookupSimpleInst :: Class
-                -> [Type]                      -- Look up (c,t)
-                -> TcM (Maybe ThetaType)       -- Here are the needed (c,t)s
-
-lookupSimpleInst clas tys
-  = getDOpts                   `thenM` \ dflags ->
-    tcGetInstEnv               `thenM` \ inst_env -> 
-    case lookupInstEnv dflags inst_env clas tys of
-      FoundInst tenv dfun
-       -> returnM (Just (substTheta (mkSubst emptyInScopeSet tenv) theta))
-        where
-          (_, rho)  = tcSplitForAllTys (idType dfun)
-          (theta,_) = tcSplitPhiTy rho
-
-      other  -> returnM Nothing
-\end{code}
 
 
 %************************************************************************
@@ -673,27 +645,29 @@ just use the expression inline.
 \begin{code}
 tcSyntaxName :: InstOrigin
             -> TcType                  -- Type to instantiate it at
-            -> Name -> Name            -- (Standard name, user name)
-            -> TcM (TcExpr, TcType)    -- Suitable expression with its type
+            -> (Name, HsExpr Name)     -- (Standard name, user name)
+            -> TcM (Name, TcExpr)      -- (Standard name, suitable expression)
 
 -- NB: tcSyntaxName calls tcExpr, and hence can do unification.
 -- So we do not call it from lookupInst, which is called from tcSimplify
 
-tcSyntaxName orig ty std_nm user_nm
+tcSyntaxName orig ty (std_nm, HsVar user_nm)
   | std_nm == user_nm
   = newMethodFromName orig ty std_nm   `thenM` \ id ->
-    returnM (HsVar id, idType id)
+    returnM (std_nm, HsVar id)
 
-  | otherwise
+tcSyntaxName orig ty (std_nm, user_nm_expr)
   = tcLookupId std_nm          `thenM` \ std_id ->
     let        
        -- C.f. newMethodAtLoc
        ([tv], _, tau)  = tcSplitSigmaTy (idType std_id)
        tau1            = substTyWith [tv] [ty] tau
+       -- Actually, the "tau-type" might be a sigma-type in the
+       -- case of locally-polymorphic methods.
     in
-    addErrCtxtM (syntaxNameCtxt user_nm orig tau1)     $
-    tcExpr (HsVar user_nm) tau1                                `thenM` \ user_fn ->
-    returnM (user_fn, tau1)
+    addErrCtxtM (syntaxNameCtxt user_nm_expr orig tau1)        $
+    tcCheckSigma user_nm_expr tau1                     `thenM` \ expr ->
+    returnM (std_nm, expr)
 
 syntaxNameCtxt name orig ty tidy_env
   = getInstLoc orig            `thenM` \ inst_loc ->