Extend TyCons and DataCons to represent data instance decls
[ghc-hetmet.git] / compiler / typecheck / TcInstDcls.lhs
index 45338d0..2a51661 100644 (file)
@@ -10,26 +10,32 @@ module TcInstDcls ( tcInstDecls1, tcInstDecls2 ) where
 
 import HsSyn
 import TcBinds         ( mkPragFun, tcPrags, badBootDeclErr )
+import TcTyClsDecls     ( tcIdxTyInstDecl )
 import TcClassDcl      ( tcMethodBind, mkMethodBind, badMethodErr, 
                          tcClassDecl2, getGenericInstances )
 import TcRnMonad       
 import TcMType         ( tcSkolSigType, checkValidInstance, checkValidInstHead )
-import TcType          ( mkClassPred, tcSplitSigmaTy, tcSplitDFunHead, mkTyVarTys,
-                         SkolemInfo(InstSkol), tcSplitDFunTy )
-import Inst            ( tcInstClassOp, newDicts, instToId, showLIE, 
+import TcType          ( mkClassPred, tcSplitSigmaTy, tcSplitDFunHead, 
+                          SkolemInfo(InstSkol), tcSplitDFunTy, mkFunTy )
+import Inst            ( newDictBndr, newDictBndrs, instToId, showLIE, 
                          getOverlapFlag, tcExtendLocalInstEnv )
 import InstEnv         ( mkLocalInstance, instanceDFunId )
 import TcDeriv         ( tcDeriving )
 import TcEnv           ( InstInfo(..), InstBindings(..), 
-                         newDFunName, tcExtendIdEnv
+                         newDFunName, tcExtendIdEnv, tcExtendGlobalEnv
                        )
 import TcHsType                ( kcHsSigType, tcHsKindedType )
 import TcUnify         ( checkSigTyVars )
-import TcSimplify      ( tcSimplifyCheck, tcSimplifySuperClasses )
-import Type            ( zipOpenTvSubst, substTheta, substTys )
-import DataCon         ( classDataCon )
+import TcSimplify      ( tcSimplifySuperClasses )
+import Type            ( zipOpenTvSubst, substTheta, mkTyConApp, mkTyVarTy,
+                          splitFunTys, TyThing )
+import Coercion         ( mkSymCoercion )
+import TyCon            ( TyCon, newTyConCo, tyConTyVars )
+import DataCon         ( classDataCon, dataConTyCon, dataConInstArgTys )
 import Class           ( classBigSig )
-import Var             ( Id, idName, idType )
+import Var             ( TyVar, Id, idName, idType, tyVarKind )
+import Id               ( mkSysLocal )
+import UniqSupply       ( uniqsFromSupply, splitUniqSupply )
 import MkId            ( mkDictFunId )
 import Name            ( Name, getSrcLoc )
 import Maybe           ( catMaybes )
@@ -38,6 +44,7 @@ import ListSetOps     ( minusList )
 import Outputable
 import Bag
 import BasicTypes      ( Activation( AlwaysActive ), InlineSpec(..) )
+import HscTypes                ( implicitTyThings )
 import FastString
 \end{code}
 
@@ -51,7 +58,6 @@ pass, when the class-instance envs and GVE contain all the info from
 all the instance and value decls.  Indeed that's the reason we need
 two passes over the instance decls.
 
-
 Here is the overall algorithm.
 Assume that we have an instance declaration
 
@@ -134,35 +140,52 @@ tcInstDecls1      -- Deal with both source-code and imported instance decls
 
 tcInstDecls1 tycl_decls inst_decls
   = checkNoErrs $
-       -- Stop if addInstInfos etc discovers any errors
-       -- (they recover, so that we get more than one error each round)
-
-       -- (1) Do the ordinary instance declarations
-    mappM tcLocalInstDecl1 inst_decls    `thenM` \ local_inst_infos ->
-
-    let
-       local_inst_info = catMaybes local_inst_infos
-       clas_decls      = filter (isClassDecl.unLoc) tycl_decls
-    in
-       -- (2) Instances from generic class declarations
-    getGenericInstances clas_decls     `thenM` \ generic_inst_info -> 
-
-       -- Next, construct the instance environment so far, consisting of
-       --      a) local instance decls
-       --      b) generic instances
-    addInsts local_inst_info   $
-    addInsts generic_inst_info $
-
-       -- (3) Compute instances from "deriving" clauses; 
-       -- This stuff computes a context for the derived instance decl, so it
-       -- needs to know about all the instances possible; hence inst_env4
-    tcDeriving tycl_decls      `thenM` \ (deriv_inst_info, deriv_binds) ->
-    addInsts deriv_inst_info   $
-
-    getGblEnv                  `thenM` \ gbl_env ->
-    returnM (gbl_env, 
-            generic_inst_info ++ deriv_inst_info ++ local_inst_info,
-            deriv_binds)
+    do {        -- Stop if addInstInfos etc discovers any errors
+               -- (they recover, so that we get more than one error each
+               -- round) 
+
+               -- (1) Do the ordinary instance declarations and instances of
+               --     indexed types
+       ; let { idxty_decls = filter (isIdxTyDecl . unLoc) tycl_decls }
+       ; local_info_tycons <- mappM tcLocalInstDecl1 inst_decls
+       ; idxty_info_tycons <- mappM tcIdxTyInstDecl idxty_decls
+
+       ; let { (local_infos,
+               local_tycons)    = unzip local_info_tycons
+            ; (idxty_infos, 
+               idxty_tycons)    = unzip idxty_info_tycons
+            ; local_idxty_info  = concat local_infos ++ catMaybes idxty_infos
+            ; local_idxty_tycon = concat local_tycons ++ 
+                                  catMaybes idxty_tycons
+            ; clas_decls        = filter (isClassDecl.unLoc) tycl_decls 
+            ; implicit_things   = concatMap implicitTyThings local_idxty_tycon
+            }
+
+               -- (2) Add the tycons of associated types and their implicit
+               --     tythings to the global environment
+       ; tcExtendGlobalEnv (local_idxty_tycon ++ implicit_things) $ do {
+
+               -- (3) Instances from generic class declarations
+       ; generic_inst_info <- getGenericInstances clas_decls
+
+               -- Next, construct the instance environment so far, consisting
+               -- of 
+               --   a) local instance decls
+               --   b) generic instances
+       ; addInsts local_idxty_info  $ do {
+       ; addInsts generic_inst_info $ do {
+
+               -- (4) Compute instances from "deriving" clauses; 
+               -- This stuff computes a context for the derived instance
+               -- decl, so it needs to know about all the instances possible
+       ; (deriv_inst_info, deriv_binds) <- tcDeriving tycl_decls
+       ; addInsts deriv_inst_info   $ do {
+
+       ; gbl_env <- getGblEnv
+       ; returnM (gbl_env, 
+                 generic_inst_info ++ deriv_inst_info ++ local_idxty_info,
+                 deriv_binds) 
+    }}}}}
 
 addInsts :: [InstInfo] -> TcM a -> TcM a
 addInsts infos thing_inside
