[project @ 2002-10-18 13:41:50 by simonpj]
authorsimonpj <unknown>
Fri, 18 Oct 2002 13:41:55 +0000 (13:41 +0000)
committersimonpj <unknown>
Fri, 18 Oct 2002 13:41:55 +0000 (13:41 +0000)
--------------------------------
   Fix a serious error in the "newtype deriving" feature
--------------------------------

The "newtype deriving" feature lets you derive arbitrary classes for
a newtype, not just the built-in ones (Read, Show, Ix etc).  It's very
cool, but Hal Duame discovered that it did utterly the Wrong Thing
for superclasses.  E.g.

newtype Foo = MkFoo Int deriving( Show, Num, Eq )

You'd get a Num instance for Foo that was *identical* to the
Num instance for Int, *including* the Show superclass. So the
superclass in the Num dictionary would show a Foo just like an
Int, which is wrong... it should show as "Foo n".

This commit fixes the problem, by building a new dictionary every time,
but using the methods from the dictionary for the representation type.

I also fixed a bug that prevented it working altogether when the
representation type was not the application of a type constructor.
For example, this now works

newtype Foo a = MkFoo a deriving( Num, Eq, Show )

I also made it a bit more efficient in the case where the type is
not parameterised.  Then the "dfun" doesn't need to be a function.

ghc/compiler/basicTypes/MkId.lhs
ghc/compiler/typecheck/Inst.lhs
ghc/compiler/typecheck/TcClassDcl.lhs
ghc/compiler/typecheck/TcDeriv.lhs
ghc/compiler/typecheck/TcEnv.lhs
ghc/compiler/typecheck/TcExpr.lhs
ghc/compiler/typecheck/TcInstDcls.lhs

index 60e0c8d..1658786 100644 (file)
@@ -743,13 +743,13 @@ that they aren't discarded by the occurrence analyser.
 mkDefaultMethodId dm_name ty = mkVanillaGlobal dm_name ty noCafIdInfo
 
 mkDictFunId :: Name            -- Name to use for the dict fun;
-           -> Class 
            -> [TyVar]
-           -> [Type]
            -> ThetaType
+           -> Class 
+           -> [Type]
            -> Id
 
-mkDictFunId dfun_name clas inst_tyvars inst_tys dfun_theta
+mkDictFunId dfun_name inst_tyvars dfun_theta clas inst_tys
   = mkVanillaGlobal dfun_name dfun_ty noCafIdInfo
   where
     dfun_ty = mkSigmaTy inst_tyvars dfun_theta (mkDictTy clas inst_tys)
index 92d6aa3..ccd8e43 100644 (file)
@@ -308,13 +308,12 @@ 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]   `thenM` \ inst ->
-    returnM (instToId inst)
+    newMethod origin id [ty]
 
 newMethod :: InstOrigin
          -> TcId
          -> [TcType]
-         -> TcM Inst
+         -> TcM Id
 newMethod orig id tys
   =    -- Get the Id type and instantiate it at the specified types
     let
@@ -328,7 +327,7 @@ newMethodWithGivenTy orig id tys theta tau
   = getInstLoc orig                    `thenM` \ loc ->
     newMethodWith loc id tys theta tau `thenM` \ inst ->
     extendLIE inst                     `thenM_`
-    returnM inst
+    returnM (instToId inst)
 
 --------------------------------------------
 -- newMethodWith and newMethodAtLoc do *not* drop the 
index 5bb0e51..c39d8a0 100644 (file)
@@ -5,7 +5,7 @@
 
 \begin{code}
 module TcClassDcl ( tcClassDecl1, tcClassDecls2, 
-                   tcMethodBind, mkMethodBind, badMethodErr
+                   MethodSpec, tcMethodBind, mkMethodBind, badMethodErr
                  ) where
 
 #include "HsVersions.h"
@@ -435,6 +435,10 @@ time, because their signatures may have different contexts and
 tyvar sets.
 
 \begin{code}
+type MethodSpec = (Id,                         -- Global selector Id
+                  TcSigInfo,           -- Signature 
+                  RenamedMonoBinds)    -- Binding for the method
+
 tcMethodBind 
        :: [(TyVar,TcTyVar)]    -- Bindings for type environment
        -> [TcTyVar]            -- Instantiated type variables for the
@@ -446,7 +450,7 @@ tcMethodBind
        -> [Inst]               -- Available from context, used to simplify constraints 
                                --      from the method body
        -> [RenamedSig]         -- Pragmas (e.g. inline pragmas)
