[project @ 2003-11-17 14:23:30 by simonmar]
[ghc-hetmet.git] / ghc / compiler / typecheck / Inst.lhs
index ccd8e43..615d157 100644 (file)
@@ -5,81 +5,83 @@
 
 \begin{code}
 module Inst ( 
-       LIE, emptyLIE, unitLIE, plusLIE, consLIE, 
-       plusLIEs, mkLIE, isEmptyLIE, lieToList, listToLIE,
        showLIE,
 
        Inst, 
-       pprInst, pprInsts, pprInstsInFull, tidyInsts, tidyMoreInsts,
+       pprInst, pprInsts, pprInstsInFull, pprDFuns,
+       tidyInsts, tidyMoreInsts,
 
-       newDictsFromOld, newDicts, cloneDict,
-       newMethod, newMethodFromName, newMethodWithGivenTy, 
-       newMethodWith, newMethodAtLoc,
+       newDictsFromOld, newDicts, cloneDict, 
        newOverloadedLit, newIPDict, 
-       tcInstCall, tcInstDataCon, tcSyntaxName,
+       newMethod, newMethodFromName, newMethodWithGivenTy, 
+       tcInstClassOp, tcInstCall, tcInstDataCon, 
+       tcSyntaxName, tcStdSyntaxName,
 
        tyVarsOfInst, tyVarsOfInsts, tyVarsOfLIE, 
        ipNamesOfInst, ipNamesOfInsts, fdPredsOfInst, fdPredsOfInsts,
        instLoc, getDictClassTys, dictPred,
 
-       lookupInst, lookupSimpleInst, LookupInstResult(..),
+       lookupInst, LookupInstResult(..),
+       tcExtendLocalInstEnv, tcGetInstEnvs,
 
        isDict, isClassDict, isMethod, 
        isLinearInst, linearInstType, isIPDict, isInheritableInst,
        isTyVarDict, isStdClassTyVarDict, isMethodFor, 
-       instBindingRequired, instCanBeGeneralised,
+       instBindingRequired,
 
        zonkInst, zonkInsts,
        instToId, instName,
 
-       InstOrigin(..), InstLoc, pprInstLoc
+       InstOrigin(..), InstLoc(..), pprInstLoc
     ) where
 
 #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 InstEnv ( InstLookupResult(..), lookupInstEnv )
-import TcMType ( zonkTcType, zonkTcTypes, zonkTcPredType, zapToType,
+import TcEnv   ( tcLookupId, checkWellStaged, topIdLvl, tcMetaTy )
+import InstEnv ( DFunId, InstEnv, lookupInstEnv, checkFunDeps, extendInstEnv )
+import TcIface ( loadImportedInsts )
+import TcMType ( zonkTcType, zonkTcTypes, zonkTcPredType, 
                  zonkTcThetaType, tcInstTyVar, tcInstType, tcInstTyVars
                )
 import TcType  ( Type, TcType, TcThetaType, TcTyVarSet,
-                 SourceType(..), PredType, ThetaType, TyVarDetails(VanillaTv),
+                 PredType(..), TyVarDetails(VanillaTv),
                  tcSplitForAllTys, tcSplitForAllTys, mkTyConApp,
-                 tcSplitMethodTy, tcSplitPhiTy, mkGenTyConApp,
+                 tcSplitPhiTy, tcIsTyVarTy, tcSplitDFunTy,
                  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
+                 isInheritablePred, isIPPred, matchTys,
+                 tidyType, tidyTypes, tidyFreeTyVars, tcSplitSigmaTy, 
+                 pprPred, pprParendType, pprThetaArrow, pprClassPred
                )
+import HscTypes        ( ExternalPackageState(..) )
 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, mkTopTyVarSubst
-               )
+import PrelInfo        ( isStandardClass, isNoDictClass )
+import Name    ( Name, mkMethodOcc, getOccName, getSrcLoc, isHomePackageName, isInternalName )
+import NameSet ( addOneToNameSet )
+import Subst   ( substTy, substTyWith, substTheta, mkTyVarSubst )
 import Literal ( inIntRange )
 import Var     ( TyVar )
 import VarEnv  ( TidyEnv, emptyTidyEnv, lookupSubstEnv, SubstResult(..) )
