[project @ 2002-09-09 12:50:26 by simonpj]
[ghc-hetmet.git] / ghc / compiler / typecheck / Inst.lhs
index 3d03c32..e24e440 100644 (file)
@@ -11,17 +11,19 @@ module Inst (
        Inst, 
        pprInst, pprInsts, pprInstsInFull, tidyInsts, tidyMoreInsts,
 
-       newDictsFromOld, newDicts, 
-       newMethod, newMethodWithGivenTy, newOverloadedLit,
-       newIPDict, tcInstId,
+       newDictsFromOld, newDicts, cloneDict,
+       newMethod, newMethodFromName, newMethodWithGivenTy, newMethodAtLoc,
+       newOverloadedLit, newIPDict, 
+       tcInstCall, tcInstDataCon, tcSyntaxName,
 
        tyVarsOfInst, tyVarsOfInsts, tyVarsOfLIE, 
        ipNamesOfInst, ipNamesOfInsts, predsOfInst, predsOfInsts,
-       instLoc, getDictClassTys, 
+       instLoc, getDictClassTys, dictPred,
 
        lookupInst, lookupSimpleInst, LookupInstResult(..),
 
        isDict, isClassDict, isMethod, 
+       isLinearInst, linearInstType,
        isTyVarDict, isStdClassTyVarDict, isMethodFor, 
        instBindingRequired, instCanBeGeneralised,
 
@@ -33,36 +35,37 @@ module Inst (
 
 #include "HsVersions.h"
 
-import CmdLineOpts ( opt_NoMethodSharing )
+import {-# SOURCE #-}  TcExpr( tcExpr )
+
 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 TcEnv   ( TcIdSet, tcGetInstEnv, tcLookupId, tcLookupGlobalId, tcLookupTyCon )
 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, 
-                 SourceType(..), PredType, ThetaType,
-                 tcSplitForAllTys, tcSplitForAllTys, 
-                 tcSplitMethodTy, tcSplitRhoTy, tcFunArgTy,
+import TcType  ( Type, TcType, TcThetaType, TcPredType, TcTauType, TcTyVarSet,
+                 SourceType(..), PredType, ThetaType, TyVarDetails(VanillaTv),
+                 tcSplitForAllTys, tcSplitForAllTys, mkTyConApp,
+                 tcSplitMethodTy, tcSplitPhiTy, mkGenTyConApp,
                  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
+                 tidyType, tidyTypes, tidyFreeTyVars, 
+                 tcCmpType, tcCmpTypes, tcCmpPred, tcSplitSigmaTy
                )
 import CoreFVs ( idFreeTyVars )
 import Class   ( Class )
-import Id      ( Id, idName, idType, mkUserLocal, mkSysLocal, mkLocalId )
+import DataCon ( dataConSig )
+import Id      ( Id, idName, idType, mkUserLocal, mkSysLocal, mkLocalId, setIdUnique )
 import PrelInfo        ( isStandardClass, isCcallishClass, isNoDictClass )
 import Name    ( Name, mkMethodOcc, getOccName )
-import NameSet ( NameSet )
-import PprType ( pprPred )     
+import PprType ( pprPred, pprParendType )      
 import Subst   ( emptyInScopeSet, mkSubst, 
                  substTy, substTyWith, substTheta, mkTyVarSubst, mkTopTyVarSubst
                )
@@ -70,8 +73,10 @@ import Literal       ( inIntRange )
 import VarEnv  ( TidyEnv, lookupSubstEnv, SubstResult(..) )
 import VarSet  ( elemVarSet, emptyVarSet, unionVarSet )
 import TysWiredIn ( floatDataCon, doubleDataCon )
-import PrelNames( fromIntegerName, fromRationalName )
+import PrelNames( fromIntegerName, fromRationalName, rationalTyConName )
 import Util    ( thenCmp, equalLength )
+import BasicTypes( IPName(..), mapIPName, ipNameName )
+
 import Bag
 import Outputable
 \end{code}
@@ -156,6 +161,9 @@ data Inst
   | LitInst
        Id
        HsOverLit       -- The literal from the occurrence site
+                       --      INVARIANT: never a rebindable-syntax literal
+                       --      Reason: tcSyntaxName does unification, and we
+                       --              don't want to deal with that during tcSimplify
        TcType          -- The type at which the literal is used
        InstLoc
 \end{code}
@@ -204,6 +212,9 @@ instLoc (Dict _ _         loc) = loc
 instLoc (Method _ _ _ _ _ loc) = loc
 instLoc (LitInst _ _ _    loc) = loc
 
+dictPred (Dict _ pred _ ) = pred
+dictPred inst            = pprPanic "dictPred" (ppr inst)
+
 getDictClassTys (Dict _ pred _) = getClassPredTys pred
 
 predsOfInsts :: [Inst] -> [PredType]
@@ -220,11 +231,12 @@ predsOfInst (LitInst _ _ _ _)          = []
 ipNamesOfInsts :: [Inst] -> [Name]
 ipNamesOfInst  :: Inst   -> [Name]
 -- Get the implicit parameters mentioned by these Insts
+-- NB: ?x and %x get different Names
 
 ipNamesOfInsts insts = [n | inst <- insts, n <- ipNamesOfInst inst]
 
-ipNamesOfInst (Dict _ (IParam n _) _)  = [n]
-ipNamesOfInst (Method _ _ _ theta _ _) = [n | IParam n _ <- theta]
+ipNamesOfInst (Dict _ (IParam n _) _)  = [ipNameName n]
+ipNamesOfInst (Method _ _ _ theta _ _) = [ipNameName n | IParam n _ <- theta]
 ipNamesOfInst other                   = []
 
 tyVarsOfInst :: Inst -> TcTyVarSet
@@ -261,6 +273,18 @@ isMethodFor :: TcIdSet -> Inst -> Bool
 isMethodFor ids (Method uniq id tys _ _ loc) = id `elemVarSet` ids
 isMethodFor ids inst                        = False
 
+isLinearInst :: Inst -> Bool
+isLinearInst (Dict _ pred _) = isLinearPred pred
+isLinearInst other          = False
+       -- We never build Method Insts that have
+       -- linear implicit paramters in them.
+       -- Hence no need to look for Methods
+       -- See TcExpr.tcId 
+
+linearInstType :: Inst -> TcType       -- %x::t  -->  t
+linearInstType (Dict _ (IParam _ ty) _) = ty
+
+
 isStdClassTyVarDict (Dict _ pred _) = case getClassPredTys_maybe pred of
                                        Just (clas, [ty]) -> isStandardClass clas && tcIsTyVarTy ty
                                        other             -> False
@@ -274,7 +298,6 @@ must be witnessed by an actual binding; the second tells whether an
 \begin{code}
 instBindingRequired :: Inst -> Bool
 instBindingRequired (Dict _ (ClassP clas _) _) = not (isNoDictClass clas)
-instBindingRequired (Dict _ (IParam _ _) _)    = False
 instBindingRequired other                     = True
 
 instCanBeGeneralised :: Inst -> Bool
@@ -297,6 +320,10 @@ newDicts orig theta
   = tcGetInstLoc orig          `thenNF_Tc` \ loc ->
     newDictsAtLoc loc theta
 
+cloneDict :: Inst -> NF_TcM Inst
+cloneDict (Dict id ty loc) = tcGetUnique       `thenNF_Tc` \ uniq ->
+                            returnNF_Tc (Dict (setIdUnique id uniq) ty loc)
+
 newDictsFromOld :: Inst -> TcThetaType -> NF_TcM [Inst]
 newDictsFromOld (Dict _ _ loc) theta = newDictsAtLoc loc theta
 
@@ -311,12 +338,20 @@ newDictsAtLoc inst_loc@(_,loc,_) theta
   where
     mk_dict uniq pred = Dict (mkLocalId (mkPredName uniq loc pred) (mkPredTy pred)) pred inst_loc
 
--- For implicit parameters, since there is only one in scope
--- at any time, we use the name of the implicit parameter itself
-newIPDict orig name ty
-  = tcGetInstLoc orig                  `thenNF_Tc` \ inst_loc ->
-    returnNF_Tc (Dict (mkLocalId name (mkPredTy pred)) pred inst_loc)
-  where pred = IParam name ty
+-- 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
+-- But with splittable implicit parameters there may be many in 
+-- scope, so we make up a new name.
+newIPDict :: InstOrigin -> IPName Name -> Type 
+         -> NF_TcM (IPName Id, Inst)
+newIPDict orig ip_name ty
+  = tcGetInstLoc orig                  `thenNF_Tc` \ inst_loc@(_,loc,_) ->
+    tcGetUnique                                `thenNF_Tc` \ uniq ->
+    let
+       pred = IParam ip_name ty
+       id   = mkLocalId (mkPredName uniq loc pred) (mkPredTy pred)
+    in
+    returnNF_Tc (mapIPName (\n -> id) ip_name, Dict id pred inst_loc)
 \end{code}
 
 
@@ -326,61 +361,50 @@ newIPDict orig 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
-  | opt_NoMethodSharing  = loop_noshare (HsVar fun) (idType fun)
-  | otherwise           = loop_share fun
-  where
-    orig = OccurrenceOf fun
-    loop_noshare fun fun_ty
-      = tcInstType fun_ty              `thenNF_Tc` \ (tyvars, theta, tau) ->
-       let 
-           ty_app = mkHsTyApp fun (mkTyVarTys tyvars)
-       in
-        if null theta then             -- Is it overloaded?
-           returnNF_Tc (ty_app, emptyLIE, tau)
-       else
-           newDicts orig theta                                         `thenNF_Tc` \ dicts ->
-           loop_noshare (mkHsDictApp ty_app (map instToId dicts)) tau  `thenNF_Tc` \ (expr, lie, final_tau) ->
-           returnNF_Tc (expr, mkLIE dicts `plusLIE` lie, final_tau)
-
-    loop_share fun
-      = tcInstType (idType fun)                `thenNF_Tc` \ (tyvars, theta, tau) ->
-       let 
-           arg_tys = mkTyVarTys tyvars
-       in
-        if null theta then             -- Is it overloaded?
-           returnNF_Tc (mkHsTyApp (HsVar fun) arg_tys, emptyLIE, tau)
-       else
-               -- Yes, it's overloaded
-           newMethodWithGivenTy orig fun arg_tys theta tau     `thenNF_Tc` \ meth ->
-           loop_share (instToId meth)                          `thenNF_Tc` \ (expr, lie, final_tau) ->
-           returnNF_Tc (expr, unitLIE meth `plusLIE` lie, final_tau)
+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 (tvs ++ ex_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_normal_tvs  = length tvs
+       ex_tvs'       = drop n_normal_tvs all_tvs'
+       result_ty     = mkTyConApp tycon (take n_normal_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')
+
+
+newMethodFromName :: InstOrigin -> TcType -> Name -> NF_TcM Inst
+newMethodFromName origin ty name
+  = tcLookupId name            `thenNF_Tc` \ id ->
+       -- Use tcLookupId not tcLookupGlobalId; the method is almost
+       -- 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
@@ -416,7 +440,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)
@@ -432,34 +456,66 @@ newOverloadedLit :: InstOrigin
                 -> HsOverLit
                 -> TcType
                 -> NF_TcM (TcExpr, LIE)
-newOverloadedLit orig lit ty
-  | Just expr <- shortCutLit lit ty
+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   `thenTc` \ (expr, lie, _) ->
+    returnTc (HsApp expr (HsLit (HsInteger i)), lie)
+
+  | Just expr <- shortCutIntLit i expected_ty 
+  = returnNF_Tc (expr, emptyLIE)
+
+  | otherwise
+  = newLitInst orig lit expected_ty
+
+newOverloadedLit orig lit@(HsFractional r fr) expected_ty
+  | fr /= fromRationalName     -- c.f. HsIntegral case
+  = tcSyntaxName orig expected_ty fromRationalName fr  `thenTc` \ (expr, lie, _) ->
+    mkRatLit r                                         `thenNF_Tc` \ rat_lit ->
+    returnTc (HsApp expr rat_lit, lie)
+
+  | Just expr <- shortCutFracLit r expected_ty 
   = returnNF_Tc (expr, emptyLIE)
 
   | otherwise
+  = newLitInst orig lit expected_ty
+
+newLitInst orig lit expected_ty
   = 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)
 
-shortCutLit :: HsOverLit -> TcType -> Maybe TcExpr
-shortCutLit (HsIntegral i fi) ty
-  | isIntTy ty && inIntRange i && fi == fromIntegerName                -- Short cut for Int
+shortCutIntLit :: Integer -> TcType -> Maybe TcExpr
+shortCutIntLit i ty
+  | isIntTy ty && inIntRange i                         -- Short cut for Int
   = Just (HsLit (HsInt i))
-  | isIntegerTy ty && fi == fromIntegerName                    -- Short cut for Integer
+  | isIntegerTy ty                             -- Short cut for Integer
   = Just (HsLit (HsInteger i))
+  | otherwise = Nothing
 
-shortCutLit (HsFractional f fr) ty
-  | isFloatTy ty  && fr == fromRationalName 
+shortCutFracLit :: Rational -> TcType -> Maybe TcExpr
+shortCutFracLit f ty
+  | isFloatTy ty 
   = Just (mkHsConApp floatDataCon [] [HsLit (HsFloatPrim f)])
-  | isDoubleTy ty && fr == fromRationalName 
+  | isDoubleTy ty
   = Just (mkHsConApp doubleDataCon [] [HsLit (HsDoublePrim f)])
+  | otherwise = Nothing
 
-shortCutLit lit ty
-  = Nothing
+mkRatLit :: Rational -> NF_TcM TcExpr
+mkRatLit r
+  = tcLookupTyCon rationalTyConName                    `thenNF_Tc` \ rat_tc ->
+    let
+       rational_ty  = mkGenTyConApp rat_tc []
+    in
+    returnNF_Tc (HsLit (HsRat r rational_ty))
 \end{code}
 
 
@@ -518,7 +574,7 @@ pprInst (Dict u pred loc) = pprPred pred <+> show_uniq u
 
 pprInst m@(Method u id tys theta tau loc)
   = hsep [ppr id, ptext SLIT("at"), 
-         brackets (interppSP tys) {- ,
+         brackets (sep (map pprParendType tys)) {- ,
          ptext SLIT("theta"), ppr theta,
          ptext SLIT("tau"), ppr tau
          show_uniq u,
@@ -562,23 +618,28 @@ lookupInst :: Inst
 -- Dictionaries
 
 lookupInst dict@(Dict _ (ClassP clas tys) loc)
-  = tcGetInstEnv               `thenNF_Tc` \ inst_env ->
-    case lookupInstEnv inst_env clas tys of
+  = getDOptsTc                 `thenNF_Tc` \ dflags ->
+    tcGetInstEnv               `thenNF_Tc` \ inst_env ->
+    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
           mapNF_Tc mk_ty_arg tyvars    `thenNF_Tc` \ ty_args ->
           let
-               subst         = mkTyVarSubst tyvars ty_args
-               dfun_rho      = substTy subst rho
-               (theta, _)    = tcSplitRhoTy dfun_rho
-               ty_app        = mkHsTyApp (HsVar dfun_id) ty_args
+               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
                returnNF_Tc (SimpleInst ty_app)
@@ -607,26 +668,28 @@ lookupInst inst@(Method _ id tys theta _ loc)
 -- [Same shortcut as in newOverloadedLit, but we
 --  may have done some unification by now]             
 
-lookupInst inst@(LitInst u lit ty loc)
-  | Just expr <- shortCutLit lit ty
+lookupInst inst@(LitInst u (HsIntegral i from_integer_name) ty loc)
+  | Just expr <- shortCutIntLit i ty
   = returnNF_Tc (GenInst [] expr)      -- GenInst, not SimpleInst, because 
                                        -- expr may be a constructor application
-
-lookupInst inst@(LitInst u (HsIntegral i from_integer_name) ty loc)
-  = tcLookupId from_integer_name               `thenNF_Tc` \ from_integer ->
+  | otherwise
+  = ASSERT( from_integer_name == fromIntegerName )     -- A LitInst invariant
+    tcLookupGlobalId fromIntegerName           `thenNF_Tc` \ from_integer ->
     newMethodAtLoc loc from_integer [ty]       `thenNF_Tc` \ (method_inst, method_id) ->
-    returnNF_Tc (GenInst [method_inst] 
+    returnNF_Tc (GenInst [method_inst]
                         (HsApp (HsVar method_id) (HsLit (HsInteger i))))
 
 
 lookupInst inst@(LitInst u (HsFractional f from_rat_name) ty loc)
-  = tcLookupId from_rat_name                   `thenNF_Tc` \ from_rational ->
+  | Just expr <- shortCutFracLit f ty
+  = returnNF_Tc (GenInst [] expr)
+
+  | otherwise
+  = ASSERT( from_rat_name == fromRationalName )        -- A LitInst invariant
+    tcLookupGlobalId fromRationalName          `thenNF_Tc` \ from_rational ->
     newMethodAtLoc loc from_rational [ty]      `thenNF_Tc` \ (method_inst, method_id) ->
-    let
-       rational_ty  = tcFunArgTy (idType method_id)
-       rational_lit = HsLit (HsRat f rational_ty)
-    in
-    returnNF_Tc (GenInst [method_inst] (HsApp (HsVar method_id) rational_lit))
+    mkRatLit f                                 `thenNF_Tc` \ rat_lit ->
+    returnNF_Tc (GenInst [method_inst] (HsApp (HsVar method_id) rat_lit))
 \end{code}
 
 There is a second, simpler interface, when you want an instance of a
@@ -640,13 +703,83 @@ lookupSimpleInst :: Class
                 -> NF_TcM (Maybe ThetaType)    -- Here are the needed (c,t)s
 
 lookupSimpleInst clas tys
-  = tcGetInstEnv               `thenNF_Tc` \ inst_env -> 
-    case lookupInstEnv inst_env clas tys of
+  = getDOptsTc                 `thenNF_Tc` \ dflags ->
+    tcGetInstEnv               `thenNF_Tc` \ inst_env -> 
+    case lookupInstEnv dflags inst_env clas tys of
       FoundInst tenv dfun
        -> 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}
+
+
+%************************************************************************
+%*                                                                     *
+               Re-mappable syntax
+%*                                                                     *
+%************************************************************************
+
+
+Suppose we are doing the -fno-implicit-prelude 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
+this:
+
+  (>>) :: HB m n mn => m a -> n b -> mn b
+
+So the idea is to generate a local binding for (>>), thus:
+
+       let then72 :: forall a b. m a -> m b -> m b
+           then72 = ...something involving the user's (>>)...
+       in
+       ...the do-expression...
+
+Now the do-expression can proceed using then72, which has exactly
+the expected type.
+
+In fact tcSyntaxName just generates the RHS for then72, because we only
+want an actual binding in the do-expression case. For literals, we can 
+just use the expression inline.
+
+\begin{code}
+tcSyntaxName :: InstOrigin
+            -> TcType                          -- Type to instantiate it at
+            -> Name -> Name                    -- (Standard name, user name)
+            -> TcM (TcExpr, LIE, TcType)       -- Suitable expression with its type
+
+-- 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
+  | std_nm == user_nm
+  = newMethodFromName orig ty std_nm   `thenNF_Tc` \ inst ->
+    let
+       id = instToId inst
+    in
+    returnTc (HsVar id, unitLIE inst, idType id)
+
+  | otherwise
+  = tcLookupGlobalId std_nm            `thenNF_Tc` \ std_id ->
+    let        
+       -- C.f. newMethodAtLoc
+       ([tv], _, tau)  = tcSplitSigmaTy (idType std_id)
+       tau1            = substTy (mkTopTyVarSubst [tv] [ty]) tau
+    in
+    tcAddErrCtxtM (syntaxNameCtxt user_nm orig tau1)   $
+    tcExpr (HsVar user_nm) tau1                                `thenTc` \ (user_fn, lie) ->
+    returnTc (user_fn, lie, tau1)
+
+syntaxNameCtxt name orig ty tidy_env
+  = tcGetInstLoc orig          `thenNF_Tc` \ inst_loc ->
+    let
+       msg = vcat [ptext SLIT("When checking that") <+> quotes (ppr name) <+> 
+                               ptext SLIT("(needed by a syntactic construct)"),
+                   nest 2 (ptext SLIT("has the required type:") <+> ppr (tidyType tidy_env ty)),
+                   nest 2 (pprInstLoc inst_loc)]
+    in
+    returnNF_Tc (tidy_env, msg)
+\end{code}