-       -> (Id, TcSigInfo, RenamedMonoBinds)    -- Details of this method
+       -> MethodSpec           -- Details of this method
        -> TcM TcMonoBinds
 
 tcMethodBind xtve inst_tyvars inst_theta avail_insts prags
@@ -508,9 +512,9 @@ mkMethodBind :: InstOrigin
             -> RenamedMonoBinds        -- Method binding (pick the right one from in here)
             -> ClassOpItem
             -> TcM (Inst,              -- Method inst
-                    (Id,                       -- Global selector Id
-                     TcSigInfo,                -- Signature 
-                     RenamedMonoBinds))        -- Binding for the method
+                    MethodSpec)
+-- Find the binding for the specified method, or make
+-- up a suitable default method if it isn't there
 
 mkMethodBind origin clas inst_tys meth_binds (sel_id, dm_info)
   = getInstLoc origin                          `thenM` \ inst_loc ->
index 0dc41a8..99f3544 100644 (file)
@@ -17,7 +17,8 @@ import RnHsSyn                ( RenamedHsBinds, RenamedMonoBinds, RenamedTyClDecl, RenamedHsPr
 import CmdLineOpts     ( DynFlag(..) )
 
 import TcRnMonad
-import TcEnv           ( tcGetInstEnv, tcSetInstEnv, newDFunName, InstInfo(..), pprInstInfo,
+import TcEnv           ( tcGetInstEnv, tcSetInstEnv, newDFunName, 
+                         InstInfo(..), pprInstInfo, InstBindings(..),
                          pprInstInfoDetails, tcLookupTyCon, tcExtendTyVarEnv
                        )
 import TcGenDeriv      -- Deriv stuff
@@ -31,7 +32,8 @@ import TcRnMonad              ( thenM, returnM, mapAndUnzipM )
 import HscTypes                ( DFunId )
 
 import BasicTypes      ( NewOrData(..) )
-import Class           ( className, classKey, classTyVars, Class )
+import Class           ( className, classKey, classTyVars, classSCTheta, Class )
+import Subst           ( mkTyVarSubst, substTheta )
 import ErrUtils                ( dumpIfSet_dyn )
 import MkId            ( mkDictFunId )
 import DataCon         ( dataConRepArgTys, isNullaryDataCon, isExistentialDataCon )
@@ -46,7 +48,8 @@ import TyCon          ( tyConTyVars, tyConDataCons, tyConArity, newTyConRep,
                        )
 import TcType          ( TcType, ThetaType, mkTyVarTys, mkTyConApp, getClassPredTys_maybe,
                          isUnLiftedType, mkClassPred, tyVarsOfTypes, tcSplitFunTys, 
-                         tcSplitTyConApp_maybe, tcEqTypes )
+                         tcSplitTyConApp_maybe, tcEqTypes, mkAppTys )
+import Type            ( splitAppTys )
 import Var             ( TyVar, tyVarKind )
 import VarSet          ( mkVarSet, subVarSet )
 import PrelNames
@@ -153,8 +156,8 @@ type DerivSoln = DerivRhs
 \end{code}
 
 
-A note about contexts on data decls
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+[Data decl contexts] A note about contexts on data decls
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Consider
 
        data (RealFloat a) => Complex a = !a :+ !a deriving( Read )
@@ -273,7 +276,7 @@ deriveOrdinaryStuff inst_env_in eqns
        -- Make a Real dfun instead of the dummy one we have so far
     gen_inst_info :: DFunId -> RenamedMonoBinds -> InstInfo
     gen_inst_info dfun binds
-      = InstInfo { iDFunId = dfun, iBinds = binds, iPrags = [] }
+      = InstInfo { iDFunId = dfun, iBinds = VanillaInst binds [] }
 
     rn_meths (cls, meths) = rnMethodBinds cls [] meths
 \end{code}
@@ -353,20 +356,16 @@ makeDerivEqns tycl_decls
                        not (isUnLiftedType arg_ty)     -- No constraints for unlifted types?
                      ]
 
-        -- "extra_constraints": see notes above about contexts on data decls
+        -- "extra_constraints": see note [Data decl contexts] above
        extra_constraints = tyConTheta tycon
 
-       --    | offensive_class = tyConTheta tycon
-       --    | otherwise           = []
-       -- offensive_class = classKey clas `elem` PrelInfo.needsDataDeclCtxtClassKeys
-
-
     mk_eqn_help NewType tycon clas tys
       =        doptM Opt_GlasgowExts                   `thenM` \ gla_exts ->
         if can_derive_via_isomorphism && (gla_exts || standard_instance) then
                -- Go ahead and use the isomorphism
                   new_dfun_name clas tycon             `thenM` \ dfun_name ->