-import VarSet  ( elemVarSet, emptyVarSet, unionVarSet )
+import VarSet  ( elemVarSet, emptyVarSet, unionVarSet, mkVarSet )
 import TysWiredIn ( floatDataCon, doubleDataCon )
-import PrelNames( fromIntegerName, fromRationalName, rationalTyConName )
-import Util    ( equalLength )
+import PrelNames       ( integerTyConName, fromIntegerName, fromRationalName, rationalTyConName )
 import BasicTypes( IPName(..), mapIPName, ipNameName )
 import UniqSupply( uniqsFromSupply )
+import CmdLineOpts( DynFlags, DynFlag( Opt_AllowUndecidableInstances ), dopt )
+import Maybes  ( isJust )
 import Outputable
 \end{code}
 
@@ -105,11 +107,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
@@ -194,10 +199,6 @@ must be witnessed by an actual binding; the second tells whether an
 instBindingRequired :: Inst -> Bool
 instBindingRequired (Dict _ (ClassP clas _) _) = not (isNoDictClass clas)
 instBindingRequired other                     = True
-
-instCanBeGeneralised :: Inst -> Bool
-instCanBeGeneralised (Dict _ (ClassP clas _) _) = not (isCcallishClass clas)
-instCanBeGeneralised other                     = True
 \end{code}
 
 
@@ -227,11 +228,13 @@ newDictsFromOld (Dict _ _ loc) theta = newDictsAtLoc loc theta
 newDictsAtLoc :: InstLoc
              -> TcThetaType
              -> TcM [Inst]
-newDictsAtLoc inst_loc@(_,loc,_) theta
+newDictsAtLoc inst_loc theta
   = newUniqueSupply            `thenM` \ us ->
     returnM (zipWith mk_dict (uniqsFromSupply us) theta)
   where
-    mk_dict uniq pred = Dict (mkLocalId (mkPredName uniq loc pred) (mkPredTy pred)) pred inst_loc
+    mk_dict uniq pred = Dict (mkLocalId (mkPredName uniq loc pred) (mkPredTy pred))
+                            pred inst_loc
+    loc = instLocSrcLoc inst_loc
 
 -- For vanilla implicit parameters, there is only one in scope
 -- at any time, so we used to use the name of the implicit parameter itself
@@ -240,7 +243,7 @@ newDictsAtLoc inst_loc@(_,loc,_) theta
 newIPDict :: InstOrigin -> IPName Name -> Type 
          -> TcM (IPName Id, Inst)
 newIPDict orig ip_name ty
-  = getInstLoc orig                    `thenM` \ inst_loc@(_,loc,_) ->
+  = getInstLoc orig                    `thenM` \ inst_loc@(InstLoc _ loc _) ->
     newUnique                          `thenM` \ uniq ->
     let
        pred = IParam ip_name ty