@@ -171,14 +194,14 @@ addInsts infos thing_inside
 
 \begin{code}
 tcLocalInstDecl1 :: LInstDecl Name 
-                -> TcM (Maybe InstInfo)        -- Nothing if there was an error
+                -> TcM ([InstInfo], [TyThing]) -- [] if there was an error
        -- A source-file instance declaration
        -- Type-check all the stuff before the "where"
        --
        -- We check for respectable instance type, and context
-tcLocalInstDecl1 decl@(L loc (InstDecl poly_ty binds uprags))
+tcLocalInstDecl1 decl@(L loc (InstDecl poly_ty binds uprags ats))
   =    -- Prime error recovery, set source location
-    recoverM (returnM Nothing)         $
+    recoverM (returnM ([], []))                $
     setSrcSpan loc                     $
     addErrCtxt (instDeclCtxt1 poly_ty) $
 
@@ -192,15 +215,27 @@ tcLocalInstDecl1 decl@(L loc (InstDecl poly_ty binds uprags))
        ; poly_ty'  <- tcHsKindedType kinded_ty
        ; let (tyvars, theta, tau) = tcSplitSigmaTy poly_ty'
        
+       -- Now, check the validity of the instance.
        ; (clas, inst_tys) <- checkValidInstHead tau
        ; checkValidInstance tyvars theta clas inst_tys
 