-          returnM (Nothing, Just (NewTypeDerived (mk_dfun dfun_name)))
+          returnM (Nothing, Just (InstInfo { iDFunId = mk_dfun dfun_name,
+                                             iBinds = NewTypeDerived rep_tys }))
        else
           if standard_instance then
                mk_eqn_help DataType tycon clas []      -- Go via bale-out route
@@ -374,17 +373,20 @@ makeDerivEqns tycl_decls
                bale_out cant_derive_err
       where
        -- Here is the plan for newtype derivings.  We see
-       --        newtype T a1...an = T (t ak...an) deriving (C1...Cm)
-       -- where aj...an do not occur free in t, and the Ci are *partial applications* of
-       -- classes with the last parameter missing
+       --        newtype T a1...an = T (t ak...an) deriving (.., C s1 .. sm, ...)
+       -- where aj...an do not occur free in t, and the (C s1 ... sm) is a 
+       -- *partial applications* of class C with the last parameter missing
        --
        -- We generate the instances
-       --       instance Ci (t ak...aj) => Ci (T a1...aj)
+       --       instance C s1 .. sm (t ak...aj) => C s1 .. sm (T a1...aj)
        -- where T a1...aj is the partial application of the LHS of the correct kind
        --
        -- Running example: newtype T s a = MkT (ST s a) deriving( Monad )
+       --      instance Monad (ST s) => Monad (T s) where 
+       --        fail = coerce ... (fail @ ST s)
 
-       kind = tyVarKind (last (classTyVars clas))
+       clas_tyvars = classTyVars clas
+       kind = tyVarKind (last clas_tyvars)
                -- Kind of the thing we want to instance
                --   e.g. argument kind of Monad, *->*
 
@@ -394,24 +396,55 @@ makeDerivEqns tycl_decls
                -- to get       instance Monad (ST s) => Monad (T s)
 
        (tyvars, rep_ty)           = newTyConRep tycon
-       maybe_rep_app              = tcSplitTyConApp_maybe rep_ty       
-       Just (rep_tc, rep_ty_args) = maybe_rep_app
+       (rep_fn, rep_ty_args)      = splitAppTys rep_ty
 
        n_tyvars_to_keep = tyConArity tycon  - n_args_to_drop
        tyvars_to_drop   = drop n_tyvars_to_keep tyvars
        tyvars_to_keep   = take n_tyvars_to_keep tyvars
 
-       n_args_to_keep = tyConArity rep_tc - n_args_to_drop
+       n_args_to_keep = length rep_ty_args - n_args_to_drop
        args_to_drop   = drop n_args_to_keep rep_ty_args
        args_to_keep   = take n_args_to_keep rep_ty_args
 
-       ctxt_pred = mkClassPred clas (tys ++ [mkTyConApp rep_tc args_to_keep])
-
-       mk_dfun dfun_name = mkDictFunId dfun_name clas tyvars 
-                                                 (tys ++ [mkTyConApp tycon (mkTyVarTys tyvars_to_keep)] )
-                                                 [ctxt_pred]
+       rep_tys  = tys ++ [mkAppTys rep_fn args_to_keep]
+       rep_pred = mkClassPred clas rep_tys
+               -- rep_pred is the representation dictionary, from where
+               -- we are gong to get all the methods for the newtype dictionary
+
+       inst_tys = (tys ++ [mkTyConApp tycon (mkTyVarTys tyvars_to_keep)])
+               -- The 'tys' here come from the partial application
+               -- in the deriving clause. The last arg is the new
+               -- instance type.
+
+               -- We must pass the superclasses; the newtype might be an instance
+               -- of them in a different way than the representation type
+               -- E.g.         newtype Foo a = Foo a deriving( Show, Num, Eq )
+               -- Then the Show instance is not done via isomprphism; it shows
+               --      Foo 3 as "Foo 3"
+               -- The Num instance is derived via isomorphism, but the Show superclass
+               -- dictionary must the Show instance for Foo, *not* the Show dictionary
+               -- gotten from the Num dictionary. So we must build a whole new dictionary
+               -- not just use the Num one.  The instance we want is something like:
+               --      instance (Num a, Show (Foo a), Eq (Foo a)) => Num (Foo a) where
+               --              (+) = ((+)@a)
+               --              ...etc...
+               -- There's no 'corece' needed because after the type checker newtypes
+               -- are transparent.
+
+       sc_theta = substTheta (mkTyVarSubst clas_tyvars inst_tys)
+                             (classSCTheta clas)
+
+               -- If there are no tyvars, there's no need
+               -- to abstract over the dictionaries we need
+       dict_args | null tyvars = []
+                 | otherwise   = rep_pred : sc_theta
+
+               -- Finally! Here's where we build the dictionary Id
+       mk_dfun dfun_name = mkDictFunId dfun_name tyvars dict_args clas inst_tys
+
+       -------------------------------------------------------------------
+       --  Figuring out whether we can only do this newtype-deriving thing
 