@@ -259,7 +262,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 ->
@@ -267,7 +270,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
@@ -300,7 +303,6 @@ tcInstDataCon orig data_con
 
     returnM (ty_args', ex_dicts, arg_tys', result_ty, ex_tvs')
 
-
 newMethodFromName :: InstOrigin -> TcType -> Name -> TcM TcId
 newMethodFromName origin ty name
   = tcLookupId name            `thenM` \ id ->
@@ -308,54 +310,42 @@ newMethodFromName origin ty name
        -- always a class op, but with -fno-implicit-prelude GHC is
        -- meant to find whatever thing is in scope, and that may
        -- be an ordinary function. 
-    newMethod origin id [ty]
-
-newMethod :: InstOrigin
-         -> TcId
-         -> [TcType]
-         -> TcM Id
-newMethod orig id tys
-  =    -- Get the Id type and instantiate it at the specified types
-    let
-       (tyvars, rho) = tcSplitForAllTys (idType id)
-       rho_ty        = substTyWith tyvars tys rho
-       (pred, tau)   = tcSplitMethodTy rho_ty
-    in
-    newMethodWithGivenTy orig id tys [pred] tau
+    getInstLoc origin          `thenM` \ loc ->
+    tcInstClassOp loc id [ty]  `thenM` \ inst ->
+    extendLIE inst             `thenM_`
+    returnM (instToId inst)
 
 newMethodWithGivenTy orig id tys theta tau
   = getInstLoc orig                    `thenM` \ loc ->
-    newMethodWith loc id tys theta tau `thenM` \ inst ->
+    newMethod loc id tys theta tau     `thenM` \ inst ->
     extendLIE inst                     `thenM_`
     returnM (instToId inst)
 
 --------------------------------------------
--- newMethodWith and newMethodAtLoc do *not* drop the 
+-- tcInstClassOp, and newMethod do *not* drop the 
 -- Inst into the LIE; they just returns the Inst
 -- This is important because they are used by TcSimplify
 -- to simplify Insts
 
-newMethodWith inst_loc@(_,loc,_) id tys theta tau
+tcInstClassOp :: InstLoc -> Id -> [TcType] -> TcM Inst
+tcInstClassOp inst_loc sel_id tys
+  = let
+       (tyvars,rho) = tcSplitForAllTys (idType sel_id)
+       rho_ty       = ASSERT( length tyvars == length tys )
+                      substTyWith tyvars tys rho
+       (preds,tau)  = tcSplitPhiTy rho_ty
+    in
+    newMethod inst_loc sel_id tys preds tau
+
+---------------------------
+newMethod inst_loc id tys theta tau
   = newUnique          `thenM` \ new_uniq ->
     let
        meth_id = mkUserLocal (mkMethodOcc (getOccName id)) new_uniq tau loc
        inst    = Method meth_id id tys theta tau inst_loc
+       loc     = instLocSrcLoc inst_loc
     in
     returnM inst
-
-newMethodAtLoc :: InstLoc
-              -> Id -> [TcType]
-              -> TcM Inst
-newMethodAtLoc inst_loc real_id tys
-       -- This actually builds the Inst
-  =    -- Get the Id type and instantiate it at the specified types
-    let
-       (tyvars,rho)  = tcSplitForAllTys (idType real_id)
-       rho_ty        = ASSERT( equalLength tyvars tys )
-                       substTy (mkTopTyVarSubst tyvars tys) rho
-       (theta, tau)  = tcSplitPhiTy rho_ty
-    in
-    newMethodWith inst_loc real_id tys theta tau
 \end{code}
 
 In newOverloadedLit we convert directly to an Int or Integer if we
@@ -372,8 +362,9 @@ 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, _) ->
-    returnM (HsApp expr (HsLit (HsInteger i)))
+  = tcSyntaxName orig expected_ty (fromIntegerName, HsVar fi)  `thenM` \ (_,expr) ->
+    mkIntegerLit i                                             `thenM` \ integer_lit ->
+    returnM (HsApp expr integer_lit)
 
   | Just expr <- shortCutIntLit i expected_ty 
   = returnM expr
@@ -383,8 +374,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 
@@ -396,9 +387,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
@@ -408,10 +396,10 @@ newLitInst orig lit expected_ty
 
 shortCutIntLit :: Integer -> TcType -> Maybe TcExpr
 shortCutIntLit i ty
-  | isIntTy ty && inIntRange i                         -- Short cut for Int
+  | isIntTy ty && inIntRange i                 -- Short cut for Int
   = Just (HsLit (HsInt i))
-  | isIntegerTy ty                             -- Short cut for Integer
-  = Just (HsLit (HsInteger i))
+  | isIntegerTy ty                     -- Short cut for Integer
+  = Just (HsLit (HsInteger i ty))
   | otherwise = Nothing
 
 shortCutFracLit :: Rational -> TcType -> Maybe TcExpr
@@ -422,13 +410,15 @@ shortCutFracLit f ty
   = Just (mkHsConApp doubleDataCon [] [HsLit (HsDoublePrim f)])
   | otherwise = Nothing
 