+       -- Next, process any associated types.
+       ; idxty_info_tycons <- mappM tcIdxTyInstDecl ats
+
+       -- Finally, construct the Core representation of the instance.
+       -- (This no longer includes the associated types.)
        ; dfun_name <- newDFunName clas inst_tys (srcSpanStart loc)
        ; overlap_flag <- getOverlapFlag
-       ; let dfun  = mkDictFunId dfun_name tyvars theta clas inst_tys
-             ispec = mkLocalInstance dfun overlap_flag
-
-       ; return (Just (InstInfo { iSpec = ispec, iBinds = VanillaInst binds uprags })) }
+       ; let dfun           = mkDictFunId dfun_name tyvars theta clas inst_tys
+             ispec          = mkLocalInstance dfun overlap_flag
+             (idxty_infos, 
+              idxty_tycons) = unzip idxty_info_tycons
+
+       ; return ([InstInfo { iSpec  = ispec, 
+                             iBinds = VanillaInst binds uprags }] ++
+                  catMaybes idxty_infos,
+                 catMaybes idxty_tycons)
+        }
 \end{code}
 
 
@@ -303,8 +338,100 @@ First comes the easy case of a non-local instance decl.
 
 \begin{code}
 tcInstDecl2 :: InstInfo -> TcM (LHsBinds Id)
+-- Returns a binding for the dfun
 
-tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = binds })
+------------------------
+-- Derived newtype instances
+--
+-- We need to make a copy of the dictionary we are deriving from
+-- because we may need to change some of the superclass dictionaries
+-- see Note [Newtype deriving superclasses] in TcDeriv.lhs
+--
+-- In the case of a newtype, things are rather easy
+--     class Show a => Foo a b where ...
+--     newtype T a = MkT (Tree [a]) deriving( Foo Int )
+-- The newtype gives an FC axiom looking like
+--     axiom CoT a ::  T a :=: Tree [a]
+--
+-- So all need is to generate a binding looking like
+--     dfunFooT :: forall a. (Foo Int (Tree [a], Show (T a)) => Foo Int (T a)
+--     dfunFooT = /\a. \(ds:Show (T a)) (df:Foo (Tree [a])).
+--               case df `cast` (Foo Int (sym (CoT a))) of
+--                  Foo _ op1 .. opn -> Foo ds op1 .. opn
+
+tcInstDecl2 (InstInfo { iSpec = ispec, 
+                       iBinds = NewTypeDerived tycon rep_tys })
+  = do { let dfun_id      = instanceDFunId ispec 
+             rigid_info   = InstSkol dfun_id
+             origin       = SigOrigin rigid_info
+             inst_ty      = idType dfun_id
+       ; inst_loc <- getInstLoc origin
+       ; (tvs, theta, inst_head) <- tcSkolSigType rigid_info inst_ty
+       ; dicts <- newDictBndrs inst_loc theta
+        ; uniqs <- newUniqueSupply
+        ; let (cls, cls_inst_tys) = tcSplitDFunHead inst_head
+        ; this_dict <- newDictBndr inst_loc (mkClassPred cls rep_tys)
+        ; let (rep_dict_id:sc_dict_ids)
+                 | null dicts = [instToId this_dict]
+                | otherwise  = map instToId dicts
+
+               -- (Here, we are relying on the order of dictionary 
+               -- arguments built by NewTypeDerived in TcDeriv.)
+
+              wrap_fn = mkCoTyLams tvs <.> mkCoLams (rep_dict_id:sc_dict_ids)
+          
+                -- we need to find the kind that this class applies to
+                -- and drop trailing tvs appropriately
+              cls_kind = tyVarKind (head (reverse (tyConTyVars cls_tycon)))
+              the_tvs  = drop_tail (length (fst (splitFunTys cls_kind))) tvs
+
+              coerced_rep_dict = mkHsCoerce (co_fn the_tvs cls_tycon cls_inst_tys) (HsVar rep_dict_id)
+
+             body | null sc_dict_ids = coerced_rep_dict
+                  | otherwise = HsCase (noLoc coerced_rep_dict) $
+                                MatchGroup [the_match] (mkFunTy in_dict_ty inst_head)
+             in_dict_ty = mkTyConApp cls_tycon cls_inst_tys
+
+              the_match = mkSimpleMatch [noLoc the_pat] the_rhs
+             the_rhs = mkHsConApp cls_data_con cls_inst_tys (map HsVar (sc_dict_ids ++ op_ids))
+
+             (uniqs1, uniqs2) = splitUniqSupply uniqs
+
+             op_ids = zipWith (mkSysLocal FSLIT("op"))
+                                     (uniqsFromSupply uniqs1) op_tys
+
+              dict_ids = zipWith (mkSysLocal FSLIT("dict"))
+                          (uniqsFromSupply uniqs2) (map idType sc_dict_ids)
+
+             the_pat = ConPatOut { pat_con = noLoc cls_data_con, pat_tvs = [],
+                                   pat_dicts = dict_ids,
+                                   pat_binds = emptyLHsBinds,
+                                   pat_args = PrefixCon (map nlVarPat op_ids),
+                                   pat_ty = in_dict_ty} 
+
+              cls_data_con = classDataCon cls
+              cls_tycon    = dataConTyCon cls_data_con
+              cls_arg_tys  = dataConInstArgTys cls_data_con cls_inst_tys 
+              
+              n_dict_args = if length dicts == 0 then 0 else length dicts - 1
+              op_tys = drop n_dict_args cls_arg_tys
+              
+              dict    = mkHsCoerce wrap_fn body
+        ; return (unitBag (noLoc $ VarBind dfun_id (noLoc dict))) }
+  where
+       -- For newtype T a = MkT <ty>
+       -- The returned coercion has kind :: C (T a):=:C <ty>
+    co_fn tvs cls_tycon cls_inst_tys | Just co_con <- newTyConCo tycon
+          = ExprCoFn (mkTyConApp cls_tycon (drop_tail 1 cls_inst_tys ++
+                      [mkSymCoercion (mkTyConApp co_con (map mkTyVarTy tvs))]))
+          | otherwise
+          = idCoercion
+    drop_tail n l = take (length l - n) l
+
+------------------------
+-- Ordinary instances
+
+tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = VanillaInst monobinds uprags })
   = let 
        dfun_id    = instanceDFunId ispec
        rigid_info = InstSkol dfun_id
@@ -329,9 +456,11 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = binds })
        origin    = SigOrigin rigid_info
     in
         -- Create dictionary Ids from the specified instance contexts.
-    newDicts InstScOrigin sc_theta'                    `thenM` \ sc_dicts ->
-    newDicts origin dfun_theta'                                `thenM` \ dfun_arg_dicts ->
-    newDicts origin [mkClassPred clas inst_tys']       `thenM` \ [this_dict] ->
+    getInstLoc InstScOrigin                            `thenM` \ sc_loc -> 
+    newDictBndrs sc_loc sc_theta'                      `thenM` \ sc_dicts ->
+    getInstLoc origin                                  `thenM` \ inst_loc -> 
+    newDictBndrs inst_loc dfun_theta'                  `thenM` \ dfun_arg_dicts ->
+    newDictBndr inst_loc (mkClassPred clas inst_tys')  `thenM` \ this_dict ->
                -- Default-method Ids may be mentioned in synthesised RHSs,
                -- but they'll already be in the environment.
 
@@ -341,7 +470,7 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = binds })
     in
     tcMethods origin clas inst_tyvars' 
              dfun_theta' inst_tys' avail_insts 