-       -- We can only do this newtype deriving thing if:
        standard_instance = null tys && classKey clas `elem` derivableClassKeys
 
        can_derive_via_isomorphism
@@ -419,7 +452,6 @@ makeDerivEqns tycl_decls
           && not (clas `hasKey` showClassKey)
           && n_tyvars_to_keep >= 0             -- Well kinded; 
                                                -- eg not: newtype T = T Int deriving( Monad )
-          && isJust maybe_rep_app              -- The rep type is a type constructor app
           && n_args_to_keep   >= 0             -- Well kinded: 
                                                -- eg not: newtype T a = T Int deriving( Monad )
           && eta_ok                            -- Eta reduction works
@@ -436,7 +468,12 @@ makeDerivEqns tycl_decls
              && (tyVarsOfTypes args_to_keep `subVarSet` mkVarSet tyvars_to_keep) 
 
        cant_derive_err = derivingThingErr clas tys tycon tyvars_to_keep
-                               (ptext SLIT("too hard for cunning newtype deriving"))
+                               (vcat [ptext SLIT("too hard for cunning newtype deriving"),
+                                       ppr n_tyvars_to_keep,
+                                       ppr n_args_to_keep,
+                                       ppr eta_ok,
+                                       ppr (isRecursiveTyCon tycon)
+                                     ])
 
     bale_out err = addErrTc err `thenM_` returnM (Nothing, Nothing) 
 
@@ -552,9 +589,8 @@ extend_inst_env dflags inst_env new_dfuns
        -- They'll appear later, when we do the top-level extendInstEnvs
 
 mk_deriv_dfun (dfun_name, clas, tycon, tyvars, _) theta
-  = mkDictFunId dfun_name clas tyvars 
-               [mkTyConApp tycon (mkTyVarTys tyvars)] 
-               theta
+  = mkDictFunId dfun_name tyvars theta
+               clas [mkTyConApp tycon (mkTyVarTys tyvars)] 
 \end{code}
 
 %************************************************************************