+mkIntegerLit :: Integer -> TcM TcExpr
+mkIntegerLit i
+  = tcMetaTy integerTyConName  `thenM` \ integer_ty ->
+    returnM (HsLit (HsInteger i integer_ty))
+
 mkRatLit :: Rational -> TcM TcExpr
 mkRatLit r
-  = tcLookupTyCon rationalTyConName                    `thenM` \ rat_tc ->
-    let
-       rational_ty  = mkGenTyConApp rat_tc []
-    in
-    returnM (HsLit (HsRat r rational_ty))
+  = tcMetaTy rationalTyConName         `thenM` \ rat_ty ->
+    returnM (HsLit (HsRat r rat_ty))
 \end{code}
 
 
@@ -486,7 +476,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]
@@ -501,6 +491,16 @@ pprInst m@(Method u id tys theta tau loc)
          show_uniq u,
          ppr (instToId m) -}]
 
+
+pprDFuns :: [DFunId] -> SDoc
+-- Prints the dfun as an instance declaration
+pprDFuns dfuns = vcat [ hang (ppr (getSrcLoc dfun) <> colon)
+                       2 (ptext SLIT("instance") <+> sep [pprThetaArrow theta,
+                                                          pprClassPred clas tys])
+                     | dfun <- dfuns
+                     , let (_, theta, clas, tys) = tcSplitDFunTy (idType dfun) ]
+       -- Print without the for-all, which the programmer doesn't write
+
 show_uniq u = ifPprDebug (text "{-" <> ppr u <> text "-}")
 
 tidyInst :: TidyEnv -> Inst -> Inst
@@ -519,16 +519,77 @@ 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}
 
 
 %************************************************************************
 %*                                                                     *
+       Extending the instance environment
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+tcExtendLocalInstEnv :: [DFunId] -> TcM a -> TcM a
+  -- Add new locally-defined instances
+tcExtendLocalInstEnv dfuns thing_inside
+ = do { traceDFuns dfuns
+      ; env <- getGblEnv
+      ; dflags  <- getDOpts
+      ; inst_env' <- foldlM (addInst dflags) (tcg_inst_env env) dfuns
+      ; let env' = env { tcg_insts = dfuns ++ tcg_insts env,
+                        tcg_inst_env = inst_env' }
+      ; setGblEnv env' thing_inside }
+
+addInst :: DynFlags -> InstEnv -> DFunId -> TcM InstEnv
+-- Check that the proposed new instance is OK, 
+-- and then add it to the home inst env
+addInst dflags home_ie dfun
+  = do {       -- Load imported instances, so that we report
+               -- duplicates correctly
+         pkg_ie  <- loadImportedInsts cls tys
+
+               -- Check functional dependencies
+       ; case checkFunDeps (pkg_ie, home_ie) dfun of
+               Just dfuns -> funDepErr dfun dfuns
+               Nothing    -> return ()
+
+               -- Check for duplicate instance decls
+       ; let { (matches, _) = lookupInstEnv dflags (pkg_ie, home_ie) cls tys
+             ; dup_dfuns = [dup_dfun | (_, (_, dup_tys, dup_dfun)) <- matches,
+                                       isJust (matchTys (mkVarSet tvs) tys dup_tys)] }
+               -- Find memebers of the match list which 
+               -- dfun itself matches. If the match is 2-way, it's a duplicate
+       ; case dup_dfuns of
+           dup_dfun : _ -> dupInstErr dfun dup_dfun
+           []           -> return ()
+
+               -- OK, now extend the envt
+       ; return (extendInstEnv home_ie dfun) }
+  where
+    (tvs, _, cls, tys) = tcSplitDFunTy (idType dfun)
+
+traceDFuns dfuns
+  = traceTc (text "Adding instances:" <+> vcat (map pp dfuns))
+  where
+    pp dfun = ppr dfun <+> dcolon <+> ppr (idType dfun)
+
+funDepErr dfun dfuns
+  = addSrcLoc (getSrcLoc dfun) $
+    addErr (hang (ptext SLIT("Functional dependencies conflict between instance declarations:"))
+              2 (pprDFuns (dfun:dfuns)))
+dupInstErr dfun dup_dfun
+  = addSrcLoc (getSrcLoc dfun) $
+    addErr (hang (ptext SLIT("Duplicate instance declarations:"))
+              2 (pprDFuns [dfun, dup_dfun]))
+\end{code}
+
+%************************************************************************
+%*                                                                     *
 \subsection{Looking up Insts}
 %*                                                                     *
 %************************************************************************
@@ -545,44 +606,6 @@ lookupInst :: Inst -> TcM (LookupInstResult s)
 -- the LookupInstResult, where they can be further processed by tcSimplify
 
 
--- Dictionaries
-lookupInst dict@(Dict _ (ClassP clas tys) loc)
-  = getDOpts                   `thenM` \ dflags ->
-    tcGetInstEnv               `thenM` \ inst_env ->
-    case lookupInstEnv dflags inst_env clas tys of
-
-      FoundInst tenv dfun_id
-       ->      -- 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) -> returnM ty
-                                  Nothing          -> tcInstTyVar VanillaTv tv `thenM` \ tc_tv ->
-                                                      returnM (mkTyVarTy tc_tv)
-          in
-          mappM mk_ty_arg tyvars       `thenM` \ ty_args ->
-          let
-               dfun_rho   = substTy (mkTyVarSubst tyvars ty_args) rho
-               (theta, _) = tcSplitPhiTy dfun_rho
-               ty_app     = mkHsTyApp (HsVar dfun_id) ty_args
-          in
-          if null theta then
-               returnM (SimpleInst ty_app)
-          else
-          newDictsAtLoc loc theta      `thenM` \ dicts ->
-          let 
-               rhs = mkHsDictApp ty_app (map instToId dicts)
-          in
-          returnM (GenInst dicts rhs)
-
-      other    -> returnM NoInstance
-
-lookupInst (Dict _ _ _)         = returnM NoInstance
-
 -- Methods
 
 lookupInst inst@(Method _ id tys theta _ loc)