-             op_items binds            `thenM` \ (meth_ids, meth_binds) ->
+             op_items monobinds uprags         `thenM` \ (meth_ids, meth_binds) ->
 
        -- Figure out bindings for the superclass context
        -- Don't include this_dict in the 'givens', else
@@ -356,12 +485,7 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = binds })
     checkSigTyVars inst_tyvars'        `thenM_`
 
        -- Deal with 'SPECIALISE instance' pragmas 
-    let
-       specs = case binds of
-                 VanillaInst _ prags -> filter isSpecInstLSig prags
-                 other               -> []
-    in
-    tcPrags dfun_id specs                      `thenM` \ prags -> 
+    tcPrags dfun_id (filter isSpecInstLSig uprags)     `thenM` \ prags -> 
     
        -- Create the result bindings
     let
@@ -405,7 +529,7 @@ tcInstDecl2 (InstInfo { iSpec = ispec, iBinds = binds })
 
 
 tcMethods origin clas inst_tyvars' dfun_theta' inst_tys' 
-         avail_insts op_items (VanillaInst monobinds uprags)
+         avail_insts op_items monobinds uprags
   =    -- Check that all the method bindings come from this class
     let
        sel_names = [idName sel_id | (sel_id, _) <- op_items]
@@ -451,48 +575,16 @@ tcMethods origin clas inst_tyvars' dfun_theta' inst_tys'
     let
        prag_fn        = mkPragFun uprags
        all_insts      = avail_insts ++ catMaybes meth_insts
-       tc_method_bind = tcMethodBind inst_tyvars' dfun_theta' all_insts prag_fn
+       sig_fn n       = Just []        -- No scoped type variables, but every method has
+                                       -- a type signature, in effect, so that we check
+                                       -- the method has the right type
+       tc_method_bind = tcMethodBind inst_tyvars' dfun_theta' all_insts sig_fn prag_fn
        meth_ids       = [meth_id | (_,meth_id,_) <- meth_infos]
     in
 
     mapM tc_method_bind meth_infos             `thenM` \ meth_binds_s ->
    
     returnM (meth_ids, unionManyBags meth_binds_s)
-
-
--- Derived newtype instances
-tcMethods origin clas inst_tyvars' dfun_theta' inst_tys' 
-         avail_insts op_items (NewTypeDerived rep_tys)
-  = getInstLoc origin                          `thenM` \ inst_loc ->
-    mapAndUnzip3M (do_one inst_loc) op_items   `thenM` \ (meth_ids, meth_binds, rhs_insts) ->
-    
-    tcSimplifyCheck
-        (ptext SLIT("newtype derived instance"))
-        inst_tyvars' avail_insts rhs_insts     `thenM` \ lie_binds ->
-
-       -- I don't think we have to do the checkSigTyVars thing
-
-    returnM (meth_ids, lie_binds `unionBags` listToBag meth_binds)
-
-  where
-    do_one inst_loc (sel_id, _)
-       = -- The binding is like "op @ NewTy = op @ RepTy"
-               -- Make the *binder*, like in mkMethodBind
-         tcInstClassOp inst_loc sel_id inst_tys'       `thenM` \ meth_inst ->
-
-               -- Make the *occurrence on the rhs*
-         tcInstClassOp inst_loc sel_id rep_tys'        `thenM` \ rhs_inst ->
-         let
-            meth_id = instToId meth_inst
-         in
-         return (meth_id, noLoc (VarBind meth_id (nlHsVar (instToId rhs_inst))), rhs_inst)
-
-       -- Instantiate rep_tys with the relevant type variables
-       -- This looks a bit odd, because inst_tyvars' are the skolemised version
-       -- of the type variables in the instance declaration; but rep_tys doesn't
-       -- have the skolemised version, so we substitute them in here
-    rep_tys' = substTys subst rep_tys
-    subst    = zipOpenTvSubst inst_tyvars' (mkTyVarTys inst_tyvars')
 \end{code}