index ec0e3b8..5d53dae 100644 (file)
@@ -6,6 +6,7 @@ module TcEnv(
        tcGetInstEnv, tcSetInstEnv, 
        InstInfo(..), pprInstInfo, pprInstInfoDetails,
        simpleInstInfoTy, simpleInstInfoTyCon, 
+       InstBindings(..),
 
        -- Global environment
        tcExtendGlobalEnv, 
@@ -572,19 +573,25 @@ as well as explicit user written ones.
 data InstInfo
   = InstInfo {
       iDFunId :: DFunId,               -- The dfun id
-      iBinds  :: RenamedMonoBinds,     -- Bindings, b
-      iPrags  :: [RenamedSig]          -- User pragmas recorded for generating specialised instances
+      iBinds  :: InstBindings
     }
 
-  | NewTypeDerived {           -- Used for deriving instances of newtypes, where the
-                               -- witness dictionary is identical to the argument dictionary
-                               -- Hence no bindings.
-      iDFunId :: DFunId                        -- The dfun id
-    }
+data InstBindings
+  = VanillaInst                -- The normal case
+       RenamedMonoBinds        -- Bindings
+       [RenamedSig]            -- User pragmas recorded for generating 
+                               -- specialised instances
+
+  | NewTypeDerived             -- Used for deriving instances of newtypes, where the
+       [Type]                  -- witness dictionary is identical to the argument 
+                               -- dictionary.  Hence no bindings, no pragmas
+       -- The [Type] are the representation types
+       -- See notes in TcDeriv
 
 pprInstInfo info = vcat [ptext SLIT("InstInfo:") <+> ppr (idType (iDFunId info))]
-pprInstInfoDetails (InstInfo { iBinds = b }) = ppr b
-pprInstInfoDetails (NewTypeDerived _)       = text "Derived from the represenation type"
+
+pprInstInfoDetails (InstInfo { iBinds = VanillaInst b _ }) = ppr b
+pprInstInfoDetails (InstInfo { iBinds = NewTypeDerived _}) = text "Derived from the represenation type"
 
 simpleInstInfoTy :: InstInfo -> Type
 simpleInstInfoTy info = case tcSplitDFunTy (idType (iDFunId info)) of
index bd31533..61edc1c 100644 (file)
@@ -44,7 +44,7 @@ import TcMType                ( tcInstTyVars, tcInstType, newHoleTyVarTy, zapToType,
                          newTyVarTy, newTyVarTys, zonkTcType, readHoleResult )
 import TcType          ( TcType, TcSigmaType, TcRhoType, TyVarDetails(VanillaTv),
                          tcSplitFunTys, tcSplitTyConApp, mkTyVarTys,
-                         isSigmaTy, isTauTy, mkFunTy, mkFunTys,
+                         isSigmaTy, mkFunTy, mkFunTys,
                          mkTyConApp, mkClassPred, tcFunArgTy,
                          tyVarsOfTypes, isLinearPred,
                          liftedTypeKind, openTypeKind, 
@@ -54,7 +54,7 @@ import TcType         ( TcType, TcSigmaType, TcRhoType, TyVarDetails(VanillaTv),
 import FieldLabel      ( FieldLabel, fieldLabelName, fieldLabelType, fieldLabelTyCon )
 import Id              ( Id, idType, recordSelectorFieldLabel, isRecordSelector, isDataConWrapId_maybe )
 import DataCon         ( DataCon, dataConFieldLabels, dataConSig, dataConStrictMarks )
-import Name            ( Name, isExternalName )
+import Name            ( Name )
 import TyCon           ( TyCon, tyConTyVars, tyConTheta, isAlgTyCon, tyConDataCons )
 import Subst           ( mkTopTyVarSubst, substTheta, substTy )
 import VarSet          ( emptyVarSet, elemVarSet )
@@ -874,8 +874,8 @@ tcId name   -- Look up the Id and instantiate its type
        | want_method_inst fun_ty
        = tcInstType VanillaTv fun_ty           `thenM` \ (tyvars, theta, tau) ->
          newMethodWithGivenTy orig fun_id 
-               (mkTyVarTys tyvars) theta tau   `thenM` \ meth ->
-         loop (HsVar (instToId meth)) tau
+               (mkTyVarTys tyvars) theta tau   `thenM` \ meth_id ->
+         loop (HsVar meth_id) tau
 
     loop fun fun_ty 
        | isSigmaTy fun_ty
index 99dba4c..b9cf1eb 100644 (file)
@@ -28,29 +28,30 @@ import TcRnMonad
 import TcMType         ( tcInstType, checkValidTheta, checkValidInstHead, instTypeErr, 
                          checkAmbiguity, UserTypeCtxt(..), SourceTyCtxt(..) )
 import TcType          ( mkClassPred, mkTyVarTy, tcSplitForAllTys, tyVarsOfType,
-                         tcSplitSigmaTy, getClassPredTys, tcSplitPredTy_maybe,
+                         tcSplitSigmaTy, getClassPredTys, tcSplitPredTy_maybe, mkTyVarTys,
                          TyVarDetails(..)
                        )
-import Inst            ( InstOrigin(..), newDicts, instToId, showLIE )
+import Inst            ( InstOrigin(..), newMethod, newMethodAtLoc, 
+                         newDicts, instToId, showLIE )
 import TcDeriv         ( tcDeriving )
-import TcEnv           ( tcExtendGlobalValEnv, tcExtendLocalValEnv2,
+import TcEnv           ( tcExtendGlobalValEnv, 
                          tcLookupClass, tcExtendTyVarEnv2,
                          tcExtendInstEnv, tcExtendLocalInstEnv, tcLookupGlobalId,
-                         InstInfo(..), pprInstInfo, simpleInstInfoTyCon, 
+                         InstInfo(..), InstBindings(..), pprInstInfo, simpleInstInfoTyCon, 
                          simpleInstInfoTy, newDFunName
                        )
 import PprType         ( pprClassPred )
-import TcMonoType      ( tcSigPolyId, tcHsTyVars, kcHsSigType, tcHsType, tcHsSigType )
+import TcMonoType      ( tcHsTyVars, kcHsSigType, tcHsType, tcHsSigType )
 import TcUnify         ( checkSigTyVars )
 import TcSimplify      ( tcSimplifyCheck, tcSimplifyTop )
 import HscTypes                ( DFunId )
-import Subst           ( mkTyVarSubst, substTheta )
+import Subst           ( mkTyVarSubst, substTheta, substTy )
 import DataCon         ( classDataCon )
 import Class           ( Class, classBigSig )
 import Var             ( idName, idType )
 import NameSet         
 import Id              ( setIdLocalExported )
-import MkId            ( mkDictFunId, unsafeCoerceId, rUNTIME_ERROR_ID )
+import MkId            ( mkDictFunId, rUNTIME_ERROR_ID )
 import FunDeps         ( checkInstFDs )
 import Generics                ( validGenericInstanceType )
 import Name            ( getSrcLoc )
@@ -59,7 +60,7 @@ import TyCon          ( TyCon )
 import TysWiredIn      ( genericTyCons )
 import SrcLoc           ( SrcLoc )
 import Unique          ( Uniquable(..) )
-import Util             ( lengthExceeds, isSingleton )
+import Util             ( lengthExceeds )
 import BasicTypes      ( NewOrData(..) )
 import UnicodeUtil     ( stringToUtf8 )
 import ErrUtils                ( dumpIfSet_dyn )
@@ -237,8 +238,8 @@ tcLocalInstDecl1 decl@(InstDecl poly_ty binds uprags Nothing src_loc)
     checkTc (checkInstFDs theta clas inst_tys)
            (instTypeErr (pprClassPred clas inst_tys) msg)      `thenM_`
     newDFunName clas inst_tys src_loc                          `thenM` \ dfun_name ->
-    returnM (Just (InstInfo { iDFunId = mkDictFunId dfun_name clas tyvars inst_tys theta,
-                              iBinds = binds, iPrags = uprags }))
+    returnM (Just (InstInfo { iDFunId = mkDictFunId dfun_name tyvars theta clas inst_tys,
+                             iBinds = VanillaInst binds uprags }))
   where
     msg  = parens (ptext SLIT("the instance types do not agree with the functional dependencies of the class"))
 \end{code}
@@ -394,10 +395,10 @@ mkGenericInstance clas loc (hs_ty, binds)
     newDFunName clas [inst_ty] loc             `thenM` \ dfun_name ->
     let
        inst_theta = [mkClassPred clas [mkTyVarTy tv] | tv <- tyvars]
-       dfun_id    = mkDictFunId dfun_name clas tyvars [inst_ty] inst_theta
+       dfun_id    = mkDictFunId dfun_name tyvars inst_theta clas [inst_ty]
     in
 
-    returnM (InstInfo { iDFunId = dfun_id, iBinds = binds, iPrags = [] })
+    returnM (InstInfo { iDFunId = dfun_id, iBinds = VanillaInst binds [] })
 \end{code}
 
 
@@ -484,25 +485,7 @@ First comes the easy case of a non-local instance decl.
 \begin{code}
 tcInstDecl2 :: InstInfo -> TcM TcMonoBinds
 
-tcInstDecl2 (NewTypeDerived { iDFunId = dfun_id })
-  = tcInstType InstTv (idType dfun_id)         `thenM` \ (inst_tyvars', dfun_theta', inst_head') ->
-    newDicts InstanceDeclOrigin dfun_theta'    `thenM` \ rep_dicts ->
-    let
-       rep_dict_id = ASSERT( isSingleton rep_dicts )
-                     instToId (head rep_dicts)         -- Derived newtypes have just one dict arg
-
-       body = TyLam inst_tyvars'    $
-              DictLam [rep_dict_id] $
-               (HsVar unsafeCoerceId `TyApp` [idType rep_dict_id, inst_head'])
-                         `HsApp` 
-               (HsVar rep_dict_id)
-       -- You might wonder why we have the 'coerce'.  It's because the
-       -- type equality mechanism isn't clever enough; see comments with Type.eqType.
-       -- So Lint complains if we don't have this. 
-    in
-    returnM (VarMonoBind dfun_id body)
-
-tcInstDecl2 (InstInfo { iDFunId = dfun_id, iBinds = monobinds, iPrags = uprags })
+tcInstDecl2 (InstInfo { iDFunId = dfun_id, iBinds = binds })
   =     -- Prime error recovery
     recoverM (returnM EmptyMonoBinds)  $
     addSrcLoc (getSrcLoc dfun_id)                              $
@@ -533,34 +516,31 @@ tcInstDecl2 (InstInfo { iDFunId = dfun_id, iBinds = monobinds, iPrags = uprags }
                -- Default-method Ids may be mentioned in synthesised RHSs,
                -- but they'll already be in the environment.
 
-        -- Check that all the method bindings come from this class
-    mkMethodBinds clas inst_tys' op_items monobinds `thenM` \ (meth_insts, meth_infos) ->
-
-    let                 -- These insts are in scope; quite a few, eh?
-       avail_insts = [this_dict] ++ dfun_arg_dicts ++
-                     sc_dicts    ++ meth_insts
-
-       xtve    = inst_tyvars `zip` inst_tyvars'
-       tc_meth = tcMethodBind xtve inst_tyvars' dfun_theta' avail_insts uprags
+       ------------------
+       -- Typecheck the methods
+    let                -- These insts are in scope; quite a few, eh?
+       avail_insts = [this_dict] ++ dfun_arg_dicts ++ sc_dicts
     in
-    mappM tc_meth meth_infos           `thenM` \ meth_binds_s ->
+    tcMethods clas inst_tyvars inst_tyvars' 
+             dfun_theta' inst_tys' avail_insts 
+             op_items binds            `thenM` \ (meth_ids, meth_binds) ->
 
        -- Figure out bindings for the superclass context
     tcSuperClasses inst_tyvars' dfun_arg_dicts sc_dicts        
                `thenM` \ (zonked_inst_tyvars, sc_binds_inner, sc_binds_outer) ->
 
-       -- Deal with SPECIALISE instance pragmas by making them
+       -- Deal with 'SPECIALISE instance' pragmas by making them
        -- look like SPECIALISE pragmas for the dfun
     let
+       uprags = case binds of
+                      VanillaInst _ uprags -> uprags
+                      other                -> []
        spec_prags = [ SpecSig (idName dfun_id) ty loc
-                    | SpecInstSig ty loc <- uprags] 
+                    | SpecInstSig ty loc <- uprags ]
+       xtve = inst_tyvars `zip` inst_tyvars'
     in
-     
     tcExtendGlobalValEnv [dfun_id] (
-       tcExtendTyVarEnv2 xtve                                  $
-       tcExtendLocalValEnv2 [(idName sel_id, tcSigPolyId sig) 
-                            | (sel_id, sig, _) <- meth_infos]  $
-               -- Map sel_id to the local method name we are using
+       tcExtendTyVarEnv2 xtve          $
        tcSpecSigs spec_prags
     )                                  `thenM` \ prag_binds ->
 
@@ -570,7 +550,7 @@ tcInstDecl2 (InstInfo { iDFunId = dfun_id, iBinds = monobinds, iPrags = uprags }
                -- Reason for setIdLocalExported: see notes with MkId.mkDictFunId
 
         dict_constr   = classDataCon clas
-       scs_and_meths = map instToId (sc_dicts ++ meth_insts)
+       scs_and_meths = map instToId sc_dicts ++ meth_ids
        this_dict_id  = instToId this_dict
        inlines       | null dfun_arg_dicts = emptyNameSet
                      | otherwise           = unitNameSet (idName dfun_id)
@@ -582,6 +562,8 @@ tcInstDecl2 (InstInfo { iDFunId = dfun_id, iBinds = monobinds, iPrags = uprags }
                -- BUT: don't inline it if it's a constant dictionary;
                -- we'll get all the benefit without inlining, and we get
                -- a **lot** of code duplication if we inline it
+               --
+               --      See Note [Inline dfuns] below
 
        dict_rhs
          | null scs_and_meths
@@ -607,7 +589,6 @@ tcInstDecl2 (InstInfo { iDFunId = dfun_id, iBinds = monobinds, iPrags = uprags }
            msg = "Compiler error: bad dictionary " ++ showSDoc (ppr clas)
 
        dict_bind  = VarMonoBind this_dict_id dict_rhs
-       meth_binds = andMonoBindList meth_binds_s
        all_binds  = sc_binds_inner `AndMonoBinds` meth_binds `AndMonoBinds` dict_bind
 
        main_bind = AbsBinds
@@ -618,10 +599,64 @@ tcInstDecl2 (InstInfo { iDFunId = dfun_id, iBinds = monobinds, iPrags = uprags }
     in
     showLIE "instance"                 `thenM_`
     returnM (main_bind `AndMonoBinds` prag_binds `AndMonoBinds` sc_binds_outer)
+
+
+tcMethods clas inst_tyvars inst_tyvars' dfun_theta' inst_tys' 
+         avail_insts op_items (VanillaInst monobinds uprags)
+  =    -- Check that all the method bindings come from this class
+    let
+       sel_names = [idName sel_id | (sel_id, _) <- op_items]
+       bad_bndrs = collectMonoBinders monobinds `minusList` sel_names
+    in
+    mappM (addErrTc . badMethodErr clas) bad_bndrs     `thenM_`
+
+       -- Make the method bindings
+    mapAndUnzipM do_one op_items                       `thenM` \ (meth_ids, meth_binds_s) ->
+   
+    returnM (meth_ids, andMonoBindList meth_binds_s)
+
+  where
+    xtve = inst_tyvars `zip` inst_tyvars'
+    do_one op_item 
+       = mkMethodBind InstanceDeclOrigin clas 
+                      inst_tys' monobinds op_item      `thenM` \ (meth_inst, meth_info) ->
+         tcMethodBind xtve inst_tyvars' dfun_theta' 
+                      avail_insts uprags meth_info     `thenM` \ meth_bind ->
+               -- Could add meth_insts to avail_insts, but not worth the bother
+         returnM (instToId meth_inst, meth_bind)
+
+-- Derived newtype instances
+tcMethods clas inst_tyvars inst_tyvars' dfun_theta' inst_tys' 
+         avail_insts op_items (NewTypeDerived rep_tys)
+  = getInstLoc InstanceDeclOrigin                      `thenM` \ inst_loc ->
+    getLIE (mapAndUnzipM (do_one inst_loc) op_items)   `thenM` \ ((meth_ids, meth_binds), lie) ->
+    
+    tcSimplifyCheck
+        (ptext SLIT("newtype derived instance"))
+        inst_tyvars' avail_insts lie                   `thenM` \ lie_binds ->
+
+       -- I don't think we have to do the checkSigTyVars thing
+
+    returnM (meth_ids, lie_binds `AndMonoBinds` andMonoBindList meth_binds)
+
+  where
+    do_one inst_loc (sel_id, _)
+       = newMethodAtLoc inst_loc sel_id inst_tys'      `thenM` \ meth_inst ->
+               -- Like in mkMethodBind
+         newMethod InstanceDeclOrigin sel_id rep_tys'  `thenM` \ rhs_id ->
+               -- The binding is like "op @ NewTy = op @ RepTy"
+         let
+            meth_id = instToId meth_inst
+         in
+         return (meth_id, VarMonoBind meth_id (HsVar rhs_id))
+
+       -- Instantiate rep_tys with the relevant type variables
+    rep_tys' = map (substTy subst) rep_tys
+    subst    = mkTyVarSubst inst_tyvars (mkTyVarTys inst_tyvars')
 \end{code}
 
-Superclass loops
-~~~~~~~~~~~~~~~~
+Note: [Superclass loops]
+~~~~~~~~~~~~~~~~~~~~~~~~~
 We have to be very, very careful when generating superclasses, lest we
 accidentally build a loop. Here's an example:
 
@@ -673,7 +708,7 @@ tcSuperClasses inst_tyvars' dfun_arg_dicts sc_dicts
 
        -- We must simplify this all the way down 
        -- lest we build superclass loops
-       -- See notes about superclass loops above
+       -- See Note [Superclass loops] above
     tcSimplifyTop sc_lie               `thenM` \ sc_binds2 ->
 
     returnM (zonked_inst_tyvars, sc_binds1, sc_binds2)
@@ -682,26 +717,9 @@ tcSuperClasses inst_tyvars' dfun_arg_dicts sc_dicts
     doc = ptext SLIT("instance declaration superclass context")
 \end{code}
 
-\begin{code}
-mkMethodBinds clas inst_tys' op_items monobinds
-  =     -- Check that all the method bindings come from this class
-    mappM (addErrTc . badMethodErr clas) bad_bndrs     `thenM_`
-
-       -- Make the method bindings
-    mapAndUnzipM mk_method_bind op_items
-
-  where
-    mk_method_bind op_item = mkMethodBind InstanceDeclOrigin clas 
-                                         inst_tys' monobinds op_item 
-
-       -- Find any definitions in monobinds that aren't from the class
-    sel_names = [idName sel_id | (sel_id, _) <- op_items]
-    bad_bndrs = collectMonoBinders monobinds `minusList` sel_names
-\end{code}
-
 
                ------------------------------
-               Inlining dfuns unconditionally
+       [Inline dfuns] Inlining dfuns unconditionally
                ------------------------------
 
 The code above unconditionally inlines dict funs.  Here's why.