@@ -605,10 +628,10 @@ lookupInst inst@(LitInst u (HsIntegral i from_integer_name) ty loc)
   | otherwise
   = ASSERT( from_integer_name == fromIntegerName )     -- A LitInst invariant
     tcLookupId fromIntegerName                 `thenM` \ from_integer ->
-    newMethodAtLoc loc from_integer [ty]       `thenM` \ method_inst ->
+    tcInstClassOp loc from_integer [ty]                `thenM` \ method_inst ->
+    mkIntegerLit i                             `thenM` \ integer_lit ->
     returnM (GenInst [method_inst]
-                    (HsApp (HsVar (instToId method_inst)) (HsLit (HsInteger i))))
-
+                    (HsApp (HsVar (instToId method_inst)) integer_lit))
 
 lookupInst inst@(LitInst u (HsFractional f from_rat_name) ty loc)
   | Just expr <- shortCutFracLit f ty
@@ -617,35 +640,94 @@ lookupInst inst@(LitInst u (HsFractional f from_rat_name) ty loc)
   | otherwise
   = ASSERT( from_rat_name == fromRationalName )        -- A LitInst invariant
     tcLookupId fromRationalName                        `thenM` \ from_rational ->
-    newMethodAtLoc loc from_rational [ty]      `thenM` \ method_inst ->
+    tcInstClassOp loc from_rational [ty]       `thenM` \ method_inst ->
     mkRatLit f                                 `thenM` \ rat_lit ->
     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.
+-- Dictionaries
+lookupInst dict@(Dict _ pred@(ClassP clas tys) loc)
+  = do { dflags  <- getDOpts
+       ; if all tcIsTyVarTy tys && 
+            not (dopt Opt_AllowUndecidableInstances dflags)
+               -- Common special case; no lookup
+               -- NB: tcIsTyVarTy... don't look through newtypes!
+               -- Don't take this short cut if we allow undecidable instances
+               -- because we might have "instance T a where ...".
+               -- [That means we need -fallow-undecidable-instances in the 
+               --  client module, as well as the module with the instance decl.]
+         then return NoInstance
+
+         else do
+       { pkg_ie  <- loadImportedInsts clas tys
+               -- Suck in any instance decls that may be relevant
+       ; tcg_env <- getGblEnv
+       ; case lookupInstEnv dflags (pkg_ie, tcg_inst_env tcg_env) clas tys of {
+           ([(tenv, (_,_,dfun_id))], []) -> instantiate_dfun tenv dfun_id pred loc ;
+           (matches, unifs)              -> do
+       { traceTc (text "lookupInst" <+> vcat [text "matches" <+> ppr matches,
+                                              text "unifs" <+> ppr unifs])
+       ; return NoInstance } } } }
+               -- In the case of overlap (multiple matches) we report
+               -- NoInstance here.  That has the effect of making the 
+               -- context-simplifier return the dict as an irreducible one.
+               -- Then it'll be given to addNoInstanceErrs, which will do another
+               -- lookupInstEnv to get the detailed info about what went wrong.
+
+lookupInst (Dict _ _ _) = returnM NoInstance
+
+-----------------
+instantiate_dfun tenv dfun_id pred loc
+  =    -- Record that this dfun is needed
+    record_dfun_usage dfun_id          `thenM_`
+
+       -- 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.        
+    getStage                                           `thenM` \ use_stage ->
+    checkWellStaged (ptext SLIT("instance for") <+> quotes (ppr pred))
+                   (topIdLvl dfun_id) use_stage                `thenM_`
+    let
+       (tyvars, rho) = tcSplitForAllTys (idType dfun_id)
+       mk_ty_arg tv  = case lookupSubstEnv tenv tv of
+                          Just (DoneTy ty) -> returnM ty
+                          Nothing          -> tcInstTyVar VanillaTv tv `thenM` \ tc_tv ->
+                                              returnM (mkTyVarTy tc_tv)
+    in
+    mappM mk_ty_arg tyvars     `thenM` \ ty_args ->
+    let
+       dfun_rho   = substTy (mkTyVarSubst tyvars ty_args) rho
+       (theta, _) = tcSplitPhiTy dfun_rho
+       ty_app     = mkHsTyApp (HsVar dfun_id) ty_args
+    in
+    if null theta then
+       returnM (SimpleInst ty_app)
+    else
+    newDictsAtLoc loc theta    `thenM` \ dicts ->
+    let 
+       rhs = mkHsDictApp ty_app (map instToId dicts)
+    in
+    returnM (GenInst dicts rhs)
+
+record_dfun_usage dfun_id
+  | isInternalName dfun_name = return ()               -- From this module
+  | not (isHomePackageName dfun_name) = return ()      -- From another package package
+  | otherwise = getGblEnv      `thenM` \ tcg_env ->
+               updMutVar (tcg_inst_uses tcg_env)
+                         (`addOneToNameSet` idName dfun_id)
+  where
+    dfun_name = idName dfun_id
 
-\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
+tcGetInstEnvs :: TcM (InstEnv, InstEnv)
+-- Gets both the home-pkg inst env (includes module being compiled)
+-- and the external-package inst-env
+tcGetInstEnvs = do { eps <- getEps; env <- getGblEnv;
+                    return (tcg_inst_env env, eps_inst_env eps) }
 \end{code}
 
 
+
 %************************************************************************
 %*                                                                     *
                Re-mappable syntax
@@ -678,27 +760,40 @@ 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)
+  = tcStdSyntaxName orig ty std_nm
 
-  | 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            = substTy (mkTopTyVarSubst [tv] [ty]) tau
+       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)        $
+
+       -- Check that the user-supplied thing has the
+       -- same type as the standard one
+    tcCheckSigma user_nm_expr tau1                     `thenM` \ expr ->
+    returnM (std_nm, expr)
+
+tcStdSyntaxName :: InstOrigin
+               -> TcType               -- Type to instantiate it at
+               -> Name                 -- Standard name
+               -> TcM (Name, TcExpr)   -- (Standard name, suitable expression)
+
+tcStdSyntaxName orig ty std_nm
+  = newMethodFromName orig ty std_nm   `thenM` \ id ->
+    returnM (std_nm, HsVar id)
 
 syntaxNameCtxt name orig ty tidy_env
   = getInstLoc orig            `thenM` \ inst_loc ->